Skip to content

Commit 09b3b7c

Browse files
authored
Merge pull request #247 from scijava/scijava-ops-benchmarks/better-charts
Improve SciJava Ops benchmark charts
2 parents b3917b2 + 0ec4663 commit 09b3b7c

11 files changed

Lines changed: 105 additions & 53 deletions

docs/ops/bin/benchmark.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ fi
1111

1212
SCRIPT_PATH=$(dirname "$(realpath -s "$0")")
1313
DOCS_OPS_PATH="$SCRIPT_PATH/.."
14-
INC_PATH="$DOCS_OPS_PATH/../../"
15-
BENCHMARKS_PATH="$INC_PATH/scijava-ops-benchmarks"
14+
BASE_PATH="$DOCS_OPS_PATH/../../"
15+
BENCHMARKS_PATH="$BASE_PATH/scijava-ops-benchmarks"
1616
BENCH_OUT_FILE=scijava-ops-benchmarks_results.json
1717
BENCH_OUT_PATH=$(realpath -s "$DOCS_OPS_PATH/$BENCH_OUT_FILE")
1818

@@ -24,8 +24,8 @@ then
2424
else
2525
echo
2626
echo '=== BUILDING THE CODE ==='
27-
cd "$INC_PATH"
28-
mvn -Denforcer.skip -Dinvoker.skip -Dmaven.test.skip -P benchmarks clean install -pl scijava-ops-benchmarks -am | grep '\(Building.*[0-9]\]\|ERROR\)'
27+
cd "$BASE_PATH"
28+
mvn -Denforcer.skip -Dinvoker.skip -Dmaven.test.skip -P benchmarks clean install -pl scijava-ops-benchmarks -am
2929

3030
echo
3131
echo '=== COPYING DEPENDENCIES ==='

docs/ops/doc/Benchmarks.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ Hardware and Software
88

99
This analysis was performed with the following hardware:
1010

11-
* 2021 Dell OptiPlex 5090 Small Form Factor
12-
* Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
13-
* 64 GB 3200 MHz DDR4 RAM
11+
* Mainboard: Gigabyte Technology Co., Ltd. X570 AORUS PRO WIFI
12+
* CPU: AMD Ryzen 7 3700X × 16
13+
* Memory: 32 GB 3200 MHz DDR4 RAM
1414

1515
The following software components were used:
1616

17-
* Ubuntu 20.04.6 LTS
18-
* Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 20.0.1+9.1 (build 20.0.1+9-jvmci-23.0-b12, mixed mode, sharing)
19-
* SciJava core commit `0b8012b2 <https://github.com/scijava/scijava/commit/0b8012b2b00ba84b0583ef7260fab1be8f251041>`_
17+
* Ubuntu 24.04 LTS
18+
* OpenJDK 64-Bit Server VM Zulu11.72+19-CA (build 11.0.23+9-LTS, mixed mode)
19+
* SciJava core commit `018d03ed <https://github.com/scijava/scijava/commit/018d03edd2c4fd20747b472d87f65a8a7033bfe1>`_
2020
* ImageJ Ops version ``2.0.0``
2121

2222
All benchmarks are executed using the `Java Microbenchmark Harness <https://github.com/openjdk/jmh>`_, using the following parameters:
@@ -119,7 +119,7 @@ Reproducing these Results
119119
1. Create a local copy of the SciJava core from the `GitHub repository <https://github.com/scijava/scijava>`_
120120
2. Ensure you have package manager `Mamba <https://mamba.readthedocs.io/en/latest/installation/mamba-installation.html#fresh-install-recommended>`_ installed.
121121
3. Run the script `docs/ops/bin/benchmark.sh`, which will:
122-
* Create the mamba Environment
122+
* Create the mamba environment
123123
* Build the benchmarking code
124124
* Execute all JMH benchmarks
125125
* Build `plotly <https://plotly.com/>`_ figures for each benchmark

docs/ops/environment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ dependencies:
66
- myst-nb
77
- openjdk=11
88
- plotly
9-
- sphinx
9+
- sphinx=7.2
1010
- sphinx-copybutton
1111
- sphinx_rtd_theme
1212

docs/ops/graph_results.py

Lines changed: 77 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import json
2+
import math
23
import statistics
34

45
import plotly.graph_objects as go
56
import plotly.io as io
7+
from plotly.subplots import make_subplots
68

79
# This script parses JMH benchmarking results into charts developed using plot.ly (https://plotly.com/)
810
# It expects JMH benchmark results be dumped to a file "scijava-ops-benchmark_results.json", within its directory.
@@ -17,54 +19,54 @@
1719
"name": "BenchmarkMatching",
1820
"title": "Basic Op Matching Performance",
1921
"bars": {
20-
"noOps": "Static Method",
21-
"noOpsAdapted": f"Static Method {A}",
22+
"sjOpsAdapted": f"SciJava Ops {A}",
2223
"sjOps": "SciJava Ops",
23-
"sjOpsAdapted": f"SciJava Ops {A}"
24+
"noOpsAdapted": f"Static Method {A}",
25+
"noOps": "Static Method",
2426
}
2527
},
2628
{
2729
"name": "BenchmarkCaching",
2830
"title": "Caching Effects on Op Matching Performance",
2931
"bars": {
30-
"noOps": "Static Method",
32+
"sjOpsWithCache": "SciJava Ops (cached)",
3133
"sjOps": "SciJava Ops",
32-
"sjOpsWithCache": "SciJava Ops (cached)"
34+
"noOps": "Static Method",
3335
}
3436
},
3537
{
3638
"name": "BenchmarkConversion",
3739
"title": "Parameter Conversion Performance",
3840
"bars": {
39-
"noOpsConverted": f"Static Method {C}",
40-
"noOpsAdaptedAndConverted": f"Static Method {AC}",
41+
"sjOpsConvertedAndAdapted": f"SciJava Ops {AC}",
4142
"sjOpsConverted": f"SciJava Ops {C}",
42-
"sjOpsConvertedAndAdapted": f"SciJava Ops {AC}"
43+
"noOpsAdaptedAndConverted": f"Static Method {AC}",
44+
"noOpsConverted": f"Static Method {C}",
4345
}
4446
},
4547
{
4648
"name": "BenchmarkFrameworks",
4749
"title": "Algorithm Execution Performance by Framework",
4850
"bars": {
49-
"noOps": "Static Method",
51+
"ijOps": "ImageJ Ops",
5052
"sjOps": "SciJava Ops",
51-
"ijOps": "ImageJ Ops"
53+
"noOps": "Static Method",
5254
}
5355
},
5456
{
5557
"name": "BenchmarkCombined",
5658
"title": "Combined Performance Metrics",
5759
"bars": {
58-
"noOps": "Static Method",
59-
"noOpsAdapted": f"Static Method {A}",
60-
"noOpsConverted": f"Static Method {C}",
61-
"noOpsAdaptedAndConverted": f"Static Method {AC}",
62-
"sjOpsWithCache": "SciJava Ops (cached)",
63-
"sjOps": "SciJava Ops",
64-
"sjOpsAdapted": f"SciJava Ops {A}",
65-
"sjOpsConverted": f"SciJava Ops {C}",
66-
"sjOpsConvertedAndAdapted": f"SciJava Ops {AC}",
6760
"ijOps": "ImageJ Ops",
61+
"sjOpsConvertedAndAdapted": f"SciJava Ops {AC}",
62+
"sjOpsConverted": f"SciJava Ops {C}",
63+
"sjOpsAdapted": f"SciJava Ops {A}",
64+
"sjOps": "SciJava Ops",
65+
"sjOpsWithCache": "SciJava Ops (cached)",
66+
"noOpsAdaptedAndConverted": f"Static Method {AC}",
67+
"noOpsConverted": f"Static Method {C}",
68+
"noOpsAdapted": f"Static Method {A}",
69+
"noOps": "Static Method",
6870
}
6971
}
7072
]
@@ -87,32 +89,71 @@
8789
name = figure["name"]
8890
print(f"Generating figure for {name}", end="")
8991

90-
x = []
91-
y = []
92-
error_y = []
93-
error_y_minus = []
92+
labels = []
93+
values = []
94+
errors = []
9495

9596
# Add each benchmark in the class
9697
for test, label in figure["bars"].items():
97-
print(f".", end="")
98+
print(".", end="")
9899
result = results[test]
99-
x.append(label)
100-
y.append(result["score"])
101-
error_y.append(result["minmax"][1] - result["score"])
102-
error_y_minus.append(result["score"] - result["minmax"][0])
103-
104-
# Create a bar chart
105-
fig = go.Figure()
106-
fig.add_bar(
107-
x=x,
108-
y=y,
109-
error_y=dict(type='data', array=error_y, arrayminus=error_y_minus),
100+
labels.append(label)
101+
score = result["score"]
102+
values.append(score)
103+
error = [result["minmax"][1] - score, score - result["minmax"][0]]
104+
errors.append(error)
105+
106+
# Create a subplot with shared y-axis
107+
fig = make_subplots(rows=1, cols=2, shared_yaxes=True, horizontal_spacing=0.02)
108+
109+
# Add log scale bars (left side)
110+
fig.add_trace(
111+
go.Bar(
112+
y=labels,
113+
x=values,
114+
orientation='h',
115+
error_x=dict(type='data', symmetric=False, array=[e[0] for e in errors], arrayminus=[e[1] for e in errors]),
116+
name="Log Scale",
117+
marker_color='blue'
118+
),
119+
row=1, col=1
110120
)
121+
122+
# Add linear scale bars (right side)
123+
fig.add_trace(
124+
go.Bar(
125+
y=labels,
126+
x=values,
127+
orientation='h',
128+
error_x=dict(type='data', symmetric=False, array=[e[0] for e in errors], arrayminus=[e[1] for e in errors]),
129+
name="Linear Scale",
130+
marker_color='red'
131+
),
132+
row=1, col=2
133+
)
134+
135+
# Update layout
111136
fig.update_layout(
112137
title_text=figure["title"] + f"<br><sup style=\"color: gray\">{A}=Adaptation, {C}=Conversion, {AC}=Adaptation & Conversion</sup>",
113-
yaxis_title="<b>Performance (&mu;s/execution)</b>"
138+
barmode='relative',
139+
yaxis=dict(title=""),
140+
#xaxis=dict(title="Log Scale (μs/execution)", type="log"),
141+
xaxis=dict(
142+
title="Log Scale (μs/execution)",
143+
type="log",
144+
range=[min(values), max(values)],
145+
),
146+
xaxis2=dict(title="Linear Scale (μs/execution)"),
147+
height=max(500, 50 * len(labels)), # Adjust height based on number of bars
148+
showlegend=False
114149
)
115150

151+
# Add a vertical line at x=0
152+
fig.add_vline(x=0, line_width=2, line_color="black")
153+
154+
# Reverse the log scale axis
155+
fig.update_xaxes(autorange="reversed", row=1, col=1)
156+
116157
# Convert to JSON and dump
117158
with open(f"images/{name}.json", "w") as f:
118159
f.write(io.to_json(fig))

docs/ops/images/BenchmarkCaching.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/ops/images/BenchmarkCombined.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/ops/images/BenchmarkConversion.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/ops/images/BenchmarkFrameworks.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/ops/images/BenchmarkMatching.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,13 @@
102102
<maven.deploy.skip>true</maven.deploy.skip>
103103
<maven.install.skip>true</maven.install.skip>
104104
</properties>
105+
106+
<profiles>
107+
<profile>
108+
<id>benchmarks</id>
109+
<modules>
110+
<module>scijava-ops-benchmarks</module>
111+
</modules>
112+
</profile>
113+
</profiles>
105114
</project>

0 commit comments

Comments
 (0)