Skip to content

Conversation

@mhl-b
Copy link
Contributor

@mhl-b mhl-b commented Jan 10, 2026

A different view on RecyclerBytesStreamOutput write benchmark. Existing RecyclerBytesStreamOutputBenchmark measures complex randomized input covering multiple paths. I think there is value in measuring individual hot-paths with simple inputs, especially in case of VInt there is an optimization for 1-byte int.

Differences from RecyclerBytesStreamOutputBenchmark:

  • Measure throughput, not average time. RecyclerBytesStreamOutput has page recycling amortized cost that impacts individual writes. Throughput-mode smoothes these spikes.
  • Constant folding. Despite randomized input, this input stays the same on every iteration of RecyclerBytesStreamOutput. I use constant values with blackholes.

Currently covers only VInt's but easy to extend for other methods.

Example run

./gradlew -p benchmarks run --args 'RecyclerBytesStreamOutputWriteBenchmark'

Benchmark                                            Mode  Cnt   Score   Error   Units
RecyclerBytesStreamOutputWriteBenchmark.writeVInt1  thrpt    5  77.812 ± 0.759  ops/ms
RecyclerBytesStreamOutputWriteBenchmark.writeVInt2  thrpt    5  61.969 ± 4.399  ops/ms
RecyclerBytesStreamOutputWriteBenchmark.writeVInt3  thrpt    5  45.292 ± 3.572  ops/ms
RecyclerBytesStreamOutputWriteBenchmark.writeVInt4  thrpt    5  32.945 ± 1.035  ops/ms

@mhl-b mhl-b requested a review from DaveCTurner January 10, 2026 02:43
@mhl-b mhl-b added >non-issue Team:Distributed Coordination Meta label for Distributed Coordination team :Distributed Coordination/Distributed A catch all label for anything in the Distributed Coordination area. Please avoid if you can. labels Jan 10, 2026
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-distributed-coordination (Team:Distributed Coordination)

Comment on lines +28 to +29
// throughput is more representable metric, it amortizes pages recycling code path and reduces benchmark error
@BenchmarkMode(Mode.Throughput)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my education, what is the difference here? Is it more than just turning the fraction over so it reports the average of operations-per-unit-time vs time-per-unit operation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's "just" turning fraction over. https://javadoc.io/doc/org.openjdk.jmh/jmh-core/1.29/org/openjdk/jmh/annotations/Mode.html#Throughput.

public static final Throughput
Throughput: operations per unit of time.
Runs by continuously calling Benchmark methods, counting the total throughput over all worker threads. This mode is time-based, and it will run until the iteration time expires.

public static final AverageTime
Average time: average time per per operation.
Runs by continuously calling Benchmark methods, counting the average time to call over all worker threads. This is the inverse of Throughput, but with different aggregation policy. This mode is time-based, and it will run until the iteration time expires.


// must not be final - avoid constant fold
// see https://github.com/openjdk/jmh/blob/master/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_10_ConstantFold.java
private int vint1 = 2;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it need to be fixed or could it be any value from 1 to 127? Should be the same code anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be any from 1 to 127. As long it's not final JMH should be able properly blackhole this property.

Comment on lines +41 to +43
private int vint2 = vint1 << 8;
private int vint3 = vint2 << 8;
private int vint4 = vint3 << 8;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vint shifts by 7 bits, not 8, and there's a 5-byte case to consider too (either very large or negative)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I keep forgetting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Distributed Coordination/Distributed A catch all label for anything in the Distributed Coordination area. Please avoid if you can. >non-issue Team:Distributed Coordination Meta label for Distributed Coordination team v9.4.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants