Mercurial > hg > gc-bench
view src/main/java/org/openjdk/gcbench/tests/DimensionalTest.java @ 89:d68c66d67740
Rehash gathered safepoints and GC pauses metrics. Formatting changes.
author | shade |
---|---|
date | Thu, 23 Nov 2017 15:10:59 +0100 |
parents | 583fef4276f5 |
children | 14c1bb4faa6e |
line wrap: on
line source
/* * Copyright (c) 2017, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ 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("%-25s %-25s %-7s %-46s %-46s%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("%-25s %-25s %-7s %8s %12s %12s %12s %8s %12s %12s %12s%n", "", "", "", "total %", "avg", "99.9%", "max", "pause %", "avg", "99.9%", "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.jvmArgsPrepend("-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("%-25s %-25s %-7s %8s %12s %12s %12s %8s %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.avg")), latencyVal(sec.get("·safepoints.pause.p0.999")), latencyVal(sec.get("·safepoints.pause.p1.00")), percentRatioVal(sec.get("·safepoints.ttsp"), sec.get("·safepoints.pause")), latencyVal(sec.get("·safepoints.ttsp.avg")), latencyVal(sec.get("·safepoints.ttsp.p0.999")), 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 "-"; } } }