public void run() { operations.initTimers(); try { SimpleClient sclient = null; ThriftClient tclient = null; JavaDriverClient jclient = null; switch (settings.mode.api) { case JAVA_DRIVER_NATIVE: jclient = settings.getJavaDriverClient(); break; case SIMPLE_NATIVE: sclient = settings.getSimpleNativeClient(); break; case THRIFT: case THRIFT_SMART: tclient = settings.getThriftClient(); break; default: throw new IllegalStateException(); } while (true) { Operation op = operations.next(); if (!op.ready(workManager, rateLimiter)) break; try { switch (settings.mode.api) { case JAVA_DRIVER_NATIVE: op.run(jclient); break; case SIMPLE_NATIVE: op.run(sclient); break; case THRIFT: case THRIFT_SMART: default: op.run(tclient); } } catch (Exception e) { if (output == null) { System.err.println(e.getMessage()); success = false; System.exit(-1); } e.printStackTrace(output); success = false; workManager.stop(); metrics.cancel(); return; } } } finally { done.countDown(); operations.closeTimers(); } }
// TODO : permit varying more than just thread count // TODO : vary thread count based on percentage improvement of previous increment, not by fixed // amounts private boolean runMulti(boolean auto, RateLimiter rateLimiter) { if (settings.command.targetUncertainty >= 0) output.println( "WARNING: uncertainty mode (err<) results in uneven workload between thread runs, so should be used for high level analysis only"); int prevThreadCount = -1; int threadCount = settings.rate.minThreads; List<StressMetrics> results = new ArrayList<>(); List<String> runIds = new ArrayList<>(); do { output.println(String.format("Running with %d threadCount", threadCount)); if (settings.command.truncate == SettingsCommand.TruncateWhen.ALWAYS) settings.command.truncateTables(settings); StressMetrics result = run( settings.command.getFactory(settings), threadCount, settings.command.count, settings.command.duration, rateLimiter, settings.command.durationUnits, output); if (result == null) return false; results.add(result); if (prevThreadCount > 0) System.out.println( String.format( "Improvement over %d threadCount: %.0f%%", prevThreadCount, 100 * averageImprovement(results, 1))); runIds.add(threadCount + " threadCount"); prevThreadCount = threadCount; if (threadCount < 16) threadCount *= 2; else threadCount *= 1.5; if (!results.isEmpty() && threadCount > settings.rate.maxThreads) break; if (settings.command.type.updates) { // pause an arbitrary period of time to let the commit log flush, etc. shouldn't make much // difference // as we only increase load, never decrease it output.println("Sleeping for 15s"); try { Thread.sleep(15 * 1000); } catch (InterruptedException e) { return false; } } // run until we have not improved throughput significantly for previous three runs } while (!auto || (hasAverageImprovement(results, 3, 0) && hasAverageImprovement(results, 5, settings.command.targetUncertainty))); // summarise all results StressMetrics.summarise(runIds, results, output, settings.samples.historyCount); return true; }
public Consumer( OpDistributionFactory operations, CountDownLatch done, WorkManager workManager, StressMetrics metrics, RateLimiter rateLimiter, int sampleCount) { this.done = done; this.rateLimiter = rateLimiter; this.workManager = workManager; this.metrics = metrics; this.operations = operations.get(metrics.getTiming(), sampleCount); }
private StressMetrics run( OpDistributionFactory operations, int threadCount, long opCount, long duration, RateLimiter rateLimiter, TimeUnit durationUnits, PrintStream output) { output.println( String.format( "Running %s with %d threads %s", operations.desc(), threadCount, durationUnits != null ? duration + " " + durationUnits.toString().toLowerCase() : opCount > 0 ? "for " + opCount + " iteration" : "until stderr of mean < " + settings.command.targetUncertainty)); final WorkManager workManager; if (opCount < 0) workManager = new WorkManager.ContinuousWorkManager(); else workManager = new WorkManager.FixedWorkManager(opCount); final StressMetrics metrics = new StressMetrics(output, settings.log.intervalMillis, settings); final CountDownLatch done = new CountDownLatch(threadCount); final Consumer[] consumers = new Consumer[threadCount]; for (int i = 0; i < threadCount; i++) { consumers[i] = new Consumer( operations, done, workManager, metrics, rateLimiter, settings.samples.liveCount / threadCount); } // starting worker threadCount for (int i = 0; i < threadCount; i++) consumers[i].start(); metrics.start(); if (durationUnits != null) { Uninterruptibles.sleepUninterruptibly(duration, durationUnits); workManager.stop(); } else if (opCount <= 0) { try { metrics.waitUntilConverges( settings.command.targetUncertainty, settings.command.minimumUncertaintyMeasurements, settings.command.maximumUncertaintyMeasurements); } catch (InterruptedException e) { } workManager.stop(); } try { done.await(); metrics.stop(); } catch (InterruptedException e) { } if (metrics.wasCancelled()) return null; metrics.summarise(); boolean success = true; for (Consumer consumer : consumers) success &= consumer.success; if (!success) return null; return metrics; }