/* This file is part of VoltDB. * Copyright (C) 2008-2010 VoltDB L.L.C. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package org.voltdb.benchmark.dedupe; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.Calendar; import java.util.Date; import org.voltdb.VoltTable; import org.voltdb.client.ClientFactory; import org.voltdb.client.ClientResponse; import org.voltdb.client.NoConnectionsException; import org.voltdb.client.ProcedureCallback; import edu.brown.hstore.HStoreConstants; import edu.brown.hstore.Hstoreservice.Status; public class ClientInsert { public static long min_execution_milliseconds = 999999999l; public static long max_execution_milliseconds = -1l; public static long tot_execution_milliseconds = 0; public static long tot_executions = 0; public static long tot_executions_latency = 0; public static long[] latency_counter = new long[] {0,0,0,0,0,0,0,0,0}; public static boolean checkLatency = false; static class AsyncCallback implements ProcedureCallback { @Override public synchronized void clientCallback(ClientResponse clientResponse) { final Status status = clientResponse.getStatus(); if (status != Status.OK) { System.err.println("Failed to execute!!!"); System.err.println(clientResponse.getStatusString()); System.err.println(clientResponse.getException()); System.exit(-1); } else { tot_executions++; if (checkLatency) { pClientCallback(clientResponse.getResults(), clientResponse.getClientRoundtrip()); } } } protected void pClientCallback(VoltTable[] vtResults, int clientRoundtrip) { long called_time_milliseconds = vtResults[0].fetchRow(0).getLong(0); long current_time_milliseconds = System.currentTimeMillis(); long execution_time = current_time_milliseconds - called_time_milliseconds; tot_executions_latency++; tot_execution_milliseconds += execution_time; if (execution_time < min_execution_milliseconds) { min_execution_milliseconds = execution_time; } if (execution_time > max_execution_milliseconds) { max_execution_milliseconds = execution_time; } // change latency to bucket int latency_bucket = (int) (execution_time / 25l); if (latency_bucket > 8) { latency_bucket = 8; } latency_counter[latency_bucket]++; }; } public static void main(String args[]) { //boolean backPressure = false; long transactions_per_second = Long.valueOf(args[0]); long transactions_per_milli = transactions_per_second / 1000l; long client_feedback_interval_secs = Long.valueOf(args[1]); long test_duration_secs = Long.valueOf(args[2]); int max_playerId = Integer.valueOf(args[3]); int max_gameId = Integer.valueOf(args[4]); long day_offset = Long.valueOf(args[5]); long lag_latency_seconds = Long.valueOf(args[6]); long lag_latency_millis = lag_latency_seconds * 1000l; long thisOutstanding = 0; long lastOutstanding = 0; String serverList = args[7]; int outputToFile = Integer.valueOf(args[8]); String outputFileName = "log-ClientRandom.log"; FileOutputStream foStatus; System.out.printf("Submitting %,d SP Calls/sec\n",transactions_per_second); System.out.printf("Feedback interval = %,d second(s)\n",client_feedback_interval_secs); System.out.printf("Running for %,d second(s)\n",test_duration_secs); System.out.printf("Max playerId = %,d\n",max_playerId); System.out.printf("Max gameId = %,d\n",max_gameId); System.out.printf("Offsetting insert timestamps by %d day(s)\n",day_offset); System.out.printf("Latency not recorded for %d second(s)\n",lag_latency_seconds); if (outputToFile == 1) { System.out.printf("Outputting to file %s\n",outputFileName); } else { System.out.printf("File output disabled.\n"); } long playerId; long gameId; long socialId = 1l; long clientId = 1l; long visitTimeMillis; long transactions_this_second = 0; long last_millisecond = System.currentTimeMillis(); long this_millisecond = System.currentTimeMillis(); long milliseconds_offset = day_offset * 1000l * 60 * 60 * 24; AsyncCallback callBack = new AsyncCallback(); final org.voltdb.client.Client voltclient = ClientFactory.createClient(); String[] voltServers = serverList.split(","); for (String thisServer : voltServers) { try { System.out.printf("Connecting to server: %s\n",thisServer); voltclient.createConnection(null, thisServer, HStoreConstants.DEFAULT_PORT, "program", "none"); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } // make random object totally random (set my milliseconds) so we can have multiple clients running simultaneously java.util.Random rand = new java.util.Random(); long startTime = System.currentTimeMillis(); long endTime = startTime + (1000l * test_duration_secs); long currentTime = startTime; long lastFeedbackTime = startTime; long num_sp_calls = 0; long startRecordingLatency = startTime + lag_latency_millis; int hourOfDay = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + 1; int minuteOfHour = Calendar.getInstance().get(Calendar.MINUTE) + 1; long nextHourCheck = -1; int timeLimitedMaxPlayerId = 1; while (endTime > currentTime) { num_sp_calls++; if (currentTime > nextHourCheck) { // check the hour of the day once per minute hourOfDay = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); minuteOfHour = Calendar.getInstance().get(Calendar.MINUTE); nextHourCheck = currentTime + (1000l * 60l); if (day_offset > 0) { // all player IDs allowed in system, backfilling yesterday data timeLimitedMaxPlayerId = max_playerId; System.out.printf("day_offset > 0, player pool governer disabled : hourLimitedMaxPlayerId = %d\n",timeLimitedMaxPlayerId); } else { // only allow 5% of total player pool per hour to enter the system timeLimitedMaxPlayerId = (int) (((hourOfDay + (minuteOfHour / 60.0)) * 5.0 / 100.0) * max_playerId); if (timeLimitedMaxPlayerId > max_playerId) { timeLimitedMaxPlayerId = max_playerId; } else if (timeLimitedMaxPlayerId < 1) { timeLimitedMaxPlayerId = 1; } System.out.printf("hourOfDay = %d : minuteOfHour = %d : hourLimitedMaxPlayerId = %d\n",hourOfDay,minuteOfHour,timeLimitedMaxPlayerId); } } playerId = rand.nextInt(timeLimitedMaxPlayerId); gameId = rand.nextInt(max_gameId); socialId = 1; clientId = 1l; visitTimeMillis = System.currentTimeMillis(); try { boolean queued = false; while (!queued) { queued = voltclient.callProcedure(callBack, "RecordHit", playerId, gameId, socialId, clientId, (visitTimeMillis - milliseconds_offset), visitTimeMillis); if (!queued) { try { voltclient.backpressureBarrier(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } } } catch (IOException e) { e.printStackTrace(); } transactions_this_second++; if (transactions_this_second >= transactions_per_milli) { this_millisecond = System.currentTimeMillis(); while (this_millisecond <= last_millisecond) { this_millisecond = System.currentTimeMillis(); } last_millisecond = this_millisecond; transactions_this_second = 0; } currentTime = System.currentTimeMillis(); if ((!checkLatency) && (currentTime >= startRecordingLatency)) { // time to start recording latency information checkLatency = true; } if (currentTime >= (lastFeedbackTime + (client_feedback_interval_secs * 1000))) { synchronized(callBack) { lastFeedbackTime = currentTime; long elapsedTimeMillis2 = System.currentTimeMillis()-startTime; float elapsedTimeSec2 = elapsedTimeMillis2/1000F; if (tot_executions_latency == 0) { tot_executions_latency = 1; } thisOutstanding = num_sp_calls - tot_executions; long runTimeMillis = endTime - startTime; double percentComplete = ((double) elapsedTimeMillis2 / (double) runTimeMillis) * 100; if (percentComplete > 100.0) { percentComplete = 100.0; } String currentDate = new Date().toString(); System.out.printf("[%s] %.3f%% Complete | SP Calls: %,d at %,.2f SP/sec | outstanding = %d (%d) | min = %d | max = %d | avg = %.2f\n",currentDate, percentComplete, num_sp_calls, (num_sp_calls / elapsedTimeSec2), thisOutstanding,(thisOutstanding - lastOutstanding), min_execution_milliseconds, max_execution_milliseconds, ((double) tot_execution_milliseconds / (double) tot_executions_latency)); if (outputToFile == 1) { try { foStatus = new FileOutputStream(outputFileName,true); new PrintStream(foStatus).printf("[%s] %.3f%% Complete | SP Calls: %,d at %,.2f SP/sec | outstanding = %d (%d) | min = %d | max = %d | avg = %.2f\n",currentDate, percentComplete, num_sp_calls, (num_sp_calls / elapsedTimeSec2), thisOutstanding,(thisOutstanding - lastOutstanding), min_execution_milliseconds, max_execution_milliseconds, ((double) tot_execution_milliseconds / (double) tot_executions_latency)); foStatus.close(); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } lastOutstanding = thisOutstanding; } } } try { voltclient.drain(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } long elapsedTimeMillis = System.currentTimeMillis()-startTime; float elapsedTimeSec = elapsedTimeMillis/1000F; System.out.println("\n"); System.out.println("*************************************************************************"); System.out.println("Checking results"); System.out.println("*************************************************************************"); System.out.printf(" - System ran for %12.4f seconds\n",elapsedTimeSec); System.out.printf(" - Performed %,d SP calls\n",num_sp_calls); System.out.printf(" - At %,.2f calls per second\n",num_sp_calls / elapsedTimeSec); System.out.printf(" - Average Latency = %.2f ms\n",((double) tot_execution_milliseconds / (double) tot_executions_latency)); System.out.printf(" - Latency 0ms - 25ms = %,d\n",latency_counter[0]); System.out.printf(" - Latency 25ms - 50ms = %,d\n",latency_counter[1]); System.out.printf(" - Latency 50ms - 75ms = %,d\n",latency_counter[2]); System.out.printf(" - Latency 75ms - 100ms = %,d\n",latency_counter[3]); System.out.printf(" - Latency 100ms - 125ms = %,d\n",latency_counter[4]); System.out.printf(" - Latency 125ms - 150ms = %,d\n",latency_counter[5]); System.out.printf(" - Latency 150ms - 175ms = %,d\n",latency_counter[6]); System.out.printf(" - Latency 175ms - 200ms = %,d\n",latency_counter[7]); System.out.printf(" - Latency 200ms+ = %,d\n",latency_counter[8]); try { voltclient.close(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } }