sclass MultiBencher { settable Runnable action; settable double seconds = 10; settable double interval = 0.001; double elapsedSeconds; new L benchers; *() {} *(Runnable *action) {} run { ensureCapacity(benchers, iceilRatio(seconds, interval)+2); long start = nanoTime(), endTime = lround(start+secondsToNanos(seconds)); while (nanoTime() < endTime) { var bencher = addAndReturn(benchers, new BenchForNSeconds(interval, action)); bencher.run(); } } long startTime() { ret empty(benchers) ? 0 : first(benchers).startTime; } S renderLegMS(int i) { ret n2(lround(nanosToMilliseconds(benchers.get(i).startTime-startTime()))) + " ms"; } S renderLegIndex(int i) { ret "Leg " + (i+1) + "/" + l(benchers) + " (T+" + renderLegMS(i) + ")"; } toString { ret lines(mapWithIndex(benchers, (i, b) -> renderLegIndex(i) + ": " + b)); } // "min records" are the times when a new minimum iteration time is reached S renderMinRecords(double improvementThreshold default 0.05) { new LS lines; long best = 0, iterations = 0, compileTime = 0, compileIterations = 0; int improvements = 0; for i, b over benchers: { long time = lround(b.min()); iterations += b.iterations(); if (i == 0) { best = time; lines.add("First leg: " + n2(time) + " ns"); } else { double ratio = doubleRatio(best, time); double improvement = ratio-1; if (improvement > improvementThreshold) { //printVars(+i, +best, +time, +ratio, +improvement); ++improvements; best = time; S percent = formatDouble1(improvement*100); lines.add("Improved " + convertToSpacesIf(improvements == 1, "another ") + pad(percent, 7) + "% after " + pad(renderLegMS(i), 8) + pad(appendBracketed(nIterations(iterations)), 22) + " - new time: " + pad(b.formatNanos(time), 12)); //lines.add("New best time in " + firstToLower(renderLegIndex(i)) + ": " + n2(time) + " ns"); compileIterations = iterations; compileTime = time; } } } if (!isEmpty()) lines.add("\nFully optimized after " + first(benchers).formatNanos(compileTime) + appendBracketed(nIterations(compileIterations))); ret lines(lines); } bool isEmpty() { ret empty(benchers); } }