This project benchmarks different trace ID generation methods:
- Java's
UUID.randomUUID() - OpenTelemetry's
RandomIdGenerator
The benchmark compares both string and raw byte generation performance for:
- UUID.randomUUID() - standard Java UUID generation
- OpenTelemetry RandomIdGenerator - used in OpenTelemetry for trace ID generation
RandomIdGenerator.generateTraceId() is ~17x faster than UUID.randomUUID().toString() when running experiments with a single JMH thread while it is ~150x faster in experiments run with 10 JMH threads (i.e. typical web application settings). Jump to results on my machine.
- Java 17 or later
- Gradle 9.x or later
- Clone this repository
- Run the benchmark:
./gradlew clean jmhReport -Pjmh.threads=10
The benchmark includes four test scenarios:
uuidBasedTraceId- MeasuresUUID.randomUUID().toString()openTelemetryTraceId- MeasuresRandomIdGenerator.generateTraceId()
Configuration:
- Warmup: 5 iterations
- Measurement: 10 iterations
- Forks: 2
- Modes: Average Time and Throughput
- Time Unit: Nanoseconds
- Threads: Default 1 threads which can be overriden by
-Pjmh.threads=<numberOfThreads>
Benchmark results are generated in two formats:
- JSON format:
build/reports/jmh/results.json - HTML report:
build/reports/jmh/index.html
The benchmark measures:
- Average Time (ns): Lower is better
- Throughput (ops/ns): Higher is better
Key metrics to look for:
- Score: The primary measurement result
- Error: The statistical error margin
- Units: The measurement unit (ns/op for time, ops/ns for throughput)
Infrastructure:
- Hardware: Apple M3 Pro 18 GB
- OS: 26.0.1 Java Settings:
- Default:
- Available processors: 11
- Max memory: 4608MB
- Overrides:
java.security.egd=''to force usingDRBGforSecureRandomimplementation used byUUID.
| Benchmark | Mode | Cnt | Score | Error | Units |
|---|---|---|---|---|---|
| TraceIdGeneratorBenchmark.openTelemetryTraceId | thrpt | 20 | 0.069 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | thrpt | 20 | 0.004 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.openTelemetryTraceId | avgt | 20 | 14.321 | ± 0.130 | ns/op |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | avgt | 20 | 247.141 | ± 8.476 | ns/op |
JMH threads: 1 and JVM version: JDK 21.0.9, OpenJDK 64-Bit Server VM, 21.0.9+10-LTS (Zulu21.46+19-CA)
| Benchmark | Mode | Cnt | Score | Error | Units |
|---|---|---|---|---|---|
| TraceIdGeneratorBenchmark.openTelemetryTraceId | thrpt | 20 | 0.069 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | thrpt | 20 | 0.004 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.openTelemetryTraceId | avgt | 20 | 14.528 | ± 0.474 | ns/op |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | avgt | 20 | 245.351 | ± 14.737 | ns/op |
JMH threads: 1 and JVM version: JDK 17.0.17, OpenJDK 64-Bit Server VM, 17.0.17+10-LTS (Zulu17.62+17-CA)
| Benchmark | Mode | Cnt | Score | Error | Units |
|---|---|---|---|---|---|
| TraceIdGeneratorBenchmark.openTelemetryTraceId | thrpt | 20 | 0.070 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | thrpt | 20 | 0.001 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.openTelemetryTraceId | avgt | 20 | 14.414 | ± 0.241 | ns/op |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | avgt | 20 | 862.166 | ± 13.122 | ns/op |
| Benchmark | Mode | Cnt | Score | Error | Units |
|---|---|---|---|---|---|
| TraceIdGeneratorBenchmark.openTelemetryTraceId | thrpt | 20 | 0.420 | ± 0.007 | ops/ns |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | thrpt | 20 | 0.003 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.openTelemetryTraceId | avgt | 20 | 24.967 | ± 1.525 | ns/op |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | avgt | 20 | 3761.317 | ± 65.991 | ns/op |
JMH threads: 10 and JVM version: JDK 21.0.9, OpenJDK 64-Bit Server VM, 21.0.9+10-LTS (Zulu21.46+19-CA)
| Benchmark | Mode | Cnt | Score | Error | Units |
|---|---|---|---|---|---|
| TraceIdGeneratorBenchmark.openTelemetryTraceId | thrpt | 20 | 0.417 | ± 0.021 | ops/ns |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | thrpt | 20 | 0.003 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.openTelemetryTraceId | avgt | 20 | 23.517 | ± 1.003 | ns/op |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | avgt | 20 | 4032.508 | ± 176.588 | ns/op |
JMH threads: 10 and JVM version: JDK 17.0.17, OpenJDK 64-Bit Server VM, 17.0.17+10-LTS (Zulu17.62+17-CA)
| Benchmark | Mode | Cnt | Score | Error | Units |
|---|---|---|---|---|---|
| TraceIdGeneratorBenchmark.openTelemetryTraceId | thrpt | 20 | 0.435 | ± 0.009 | ops/ns |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | thrpt | 20 | 0.001 | ± 0.001 | ops/ns |
| TraceIdGeneratorBenchmark.openTelemetryTraceId | avgt | 20 | 23.236 | ± 0.393 | ns/op |
| TraceIdGeneratorBenchmark.uuidBasedTraceId | avgt | 20 | 12327.410 | ± 886.314 | ns/op |
- The benchmarks use JMH's Blackhole to prevent dead code elimination
- Each benchmark is run in isolated JVM forks to prevent cross-contamination
MIT License