Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JBoss, Home of Professional Open Source.
* Copyright 2013 Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package io.narayana.perf;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author M Musgrove
*
* Config and result data for running a work load (@link{Measurement#measure})
*/
public class Measurement implements Serializable {
String name;
int numberOfMeasurements = 1; // if > 1 then an average of each run is taken (after removing outliers)
int numberOfCalls; // the total number of iterations used in this measurement
int numberOfThreads = 1; // the number of threads used to complete the measurement
int batchSize = 1; // iterations are executed in batches
private long maxTestTime = 0; // terminate measurement if test takes longer than this value
private int numberOfWarmupCalls = 0; //number of iterations before starting the measurement
private String info;
RegressionChecker config; // holds file based measurment data
private T context;
private final Set contexts = new HashSet();
int numberOfErrors = 0;
long totalMillis = 0L;
int one = 0; // time in msecs to do one call
double throughput = 0; // calls per second
private boolean cancelled;
private boolean mayInterruptIfRunning;
int numberOfBatches = 0;
boolean regression;
boolean failOnRegression;
private Exception exception;
public Measurement(int numberOfThreads, int numberOfCalls) {
this(numberOfThreads, numberOfCalls, 10);
}
public Measurement(int numberOfThreads, int numberOfCalls, int batchSize) {
this(0L, numberOfThreads, numberOfCalls, batchSize);
}
public Measurement(long maxTestTime, int numberOfThreads, int numberOfCalls, int batchSize) {
this(new Builder("").
maxTestTime(maxTestTime).numberOfThreads(numberOfThreads).numberOfCalls(numberOfCalls).batchSize(batchSize).construct());
}
public Measurement(Measurement result) {
this(result.maxTestTime, result.numberOfThreads, result.numberOfCalls, result.batchSize);
}
private Measurement(Builder builder) {
name = builder.name;
numberOfMeasurements = builder.numberOfMeasurements;
numberOfCalls = builder.numberOfCalls;
numberOfThreads = builder.numberOfThreads;
batchSize = builder.batchSize;
maxTestTime = builder.maxTestTime;
numberOfWarmupCalls = builder.numberOfWarmupCalls;
numberOfBatches = builder.numberOfBatches;
config = builder.config;
info = builder.info;
failOnRegression = config == null ? false : config.isFailOnRegression();
}
public boolean isRegression() {
return regression;
}
public boolean isFailOnRegression() {
return failOnRegression;
}
public boolean shouldFail() {
return isFailOnRegression() && isRegression();
}
public void setRegression(boolean regression) {
this.regression = regression;
}
public void setContext(T value) {
context = value;
}
public T getContext() {
return context;
}
public Set getContexts() {
return contexts;
}
void addContext(T t) {
contexts.add(t);
}
public int getNumberOfMeasurements() {
return numberOfMeasurements;
}
public int getNumberOfThreads() {
return numberOfThreads;
}
public int getNumberOfCalls() {
return numberOfCalls;
}
void setNumberOfCalls(int numberOfCalls) {
this.numberOfCalls = numberOfCalls;
}
public int getBatchSize() {
return batchSize;
}
int getNumberOfBatches() {
return numberOfBatches;
}
public long getTotalMillis() {
return totalMillis;
}
public long getOne() {
return one;
}
public void setTotalMillis(long totalMillis) {
this.totalMillis = totalMillis;
if (totalMillis != 0) {
this.one = totalMillis > 0 ? (int) (totalMillis / numberOfCalls) : 0;
this.throughput = (1000.0 * numberOfCalls) / totalMillis;
}
}
public double getThroughput() {
return throughput;
}
public int getNumberOfErrors() {
return numberOfErrors;
}
public void setNumberOfErrors(int numberOfErrors) {
this.numberOfErrors = numberOfErrors;
}
public void incrementErrorCount() {
this.numberOfErrors += 1;
}
public void incrementErrorCount(int delta) {
this.numberOfErrors += delta;
}
public String toString() {
return String.format("%f calls / second (%d calls in %d ms using %d threads. %d errors)",
getThroughput(), getNumberOfCalls(),
getTotalMillis(), getNumberOfThreads(),
getNumberOfErrors());
}
public void setInfo(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
/**
* Cancel the measurement.
*
* A worker may cancel a measurement by invoking this method on the Measurement object it was
* passed in its @see Worker#doWork(T, int, Measurement) method
* @param mayInterruptIfRunning if false then any running calls to @see Worker#doWork will be allowed to finish
* before the the measurement is cancelled.
*/
public void cancel(boolean mayInterruptIfRunning) {
this.cancelled = true;
this.mayInterruptIfRunning = mayInterruptIfRunning;
}
/**
* Cancel the measurement.
*
* A worker may cancel a measurement by invoking this method on the Measurement object it was
* passed in its @see Worker#doWork(T, int, Measurement) method
* @param reason the reason for the cancelation
* @param mayInterruptIfRunning if false then any running calls to @see Worker#doWork will be allowed to finish
* before the the measurement is cancelled.
*/
public void cancel(String reason, boolean mayInterruptIfRunning) {
this.setInfo(reason);
this.cancelled = true;
this.mayInterruptIfRunning = mayInterruptIfRunning;
}
void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public boolean isCancelled() {
return cancelled;
}
public boolean isMayInterruptIfRunning() {
return mayInterruptIfRunning;
}
/**
* @return max test time in milliseconds
*/
public long getMaxTestTime() {
return maxTestTime;
}
public int getNumberOfWarmupCalls() {
return numberOfWarmupCalls;
}
/**
*
* @return true if the measurement took longer than the maximum test time {@link io.narayana.perf.Measurement#getMaxTestTime()}
*/
public boolean isTimedOut() {
return isCancelled() || getTotalMillis() > maxTestTime;
}
public Measurement measure(WorkerWorkload workload) {
return measure(null, workload);
}
public Measurement measure(final WorkerLifecycle lifecycle, final WorkerWorkload workload) {
if (workload == null)
throw new IllegalArgumentException("workload must not be null");
if (lifecycle != null)
lifecycle.init();
if (numberOfWarmupCalls > 0) {
System.out.printf("Test Warm Up: %s: (%d calls using %d threads)%n", name, numberOfWarmupCalls, numberOfThreads);
doWork(workload, new Measurement(maxTestTime, 1, numberOfWarmupCalls, 1));
}
System.out.printf("Test Run: %s (%d calls using %d threads)%n", name, numberOfCalls, numberOfThreads);
if (config == null) {
for (int i = 0; i < numberOfMeasurements; i++)
doWork(workload, this);
} else {
boolean wasFailOnRegression = config.isFailOnRegression();
List metrics = new ArrayList();
if (wasFailOnRegression) {
config.setFailOnRegression(false);
this.failOnRegression = false;
}
for (int i = 0; i < numberOfMeasurements; i++) {
doWork(workload, this);
metrics.add(getThroughput());
}
config.setFailOnRegression(wasFailOnRegression);
this.failOnRegression = wasFailOnRegression;
throughput = Averager.getAverage(metrics);
}
if (lifecycle != null)
lifecycle.fini();
StringBuilder sb = new StringBuilder();
if (config != null)
setRegression(!config.updateMetric(sb, name, getThroughput(), true));
setInfo(sb.toString());
return this;
}
private Measurement doWork(final WorkerWorkload workload, final Measurement opts) {
ExecutorService executor = Executors.newFixedThreadPool(opts.getNumberOfThreads());
final AtomicInteger count = new AtomicInteger(opts.getNumberOfBatches());
final Collection>> tasks = new ArrayList>>();
final CyclicBarrier cyclicBarrier = new CyclicBarrier(opts.getNumberOfThreads() + 1); // workers + self
totalMillis = 0;
for (int i = 0; i < opts.getNumberOfThreads(); i++)
tasks.add(executor.submit(new Callable>() {
public Measurement call() throws Exception {
Measurement res = new Measurement<>(
opts.getMaxTestTime(), opts.getNumberOfThreads(), opts.getNumberOfCalls(), opts.getBatchSize());
int errorCount = 0;
try {
cyclicBarrier.await();
long start = System.nanoTime();
// all threads are ready - this thread gets more work in batch size chunks until there isn't anymore
while (count.decrementAndGet() >= 0) {
res.setNumberOfCalls(opts.getBatchSize());
// ask the worker to do batchSize units or work
try {
res.setContext(workload.doWork(res.getContext(), opts.getBatchSize(), res));
errorCount += res.getNumberOfErrors();
} catch (Exception e) {
if (res.getException() == null)
e.printStackTrace();
res.setException(e);
errorCount += opts.getBatchSize();
res.setCancelled(true);
}
if (res.isCancelled()) {
for (Future> task : tasks) {
if (!task.equals(this))
task.cancel(res.isMayInterruptIfRunning());
}
opts.setContext(res.getContext());
if (res.getException() != null)
opts.setException(res.getException());
break;
}
}
cyclicBarrier.await();
res.setTotalMillis((System.nanoTime() - start) / 1000000L);
if (res.getTotalMillis() < 0)
res.setTotalMillis(-res.getTotalMillis());
res.setNumberOfErrors(errorCount);
} finally {
workload.finishWork(res);
}
return res;
};
}));
opts.setNumberOfErrors(0);
long start = System.nanoTime();
try {
cyclicBarrier.await(); // wait for each thread to arrive at the barrier
// wait for each thread to finish
if (opts.getMaxTestTime() > 0)
cyclicBarrier.await(opts.getMaxTestTime(), TimeUnit.MILLISECONDS);
else
cyclicBarrier.await();
long tot = System.nanoTime() - start;
if (tot < 0) // nanoTime is reckoned from an arbitrary origin which may be in the future
tot = -tot;
opts.setTotalMillis(tot / 1000000L);
} catch (InterruptedException e) {
opts.incrementErrorCount(); // ? exactly how many errors were there?
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
opts.incrementErrorCount(); // ? exactly how many errors were there?
opts.setCancelled(true);
} catch (TimeoutException e) {
opts.incrementErrorCount(); // ? exactly how many errors were there?
opts.setCancelled(true);
}
for (Future> t : tasks) {
try {
Measurement outcome = t.get();
T context = outcome.getContext();
if (context != null)
opts.addContext(context);
if (outcome.getException() != null)
opts.setException(outcome.getException());
opts.incrementErrorCount(outcome.getNumberOfErrors());
} catch (CancellationException e) {
opts.incrementErrorCount(opts.getBatchSize());
opts.setCancelled(true);
} catch (ExecutionException e) { // should be a BrokenBarrierException due to a timeout
System.out.printf("ExecutionException exception: %s%n", e.getMessage());
opts.incrementErrorCount(opts.getBatchSize());
opts.setCancelled(true);
} catch (Exception e) {
System.err.printf("Performance test exception: %s%n", e.getMessage());
opts.incrementErrorCount(opts.getBatchSize());
}
}
executor.shutdownNow();
return opts;
}
public void setException(Exception exception) {
this.exception = exception;
}
public Exception getException() {
return exception;
}
public static final class Builder {
private String name;
private int numberOfCalls = 10;
private int numberOfThreads = 1;
private int batchSize = 1;
private long maxTestTime = 0L;
private int numberOfWarmupCalls = 0;
private int numberOfBatches;
private int numberOfMeasurements = 1;
private String info;
RegressionChecker config;
public Builder(String name) {
name(name);
}
public Builder name(String name) {
if (name == null)
throw new IllegalArgumentException("name must be null");
this.name = name;
return this;
}
/**
* The number of times to run the measurement.
* If greater than one then outliers are discounted and an average is taken of the remaining runs.
* @param numberOfMeasurements number of measurements
* @return the builder
*/
public Builder numberOfMeasurements(int numberOfMeasurements) {
this.numberOfMeasurements = numberOfMeasurements;
return this;
}
public Builder numberOfCalls(int numberOfCalls) {
this.numberOfCalls = numberOfCalls;
return this;
}
public Builder numberOfThreads(int numberOfThreads) {
this.numberOfThreads = numberOfThreads;
return this;
}
public Builder batchSize(int batchSize) {
this.batchSize = batchSize;
return this;
}
public Builder maxTestTime(long maxTestTime) {
this.maxTestTime = maxTestTime;
return this;
}
public Builder numberOfWarmupCalls(int numberOfWarmupCalls) {
this.numberOfWarmupCalls = numberOfWarmupCalls;
return this;
}
public Builder info(String info) {
this.info = info;
return this;
}
public Builder config() throws IOException {
return config(new RegressionChecker());
}
public Builder config(RegressionChecker config) {
this.config = config;
return this;
}
private Builder construct() {
if (config == null && RegressionChecker.isRegressionCheckEnabled()) {
try {
config = new RegressionChecker();
} catch (IOException e) {
}
}
if (config != null) {
String[] xargs = config.getTestArgs(name);
numberOfMeasurements = config.getArg(name, xargs, 0, numberOfMeasurements, Integer.class);
maxTestTime = config.getArg(name, xargs, 1, maxTestTime, Long.class);
numberOfWarmupCalls = config.getArg(name, xargs, 2, numberOfWarmupCalls, Integer.class);
numberOfCalls = config.getArg(name, xargs, 3, numberOfCalls, Integer.class);
numberOfThreads = config.getArg(name, xargs, 4, numberOfThreads, Integer.class);
batchSize = config.getArg(name, xargs, 5, batchSize, Integer.class);
}
if (batchSize <= 0) {
System.err.printf("Invalid batch size (%d) setting to 1%n", batchSize);
batchSize = 1;
}
if (numberOfCalls < batchSize) {
System.err.println("Updating call count (request size less than batch size)");
numberOfCalls = batchSize;
}
numberOfBatches = numberOfCalls / batchSize;
if (numberOfBatches < numberOfThreads) {
System.err.printf("Too few batches - reducing thread count (%d %d %d)%n",
numberOfThreads, numberOfBatches, numberOfCalls);
numberOfThreads = numberOfBatches;
}
return this;
}
public Measurement build() {
construct();
return new Measurement<>(this);
}
}
}