/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * 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 com; import org.voltdb.compiler.VoltProjectBuilder; import org.voltdb.client.Client; import org.voltdb.client.ClientResponse; import org.voltdb.client.ProcedureCallback; import org.voltdb.client.ClientFactory; import org.voltdb.client.NullCallback; import org.voltdb.VoltTable; import org.voltdb.VoltType; import org.voltdb.client.NoConnectionsException; import java.util.Date; import java.util.ArrayList; import java.util.*; import java.text.SimpleDateFormat; import java.util.Calendar; import java.io.IOException; import java.io.FileOutputStream; import java.io.PrintStream; import org.apache.log4j.Logger; public class ClientRandom { 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 final Logger m_logger = Logger.getLogger(ClientRandom.class.getName()); public static boolean checkLatency = false; static class AsyncCallback implements ProcedureCallback { @Override public synchronized void clientCallback(ClientResponse clientResponse) { final byte status = clientResponse.getStatus(); FileOutputStream foStatus; if (status != ClientResponse.SUCCESS) { m_logger.error("***AsyncCallback Issue : Failed to execute!!!"); m_logger.error(clientResponse.getStatusString()); m_logger.error(clientResponse.getException()); } else { tot_executions++; if (checkLatency) { pClientCallback(clientResponse.getResults(), clientResponse.getClientRoundtrip()); } } } protected void pClientCallback(VoltTable[] vtResults, int clientRoundtrip) { long execution_time = (long) clientRoundtrip; 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) Long.valueOf(args[0]); long transactions_per_milli = transactions_per_second / 1000l; long client_feedback_interval_secs = (long) Long.valueOf(args[1]); long test_duration_secs = (long) Long.valueOf(args[2]); int max_playerId = (int) Integer.valueOf(args[3]); int max_field1 = (int) Integer.valueOf(args[4]); long day_offset = (long) Long.valueOf(args[5]); long lag_latency_seconds = (long) Long.valueOf(args[6]); long lag_latency_millis = lag_latency_seconds * 1000l; long thisOutstanding = 0; long lastOutstanding = 0; String serverList = args[7]; long reset_latency_seconds = (long) Long.valueOf(args[8]); long reset_latency_millis = reset_latency_seconds * 1000l; m_logger.info(String.format("Submitting %,d SP Calls/sec",transactions_per_second)); m_logger.info(String.format("Feedback interval = %,d second(s)",client_feedback_interval_secs)); m_logger.info(String.format("Running for %,d second(s)",test_duration_secs)); m_logger.info(String.format("Max playerId = %,d",max_playerId)); m_logger.info(String.format("Max field1 = %,d",max_field1)); m_logger.info(String.format("Offsetting insert timestamps by %d day(s)",day_offset)); m_logger.info(String.format("Latency not recorded for %d second(s)",lag_latency_seconds)); m_logger.info(String.format("Resetting min/max/avg latency every %d second(s)",reset_latency_seconds)); long playerId; long field1; long field2 = 1l; long field3 = 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(); // create generic client final org.voltdb.client.Client voltclient = ClientFactory.createClient(); // create HEAVYWEIGHT client with expected message size of 128 bytes // final org.voltdb.client.Client voltclient = ClientFactory.createClient(128,null,true,null); String[] voltServers = serverList.split(","); for (String thisServer : voltServers) { try { thisServer = thisServer.trim(); m_logger.info(String.format("Connecting to server: %s",thisServer)); voltclient.createConnection(thisServer, "program", "none"); } catch (IOException e) { m_logger.error(e.toString()); 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; long nextLatencyReset = startTime + reset_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; m_logger.info(String.format("day_offset > 0, player pool governer disabled : hourLimitedMaxPlayerId = %d",timeLimitedMaxPlayerId)); } else { // only allow 5% of total player pool per hour to enter the system timeLimitedMaxPlayerId = (int) ((((double) hourOfDay + ((double) minuteOfHour / 60.0)) * 5.0 / 100.0) * (double) max_playerId); if (timeLimitedMaxPlayerId > max_playerId) { timeLimitedMaxPlayerId = max_playerId; } else if (timeLimitedMaxPlayerId < 1) { timeLimitedMaxPlayerId = 1; } m_logger.info(String.format("hourOfDay = %d : minuteOfHour = %d : hourLimitedMaxPlayerId = %d",hourOfDay,minuteOfHour,timeLimitedMaxPlayerId)); } } playerId = (long) rand.nextInt(timeLimitedMaxPlayerId); field1 = (long) rand.nextInt(max_field1); field2 = 1l; field3 = 1l; visitTimeMillis = System.currentTimeMillis(); try { voltclient.callProcedure(callBack, "RecordHit", playerId, field1, field2, field3, (visitTimeMillis - milliseconds_offset), visitTimeMillis); } catch (IOException e) { m_logger.error(e.toString()); System.exit(-1); } 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 >= nextLatencyReset) { synchronized(callBack) { nextLatencyReset = currentTime + reset_latency_millis; min_execution_milliseconds = 999999999l; max_execution_milliseconds = -1l; tot_execution_milliseconds = 0; tot_executions_latency = 0; m_logger.info("...Resetting latency min/max/avg"); } } 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(); m_logger.info(String.format("[%s] %.3f%% Complete | SP Calls: %,d at %,.2f SP/sec | outstanding = %d (%d) | min = %d | max = %d | avg = %.2f",currentDate, percentComplete, num_sp_calls, (num_sp_calls / elapsedTimeSec2), thisOutstanding,(thisOutstanding - lastOutstanding), min_execution_milliseconds, max_execution_milliseconds, (double) ((double) tot_execution_milliseconds / (double) tot_executions_latency))); lastOutstanding = thisOutstanding; } } } try { voltclient.drain(); } catch (InterruptedException e) { m_logger.error(e.toString()); System.exit(-1); } catch (NoConnectionsException e) { m_logger.error(e.toString()); System.exit(-1); } long elapsedTimeMillis = System.currentTimeMillis()-startTime; float elapsedTimeSec = elapsedTimeMillis/1000F; m_logger.info("*************************************************************************"); m_logger.info("Checking results"); m_logger.info("*************************************************************************"); m_logger.info(String.format(" - System ran for %12.4f seconds",elapsedTimeSec)); m_logger.info(String.format(" - Performed %,d SP calls",num_sp_calls)); m_logger.info(String.format(" - At %,.2f calls per second",num_sp_calls / elapsedTimeSec)); m_logger.info(String.format(" - Average Latency = %.2f ms",(double) ((double) tot_execution_milliseconds / (double) tot_executions_latency))); m_logger.info(String.format(" - Latency 0ms - 25ms = %,d",latency_counter[0])); m_logger.info(String.format(" - Latency 25ms - 50ms = %,d",latency_counter[1])); m_logger.info(String.format(" - Latency 50ms - 75ms = %,d",latency_counter[2])); m_logger.info(String.format(" - Latency 75ms - 100ms = %,d",latency_counter[3])); m_logger.info(String.format(" - Latency 100ms - 125ms = %,d",latency_counter[4])); m_logger.info(String.format(" - Latency 125ms - 150ms = %,d",latency_counter[5])); m_logger.info(String.format(" - Latency 150ms - 175ms = %,d",latency_counter[6])); m_logger.info(String.format(" - Latency 175ms - 200ms = %,d",latency_counter[7])); m_logger.info(String.format(" - Latency 200ms+ = %,d",latency_counter[8])); try { voltclient.close(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } }