|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Builds the JMH benchmark fat jar and runs it, then prints a formatted |
| 3 | +# transformation-time summary. |
| 4 | +# Any arguments are forwarded to JMH, e.g.: |
| 5 | +# ./benchmark.sh # full run (~10-15 min) |
| 6 | +# ./benchmark.sh -f 1 -wi 2 -i 3 # quick smoke run (~2 min) |
| 7 | +# ./benchmark.sh mutableSimpleBean # single benchmark |
| 8 | +# ./benchmark.sh -rf json -rff out.json # write results to JSON |
| 9 | + |
| 10 | +set -euo pipefail |
| 11 | + |
| 12 | +MODULES="bull-common,bull-converter,bull-bean-transformer,bull-benchmark" |
| 13 | +JAR="bull-benchmark/target/benchmarks.jar" |
| 14 | +MVN="./mvnw" |
| 15 | + |
| 16 | +if [[ "$(uname -s)" == MINGW* || "$(uname -s)" == CYGWIN* ]]; then |
| 17 | + MVN="./mvnw.cmd" |
| 18 | +fi |
| 19 | + |
| 20 | +echo "==> Building benchmark jar..." |
| 21 | +BUILD_LOG=$(mktemp) |
| 22 | +trap 'rm -f "$TMPOUT" "$BUILD_LOG"' EXIT |
| 23 | +if ! "$MVN" package -pl "$MODULES" -DskipTests -Djacoco.skip=true -q >"$BUILD_LOG" 2>&1; then |
| 24 | + cat "$BUILD_LOG" |
| 25 | + exit 1 |
| 26 | +fi |
| 27 | + |
| 28 | +TMPOUT=$(mktemp) |
| 29 | + |
| 30 | +echo "==> Running benchmarks..." |
| 31 | +java -jar "$JAR" "$@" 2>&1 \ |
| 32 | + | grep -v \ |
| 33 | + -e "^NOTE:" \ |
| 34 | + -e "^WARNING:" \ |
| 35 | + -e "^Processing [0-9]" \ |
| 36 | + -e "^Writing out" \ |
| 37 | + | tee "$TMPOUT" |
| 38 | + |
| 39 | +# ----------------------------------------------------------------------- |
| 40 | +# Pretty-print a transformation-time summary from the JMH result lines. |
| 41 | +# Scores are in µs/op; we convert to ms for readability. |
| 42 | +# Result lines look like either of: |
| 43 | +# TransformerBenchmark.mutableSimpleBean avgt 2 0.536 us/op |
| 44 | +# TransformerBenchmark.mutableSimpleBean avgt 20 0.536 ± 0.012 us/op |
| 45 | +# ----------------------------------------------------------------------- |
| 46 | +echo "" |
| 47 | +echo "==> Transformation times summary (ms/op):" |
| 48 | +echo "" |
| 49 | + |
| 50 | +awk ' |
| 51 | +function us_to_ms(v, r) { |
| 52 | + r = v / 1000 |
| 53 | + # print with enough decimals to show non-zero values even for fast paths |
| 54 | + return sprintf("%.6f", r) |
| 55 | +} |
| 56 | +/^TransformerBenchmark\./ { |
| 57 | + split($1, parts, ".") |
| 58 | + name = parts[2] |
| 59 | + score = $4 |
| 60 | + if ($5 == "±") { error = "± " us_to_ms($6); unit = $7 } |
| 61 | + else { error = ""; unit = $5 } |
| 62 | + scores[name] = us_to_ms(score) |
| 63 | + errors[name] = error |
| 64 | + # classify into bean transformations vs type conversions |
| 65 | + if (name ~ /typeConversion/) { |
| 66 | + conv[length(conv)+1] = name |
| 67 | + } else { |
| 68 | + beans[length(beans)+1] = name |
| 69 | + } |
| 70 | +} |
| 71 | +END { |
| 72 | + fmt = " %-44s %12s %-16s\n" |
| 73 | + sep = " " sprintf("%-44s", "--------------------------------------------") \ |
| 74 | + " " sprintf("%-12s", "------------") \ |
| 75 | + " " sprintf("%-16s", "----------------") |
| 76 | +
|
| 77 | + print " Bean transformations:" |
| 78 | + printf fmt, " Benchmark", "Time (ms/op)", "Error (ms/op)" |
| 79 | + print sep |
| 80 | + for (i = 1; i <= length(beans); i++) { |
| 81 | + n = beans[i] |
| 82 | + printf fmt, " " n, scores[n], errors[n] |
| 83 | + } |
| 84 | +
|
| 85 | + print "" |
| 86 | + print " Type conversions:" |
| 87 | + printf fmt, " Benchmark", "Time (ms/op)", "Error (ms/op)" |
| 88 | + print sep |
| 89 | + for (i = 1; i <= length(conv); i++) { |
| 90 | + n = conv[i] |
| 91 | + printf fmt, " " n, scores[n], errors[n] |
| 92 | + } |
| 93 | +} |
| 94 | +' "$TMPOUT" |
0 commit comments