view src/main/java/org/openjdk/gcbench/tests/MachineCntTest.java @ 88:583fef4276f5

Update license and copyright headers.
author shade
date Wed, 22 Nov 2017 15:58:02 +0100
parents 71b2baff8548
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.LinuxPerfNormProfiler;
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 MachineCntTest extends AbstractTest {

    private final Dimension[] dimensions;

    public MachineCntTest(Options baseOpts, Class<?> benchmark, String label, String description,
                           Dimension... dimensions) {
        super(baseOpts, label, benchmark, description);
        this.dimensions = dimensions;
    }

    @Override
    protected void doRun() {
        pw.println("  This tests requires installed 'perf', and probably elevated privileges:");
        pw.println("    $ echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid");
        pw.println();

        pw.println("  Test dimensions: ");
        for (Dimension d : dimensions) {
            pw.print("    ");
            pw.println(d.toString());
        }
        pw.println();

        pw.print("  ");

        for (Dimension d : dimensions) {
            pw.printf("%-30s ", d.label());
        }

        pw.printf("%-35s %-25s %-25s %-25s %n",
                "Performance",
                "Cycles",
                "Instructions",
                "Branches"
        );

        Object lastKeyVal = null;

        for (DimensionValues values : DimensionValues.product(dimensions)) {
            ChainedOptionsBuilder builder = new OptionsBuilder()
                    .parent(baseOpts)
                    .threads(1)
                    .forks(5)
                    .warmupIterations(3)
                    .warmupTime(TimeValue.seconds(1))
                    .measurementIterations(1)
                    .measurementTime(TimeValue.seconds(3))
                    .addProfiler(LinuxPerfNormProfiler.class, "events=cycles,instructions,branches");


            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;
                }

                switch (d.type()) {
                    case JVM_MODE:
                        builder = builder.jvmArgsAppend(String.valueOf(value));
                        break;
                    case JAVA_TYPE:
                        builder = builder.include(benchmark.getName() + ".test_" + value);
                        break;
                    default:
                        throw new IllegalStateException("Unknown dimension: " + d);
                }
            }

            if (lastKeyVal != keyVal) {
                pw.println();
                lastKeyVal = keyVal;
            }

            runWith(values, builder.build());
        }
    }

    private void runWith(DimensionValues values, Options opts) {
        pw.print("  ");

        for (Object v : values.values) {
            pw.printf("%-30s ", v);
        }

        try {
            RunResult result = new Runner(opts).runSingle();

            Result prim = result.getPrimaryResult();
            Map<String, Result> sec = result.getSecondaryResults();

            pw.printf("%-35s %-25s %-25s %-25s%n",
                    shortVal(prim),
                    shortVal(sec.get("cycles")),
                    shortVal(sec.get("instructions")),
                    shortVal(sec.get("branches"))
            );
        } 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 shortVal(Result r) {
        if (r != null) {
            if (!Double.isNaN(r.getScoreError())) {
                return String.format("%.2f ± %.2f %s", r.getScore(), r.getScoreError(), r.getScoreUnit());
            } else {
                return String.format("%.2f %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 "-";
        }
    }
}