From 5b5836adb28b7a6d82297d00f68384dca36c4eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bulej?= Date: Mon, 21 Jun 2021 12:48:48 +0200 Subject: [PATCH 1/2] Print a message if the benchmark operation fails This gives us a chance to at least print the name of the failure exception, because the exception can be lost if any of the tear-down methods in the finally blocks throws an exception. An alternative would be to complicate the exception handling even more to make sure the original exception does not get lost, but at that point, the benchmark is doomed anyway. --- .../renaissance/harness/ExecutionDriver.java | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/renaissance-harness/src/main/java/org/renaissance/harness/ExecutionDriver.java b/renaissance-harness/src/main/java/org/renaissance/harness/ExecutionDriver.java index 15b10b9d..92be60ca 100644 --- a/renaissance-harness/src/main/java/org/renaissance/harness/ExecutionDriver.java +++ b/renaissance-harness/src/main/java/org/renaissance/harness/ExecutionDriver.java @@ -34,10 +34,13 @@ final class ExecutionDriver { private final ExecutionPolicy executionPolicy; /** Preformatted message to print before executing the benchmark. */ - private final String beforeEachMessageFormat; + private final String beforeEachFormat; - /** Preformatted message to print after executing the benchmark. */ - private final String afterEachMessageFormat; + /** Preformatted message to print after successful benchmark operation. */ + private final String afterSuccessFormat; + + /** Preformatted message to print after failed benchmark operation. */ + private final String afterFailureFormat; /** The value of {@link System#nanoTime()} at VM start. */ private final long vmStartNanos; @@ -58,20 +61,17 @@ private ExecutionDriver( this.benchmarkName = context.benchmarkName(); - // Pre-format the before/after messages (escaping the format specifier - // for the operation index which keeps changing) so that we don't have - // to query the static information over and over. - this.beforeEachMessageFormat = String.format( - "====== %s (%s) [%s], iteration %%d started ======\n", - context.benchmarkName(), context.benchmarkPrimaryGroup(), - context.configurationName() + // Pre-format the message prefix so that we don't have to query + // the static information about a benchmark over and over. + String prefix = String.format( + "====== %s (%s) [%s], iteration", context.benchmarkName(), + context.benchmarkPrimaryGroup(), context.configurationName() ); - this.afterEachMessageFormat = String.format( - "====== %s (%s) [%s], iteration %%d completed (%%.3f ms) ======\n", - context.benchmarkName(), context.benchmarkPrimaryGroup(), - context.configurationName() - ); + // Add formats for the message parts that change. + this.beforeEachFormat = prefix + " %d started ======\n"; + this.afterSuccessFormat = prefix + " %d completed (%.3f ms) ======\n"; + this.afterFailureFormat = prefix + " %d failed (%s) ======\n"; } @@ -84,17 +84,23 @@ public final void executeBenchmark() throws ValidationException { try { eventDispatcher.notifyAfterBenchmarkSetUp(benchmarkName); + int operationIndex = 0; + try { - int operationIndex = 0; while (executionPolicy.canExecute(benchmarkName, operationIndex)) { printBeforeEachMessage(operationIndex); final long durationNanos = executeOperation(operationIndex); - printAfterEachMessage(operationIndex, durationNanos); + printAfterSuccessMessage(operationIndex, durationNanos); operationIndex++; } + } catch (Throwable cause) { + // Print failure line with a cause and rethrow the exception. + printAfterFailureMessage(operationIndex, cause.getClass().getSimpleName()); + throw cause; + } finally { // Complement the notifyAfterBenchmarkSetUp() events. eventDispatcher.notifyBeforeBenchmarkTearDown(benchmarkName); @@ -149,15 +155,19 @@ private long executeOperation(final int index) throws ValidationException { private void printBeforeEachMessage(int index) { - System.out.printf(beforeEachMessageFormat, index); + System.out.printf(beforeEachFormat, index); } - private void printAfterEachMessage(int index, long nanos) { + private void printAfterSuccessMessage(int index, long nanos) { final double millis = nanos / 1e6; // Use root locale to avoid locale-specific float formatting. - System.out.printf(Locale.ROOT, afterEachMessageFormat, index, millis); + System.out.printf(Locale.ROOT, afterSuccessFormat, index, millis); + } + + private void printAfterFailureMessage(int index, String cause) { + System.out.printf(afterFailureFormat, index, cause); } From 6e4f2e0bbefe56f9961f38e94535fe161bbb1f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Bulej?= Date: Wed, 16 Jun 2021 14:28:05 +0200 Subject: [PATCH 2/2] Print the validation warning using a single call This may help avoid interleaving the contents of stderr and stdout. --- .../src/main/java/org/renaissance/BenchmarkResult.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/renaissance-core/src/main/java/org/renaissance/BenchmarkResult.java b/renaissance-core/src/main/java/org/renaissance/BenchmarkResult.java index 9d62dbe8..7e4c2ab9 100644 --- a/renaissance-core/src/main/java/org/renaissance/BenchmarkResult.java +++ b/renaissance-core/src/main/java/org/renaissance/BenchmarkResult.java @@ -40,8 +40,10 @@ public static BenchmarkResult dummy(Object... objects) { return () -> { Arrays.fill(objects, null); - System.err.println("WARNING: This benchmark provides no result that can be validated."); - System.err.println(" There is no way to check that no silent failure occurred."); + System.err.print( + "WARNING: This benchmark provides no result that can be validated.\n"+ + "There is no way to check that no silent failure occurred.\n" + ); }; }