Mercurial > hg > gc-bench
view src/main/java/org/openjdk/gcbench/tests/DimensionalTest.java @ 45:9bdd6c03b353
Report median pause/ttsp time, mark columns appropriately.
author | shade |
---|---|
date | Thu, 08 Dec 2016 12:16:59 +0100 |
parents | 198cdbd1c4e8 |
children | a009ea5f9d2c |
line wrap: on
line source
package org.openjdk.gcbench.tests; import org.openjdk.jmh.profile.GCProfiler; import org.openjdk.jmh.profile.SafepointsProfiler; import org.openjdk.jmh.results.Result; import org.openjdk.jmh.results.RunResult; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.*; import java.util.Map; public class DimensionalTest extends AbstractTest { private final Dimension[] dimensions; private final boolean rated; public DimensionalTest(Options baseOpts, Class<?> benchmark, String label, String description, Dimension... dimensions) { this(baseOpts, benchmark, label, description, false, dimensions); } public DimensionalTest(Options baseOpts, Class<?> benchmark, String label, String description, boolean rated, Dimension... dimensions) { super(baseOpts, label, benchmark, description); this.dimensions = dimensions; this.rated = rated; } @Override protected void doRun() { pw.println(" Test dimensions: "); for (Dimension d : dimensions) { pw.print(" "); pw.println(d.toString()); } pw.println(); pw.print(" "); for (Dimension d : dimensions) { pw.printf("%-10s ", d.label()); } if (rated) { pw.printf("%-15s ", "Target rate"); } pw.printf("%-35s %-25s %-7s %-60s %-60s%n", "Work rate", "Allocation rate", "Pauses", "Pause time", "Time to safepoint" ); pw.print(" "); for (Dimension d : dimensions) { pw.printf("%-10s ", ""); } if (rated) { pw.printf("%-15s ", ""); } pw.printf("%-35s %-25s %-7s %8s %12s %12s %12s %12s %8s %12s %12s %12s %12s %n", "", "", "", "total %", "sum", "median", "99%", "max", "pause %", "sum", "median", "99%", "max" ); Object lastKeyVal = null; for (DimensionValues values : DimensionValues.product(dimensions)) { ChainedOptionsBuilder builder = new OptionsBuilder() .parent(baseOpts) .addProfiler(GCProfiler.class) .addProfiler(SafepointsProfiler.class) .include(benchmark.getName()); int heapSize = -1; int lds = -1; Object keyVal = -1; for (int i = 0; i < dimensions.length; i++) { Dimension d = dimensions[i]; Object value = values.values[i]; if (i == dimensions.length - 2) { keyVal = value; } int intValue = Integer.valueOf(value.toString()); switch (d.type()) { case HEAPSIZE: builder = builder.jvmArgsAppend("-Xmx" + value + "m", "-Xms" + value + "m"); heapSize = intValue; break; case LDS: builder = builder.param("ldsMB", String.valueOf(value)); lds = intValue; break; case THREADS: builder = builder.threads(intValue); break; case SIZE: builder = builder.param("size", String.valueOf(value)); break; default: throw new IllegalStateException("Unknown dimension: " + d); } } if (heapSize != -1 && lds != -1 && lds >= heapSize) { // Skip this one! continue; } if (lastKeyVal != keyVal) { pw.println(); lastKeyVal = keyVal; } if (rated) { final int RATE_STEPS = 5; int maxRate = calibrateRate(builder.build()); for (int rate = maxRate / RATE_STEPS; rate <= maxRate; rate += Math.max(1, maxRate / RATE_STEPS)) { Options opts = new OptionsBuilder() .parent(builder.build()) .param("rate", String.valueOf(rate)) .build(); runWith(values, opts, rate); } pw.println(); } else { runWith(values, builder.build(), 0); } } } private int calibrateRate(Options base) { try { Options opts = new OptionsBuilder() .parent(base) .param("rate", String.valueOf(Integer.MAX_VALUE)) .build(); RunResult result = new Runner(opts).runSingle(); return (int) result.getPrimaryResult().getScore(); } catch (RunnerException e) { return 0; } } private void runWith(DimensionValues values, Options opts, int rate) { pw.print(" "); for (Object v : values.values) { pw.printf("%-10s ", v); } if (rated) { pw.printf("%-15s ", rate); } try { RunResult result = new Runner(opts).runSingle(); Result prim = result.getPrimaryResult(); Map<String, Result> sec = result.getSecondaryResults(); pw.printf("%-35s %-25s %-7s %8s %12s %12s %12s %12s %8s %12s %12s %12s %12s %n", shortVal(prim), shortVal(sec.get("·gc.alloc.rate")), intVal(sec.get("·safepoints.pause.count")), percentRatioVal(sec.get("·safepoints.pause"), sec.get("·safepoints.interval")), latencyVal(sec.get("·safepoints.pause")), latencyVal(sec.get("·safepoints.pause.p0.50")), latencyVal(sec.get("·safepoints.pause.p0.99")), latencyVal(sec.get("·safepoints.pause.p1.00")), percentRatioVal(sec.get("·safepoints.ttsp"), sec.get("·safepoints.pause")), latencyVal(sec.get("·safepoints.ttsp")), latencyVal(sec.get("·safepoints.ttsp.p0.50")), latencyVal(sec.get("·safepoints.ttsp.p0.99")), latencyVal(sec.get("·safepoints.ttsp.p1.00")) ); } catch (RunnerException e) { pw.print("FAILED: "); Throwable cause = e.getCause(); if (cause != null) { for (Throwable t : cause.getSuppressed()) { pw.print(t.getMessage() + " "); } } else { pw.println(" unknown error"); e.printStackTrace(pw); } pw.println(); } } private String percentRatioVal(Result r1, Result r2) { if (r1 != null && r2 != null) { return String.format("%.2f %%", 100D * r1.getScore() / r2.getScore()); } return "-"; } private String intVal(Result r) { if (r != null) { if (!Double.isNaN(r.getScoreError())) { return String.format("%d ± %d", Math.round(r.getScore()), Math.round(r.getScoreError())); } else { return String.format("%d", Math.round(r.getScore())); } } else { return "-"; } } private String shortVal(Result r) { if (r != null) { if (!Double.isNaN(r.getScoreError())) { return String.format("%.1f ± %.1f %s", r.getScore(), r.getScoreError(), r.getScoreUnit()); } else { return String.format("%.1f %s", r.getScore(), r.getScoreUnit()); } } else { return "-"; } } private String latencyVal(Result r) { if (r != null && !Double.isNaN(r.getScore())) { return String.format("%.3f %s", r.getScore(), r.getScoreUnit()); } else { return "-"; } } }