![JAR search and dependency download from the Maven repository](/logo.png)
com.fillumina.performance.Telemetry Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of performance-tools Show documentation
Show all versions of performance-tools Show documentation
Configurable tool to easily compare performances of different code
snippets and to take performance telemetry of a running application.
The newest version!
package com.fillumina.performance;
import com.fillumina.performance.consumer.PerformanceConsumer;
import com.fillumina.performance.consumer.viewer.StringTableViewer;
import com.fillumina.performance.producer.RunningLoopPerformances;
import com.fillumina.performance.producer.LoopPerformances;
/**
* Evaluates the percentage of time employed by different parts of a code.
* It allows to better understand which part of an execution takes the most.
* Because it uses a {@link ThreadLocal} it can be
* used in a multi-threaded environment (i.e. in a web server where it can
* trace a single request against other requests being executed at the same
* time).
*
* The static methods return a {@code boolean}
* so that they can be used within an assertion
* which will not by default be executed by the JVM.
*
assert Telemetry.section("calculation");
*
* By this way the performance code can be left in place without affecting
* the speed of the final application.
* The returned value is always {@code true} to make the assertion succeed.
*
public class TelemetryTest {
private static final int ITERATIONS = 10;
private static final String START = "START";
private static final String ONE = "ONE";
private static final String TWO = "TWO";
private static final String THREE = "THREE";
private boolean printout = false;
public static void main(final String[] args) {
final TelemetryTest tt = new TelemetryTest();
tt.printout = true;
tt.shouldReturnValidResults();
}
void process() {
Telemetry.section(START);
stepOne();
Telemetry.section(ONE);
stepTwo();
Telemetry.section(TWO);
stepThree();
Telemetry.section(THREE);
}
void stepOne() {
worksForMills(20);
}
void stepTwo() {
worksForMills(10);
}
void stepThree() {
worksForMills(100);
}
void worksForMills(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
// do nothing
}
}
@Test
public void shouldReturnValidResults() {
Telemetry.init();
for (int i=0; i<ITERATIONS; i++) {
Telemetry.startIteration();
process();
}
if (printout) {
Telemetry.print();
}
Telemetry.use(AssertPerformance.withTolerance(5)
.assertPercentageFor(START).sameAs(0)
.assertPercentageFor(ONE).sameAs(20)
.assertPercentageFor(TWO).sameAs(10)
.assertPercentageFor(THREE).sameAs(100));
}
}
*
* @author Francesco Illuminati
*/
public class Telemetry {
private static final ThreadLocal threadLocal =
new ThreadLocal<>();
private final RunningLoopPerformances runningPerf;
private long last;
private long iterations;
public Telemetry() {
runningPerf = new RunningLoopPerformances();
last = System.nanoTime();
}
/**
* Initialize the test. If it is not called all the other calls will
* be ignored so to be able to run a code normally if it is not under
* Telemetry.
*
* @return always true so that it can be put on an assert
*/
public static boolean init() {
threadLocal.set(new Telemetry());
return true;
}
/** It determines the start of a new iteration. */
public static boolean startIteration() {
final Telemetry telemetry = getTelemetry();
telemetry.runningPerf.setIterations(++telemetry.iterations);
return true;
};
/**
* Defines a section by name. It records the time elapsed since the
* last call to itself or to {@link #startIteration()}.
*
* @return always true so it can be put on an assert.
*/
public static boolean section(final String name) {
final Telemetry telemetry = threadLocal.get();
if (telemetry != null) {
telemetry.localSegment(name);
}
return true;
}
/** @return the performances. */
public static LoopPerformances getLoopPerformances() {
final Telemetry telemetry = getTelemetry();
final RunningLoopPerformances performances = telemetry.runningPerf;
performances.setIterations(telemetry.iterations);
return performances.getLoopPerformances();
}
/** Makes the consumer consumes the performances. */
public static void use(final PerformanceConsumer consumer) {
consumer.consume("Telemetry", getLoopPerformances());
}
/** Prints out the performances in a human readable form. */
public static void print() {
System.out.println(threadLocal.get().toString());
}
private void localSegment(final String name) {
final long nano = getSegmentTime();
runningPerf.add(name, nano);
}
private long getSegmentTime() {
final long nano = System.nanoTime();
final long segment = nano - last;
last = nano;
return segment;
}
/** @return the {@link Telemetry} relative to the current thread. */
public static Telemetry getTelemetry() {
final Telemetry telemetry = threadLocal.get();
if (telemetry == null) {
throw new IllegalStateException(
"No Telemetry available for this thread");
}
return telemetry;
}
@Override
public String toString() {
return StringTableViewer.INSTANCE
.getTable(runningPerf.getLoopPerformances())
.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy