package org.openjdk; import org.openjdk.jmh.profile.LinuxPerfNormProfiler; import org.openjdk.jmh.profile.LinuxPerfProfiler; 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 sun.misc.Unsafe; import org.openjdk.jmh.annotations.*; import org.openjdk.jol.util.VMSupport; import java.util.*; import java.util.concurrent.TimeUnit; @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 100, time = 1, timeUnit = TimeUnit.SECONDS) @Fork(10) @State(Scope.Thread) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public class ArrayCopyByteScan { static final int STORAGE_SIZE = 17 * 1024 * 1024; @Param({"8000"}) int copySize; @Param("0") int src; @Param("0") int dst; @Param("false") boolean alignSize; byte[] data; long lastDataAddr; @Setup(Level.Trial) public void setupData() throws InterruptedException { Random r = new Random(); if (alignSize) { // Get the perfectly-aligned array: do { data = new byte[r.nextInt(STORAGE_SIZE)]; data = new byte[STORAGE_SIZE]; lastDataAddr = VMSupport.addressOf(data); } while ((lastDataAddr + Unsafe.ARRAY_BYTE_BASE_OFFSET) % STORAGE_SIZE != 0); } else { data = new byte[STORAGE_SIZE]; } } @Setup(Level.Iteration) public void setUp() throws InterruptedException { if (alignSize) { long addr = VMSupport.addressOf(data); if (lastDataAddr != addr) { throw new IllegalStateException("Move detected: " + lastDataAddr + " " + addr); } } } @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) public void arraycopy() { System.arraycopy(data, src, data, dst, copySize); } public static void main(String... args) throws CommandLineOptionException { final int copySize = 7000; final int startDst = 8100; // final int finalDst = STORAGE_SIZE - copySize; final int finalDst = 12200; final int src = 0; final int delta = 1; boolean headerPrinted = false; for (int dst = startDst; dst < finalDst; dst += delta) { try { Options opts = new OptionsBuilder() .include(ArrayCopyByteScan.class.getName()) .param("copySize", String.valueOf(copySize)) .forks(1) .warmupIterations(3) .measurementIterations(3) .warmupTime(TimeValue.milliseconds(100)) .measurementTime(TimeValue.milliseconds(100)) .verbosity(VerboseMode.SILENT) .param("src", String.valueOf(src)) .param("dst", String.valueOf(dst)) .addProfiler(LinuxPerfNormProfiler.class, "events=r8a2,r41d0,r42d0,r107") // .addProfiler(LinuxPerfNormProfiler.class, "events=r1003,r105,r205") .build(); RunResult result = new Runner(opts).runSingle(); Result res = result.getPrimaryResult(); Map sr = result.getSecondaryResults(); if (!headerPrinted) { headerPrinted = true; System.out.printf("%5s, %5s, %7s, %7s, ", "Src", "Dst", "Score", "Error"); for (String k : sr.keySet()) { System.out.printf("%7s, ", k); } System.out.println(); } System.out.printf("%5d, %5d, %7.2f, %7.2f, ", src, dst, res.getScore(), res.getScoreError()); for (String k : sr.keySet()) { System.out.printf("%7.0f, ", sr.get(k).getScore()); } System.out.println(); } catch (RunnerException e) { // System.out.printf("%5d, %5d, FAILED%n", src, dst); } } } }