Merged
Conversation
BenchmarksBenchmarks Report for benchmark platform 🐌Benchmarks for #7869 compared to master:
The following thresholds were used for comparing the benchmark speeds:
Allocation changes below 0.5% are ignored. Benchmark detailsBenchmarks.Trace.ActivityBenchmark - Same speed ✔️ Same allocations ✔️Raw results
Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️Raw results
Benchmarks.Trace.Asm.AppSecBodyBenchmark - Same speed ✔️ Same allocations ✔️Raw results
Benchmarks.Trace.Asm.AppSecEncoderBenchmark - Same speed ✔️ Same allocations ✔️Raw results
Benchmarks.Trace.Asm.AppSecWafBenchmark - Same speed ✔️ Fewer allocations 🎉
|
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack‑net6.0 | 3.5 KB | 2.83 KB | -672 B | -19.18% |
| Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmark‑net472 | 8.19 KB | 0 b | -8.19 KB | -100.00% |
| Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack‑net472 | 8.19 KB | 0 b | -8.19 KB | -100.00% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | RunWafRealisticBenchmark |
net6.0 | 457μs | 3.08μs | 30.6μs | 0 | 0 | 0 | 5.48 KB |
| master | RunWafRealisticBenchmark |
netcoreapp3.1 | 496μs | 4.32μs | 42.1μs | 0 | 0 | 0 | 4.58 KB |
| master | RunWafRealisticBenchmark |
net472 | 503μs | 607ns | 2.27μs | 0 | 0 | 0 | 8.19 KB |
| master | RunWafRealisticBenchmarkWithAttack |
net6.0 | 311μs | 778ns | 2.81μs | 0 | 0 | 0 | 3.5 KB |
| master | RunWafRealisticBenchmarkWithAttack |
netcoreapp3.1 | 352μs | 3.19μs | 31μs | 0 | 0 | 0 | 2.32 KB |
| master | RunWafRealisticBenchmarkWithAttack |
net472 | 371μs | 373ns | 1.29μs | 0 | 0 | 0 | 8.19 KB |
| #7869 | RunWafRealisticBenchmark |
net6.0 | 424μs | 1.2μs | 4.32μs | 0 | 0 | 0 | 5.48 KB |
| #7869 | RunWafRealisticBenchmark |
netcoreapp3.1 | 476μs | 3.51μs | 33.4μs | 0 | 0 | 0 | 4.58 KB |
| #7869 | RunWafRealisticBenchmark |
net472 | 499μs | 667ns | 2.58μs | 0 | 0 | 0 | 0 b |
| #7869 | RunWafRealisticBenchmarkWithAttack |
net6.0 | 320μs | 762ns | 2.75μs | 0 | 0 | 0 | 2.83 KB |
| #7869 | RunWafRealisticBenchmarkWithAttack |
netcoreapp3.1 | 325μs | 1.46μs | 5.47μs | 0 | 0 | 0 | 2.32 KB |
| #7869 | RunWafRealisticBenchmarkWithAttack |
net472 | 373μs | 590ns | 2.29μs | 0 | 0 | 0 | 0 b |
Benchmarks.Trace.AspNetCoreBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendRequest |
net6.0 | 61.4μs | 113ns | 422ns | 0 | 0 | 0 | 14.52 KB |
| master | SendRequest |
netcoreapp3.1 | 71.1μs | 70.2ns | 253ns | 0 | 0 | 0 | 17.42 KB |
| master | SendRequest |
net472 | 0.00553ns | 0.00212ns | 0.00822ns | 0 | 0 | 0 | 0 b |
| #7869 | SendRequest |
net6.0 | 61.6μs | 38.2ns | 143ns | 0 | 0 | 0 | 14.52 KB |
| #7869 | SendRequest |
netcoreapp3.1 | 72.4μs | 324ns | 1.59μs | 0 | 0 | 0 | 17.42 KB |
| #7869 | SendRequest |
net472 | 0.151ns | 0.0059ns | 0.0229ns | 0 | 0 | 0 | 0 b |
Benchmarks.Trace.CharSliceBenchmark - Same speed ✔️ Fewer allocations 🎉
Fewer allocations 🎉 in #7869
Benchmark
Base Allocated
Diff Allocated
Change
Change %
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice‑net6.0
976 B
640 B
-336 B
-34.43%
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice‑net472
8.19 KB
0 b
-8.19 KB
-100.00%
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool‑net472
8.19 KB
0 b
-8.19 KB
-100.00%
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice‑net6.0 | 976 B | 640 B | -336 B | -34.43% |
| Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice‑net472 | 8.19 KB | 0 b | -8.19 KB | -100.00% |
| Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool‑net472 | 8.19 KB | 0 b | -8.19 KB | -100.00% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | OriginalCharSlice |
net6.0 | 1.89ms | 907ns | 3.51μs | 0 | 0 | 0 | 640.3 KB |
| master | OriginalCharSlice |
netcoreapp3.1 | 3.97ms | 1.68μs | 6.27μs | 0 | 0 | 0 | 640.1 KB |
| master | OriginalCharSlice |
net472 | 2.64ms | 648ns | 2.42μs | 0 | 0 | 0 | 647.17 KB |
| master | OptimizedCharSlice |
net6.0 | 1.4ms | 554ns | 2.07μs | 0 | 0 | 0 | 976 B |
| master | OptimizedCharSlice |
netcoreapp3.1 | 2.82ms | 905ns | 3.39μs | 0 | 0 | 0 | 104 B |
| master | OptimizedCharSlice |
net472 | 1.99ms | 996ns | 3.59μs | 0 | 0 | 0 | 8.19 KB |
| master | OptimizedCharSliceWithPool |
net6.0 | 1.01ms | 347ns | 1.3μs | 0 | 0 | 0 | 304 B |
| master | OptimizedCharSliceWithPool |
netcoreapp3.1 | 2ms | 2.03μs | 7.88μs | 0 | 0 | 0 | 104 B |
| master | OptimizedCharSliceWithPool |
net472 | 1.15ms | 639ns | 2.39μs | 0 | 0 | 0 | 8.19 KB |
| #7869 | OriginalCharSlice |
net6.0 | 2.07ms | 1.04μs | 3.89μs | 0 | 0 | 0 | 640.64 KB |
| #7869 | OriginalCharSlice |
netcoreapp3.1 | 4.01ms | 1.35μs | 5.05μs | 0 | 0 | 0 | 640.1 KB |
| #7869 | OriginalCharSlice |
net472 | 2.72ms | 1.52μs | 5.68μs | 0 | 0 | 0 | 647.17 KB |
| #7869 | OptimizedCharSlice |
net6.0 | 1.44ms | 775ns | 3μs | 0 | 0 | 0 | 640 B |
| #7869 | OptimizedCharSlice |
netcoreapp3.1 | 2.81ms | 425ns | 1.53μs | 0 | 0 | 0 | 104 B |
| #7869 | OptimizedCharSlice |
net472 | 2.04ms | 834ns | 3.12μs | 0 | 0 | 0 | 0 b |
| #7869 | OptimizedCharSliceWithPool |
net6.0 | 1.01ms | 441ns | 1.65μs | 0 | 0 | 0 | 304 B |
| #7869 | OptimizedCharSliceWithPool |
netcoreapp3.1 | 1.86ms | 1.77μs | 6.6μs | 0 | 0 | 0 | 104 B |
| #7869 | OptimizedCharSliceWithPool |
net472 | 1.14ms | 625ns | 2.42μs | 0 | 0 | 0 | 0 b |
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Same speed ✔️ More allocations ⚠️
More allocations ⚠️ in #7869
Benchmark
Base Allocated
Diff Allocated
Change
Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net6.0
41.71 KB
42.08 KB
362 B
0.87%
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net6.0 | 41.71 KB | 42.08 KB | 362 B | 0.87% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | WriteAndFlushEnrichedTraces |
net6.0 | 685μs | 1.86μs | 7.21μs | 0 | 0 | 0 | 41.71 KB |
| master | WriteAndFlushEnrichedTraces |
netcoreapp3.1 | 627μs | 903ns | 3.5μs | 0 | 0 | 0 | 41.98 KB |
| master | WriteAndFlushEnrichedTraces |
net472 | 832μs | 1.3μs | 4.88μs | 8.33 | 0 | 0 | 56.18 KB |
| #7869 | WriteAndFlushEnrichedTraces |
net6.0 | 748μs | 1.22μs | 4.55μs | 0 | 0 | 0 | 42.08 KB |
| #7869 | WriteAndFlushEnrichedTraces |
netcoreapp3.1 | 643μs | 768ns | 2.66μs | 0 | 0 | 0 | 42.04 KB |
| #7869 | WriteAndFlushEnrichedTraces |
net472 | 884μs | 2.85μs | 10.7μs | 8.33 | 0 | 0 | 55.91 KB |
Benchmarks.Trace.DbCommandBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | ExecuteNonQuery |
net6.0 | 1.93μs | 9.98ns | 47.9ns | 0 | 0 | 0 | 1.02 KB |
| master | ExecuteNonQuery |
netcoreapp3.1 | 2.47μs | 11.2ns | 40.5ns | 0 | 0 | 0 | 1.02 KB |
| master | ExecuteNonQuery |
net472 | 2.71μs | 1.89ns | 7.31ns | 0.15 | 0 | 0 | 987 B |
| #7869 | ExecuteNonQuery |
net6.0 | 1.88μs | 9.23ns | 40.2ns | 0 | 0 | 0 | 1.02 KB |
| #7869 | ExecuteNonQuery |
netcoreapp3.1 | 2.63μs | 6.08ns | 23.6ns | 0 | 0 | 0 | 1.02 KB |
| #7869 | ExecuteNonQuery |
net472 | 2.69μs | 1.7ns | 6.14ns | 0.149 | 0 | 0 | 987 B |
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | CallElasticsearch |
net6.0 | 1.76μs | 8.03ns | 30ns | 0 | 0 | 0 | 1.03 KB |
| master | CallElasticsearch |
netcoreapp3.1 | 2.23μs | 11.7ns | 56.2ns | 0 | 0 | 0 | 1.03 KB |
| master | CallElasticsearch |
net472 | 3.57μs | 3.38ns | 13.1ns | 0.16 | 0 | 0 | 1.04 KB |
| master | CallElasticsearchAsync |
net6.0 | 1.79μs | 8.33ns | 32.3ns | 0 | 0 | 0 | 1.01 KB |
| master | CallElasticsearchAsync |
netcoreapp3.1 | 2.44μs | 8.58ns | 33.2ns | 0 | 0 | 0 | 1.08 KB |
| master | CallElasticsearchAsync |
net472 | 3.71μs | 1.19ns | 4.6ns | 0.165 | 0 | 0 | 1.1 KB |
| #7869 | CallElasticsearch |
net6.0 | 1.77μs | 5.01ns | 18.7ns | 0 | 0 | 0 | 1.03 KB |
| #7869 | CallElasticsearch |
netcoreapp3.1 | 2.24μs | 11.1ns | 47ns | 0 | 0 | 0 | 1.03 KB |
| #7869 | CallElasticsearch |
net472 | 3.47μs | 5.42ns | 21ns | 0.157 | 0 | 0 | 1.04 KB |
| #7869 | CallElasticsearchAsync |
net6.0 | 1.84μs | 8.98ns | 38.1ns | 0 | 0 | 0 | 1.01 KB |
| #7869 | CallElasticsearchAsync |
netcoreapp3.1 | 2.38μs | 12.2ns | 58.6ns | 0 | 0 | 0 | 1.08 KB |
| #7869 | CallElasticsearchAsync |
net472 | 3.77μs | 1.41ns | 5.26ns | 0.168 | 0 | 0 | 1.1 KB |
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | ExecuteAsync |
net6.0 | 1.82μs | 5.61ns | 21.7ns | 0 | 0 | 0 | 952 B |
| master | ExecuteAsync |
netcoreapp3.1 | 2.35μs | 10.9ns | 43.4ns | 0 | 0 | 0 | 952 B |
| master | ExecuteAsync |
net472 | 2.67μs | 3.16ns | 12.2ns | 0.133 | 0 | 0 | 915 B |
| #7869 | ExecuteAsync |
net6.0 | 1.79μs | 6.52ns | 25.2ns | 0 | 0 | 0 | 952 B |
| #7869 | ExecuteAsync |
netcoreapp3.1 | 2.4μs | 8.52ns | 33ns | 0 | 0 | 0 | 952 B |
| #7869 | ExecuteAsync |
net472 | 2.65μs | 0.991ns | 3.84ns | 0.133 | 0 | 0 | 915 B |
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendAsync |
net6.0 | 6.79μs | 10ns | 38.9ns | 0 | 0 | 0 | 2.36 KB |
| master | SendAsync |
netcoreapp3.1 | 8.96μs | 35ns | 135ns | 0 | 0 | 0 | 2.9 KB |
| master | SendAsync |
net472 | 12.2μs | 10.5ns | 40.6ns | 0.488 | 0 | 0 | 3.18 KB |
| #7869 | SendAsync |
net6.0 | 6.88μs | 10.5ns | 37.8ns | 0 | 0 | 0 | 2.36 KB |
| #7869 | SendAsync |
netcoreapp3.1 | 8.58μs | 30.8ns | 111ns | 0 | 0 | 0 | 2.9 KB |
| #7869 | SendAsync |
net472 | 12.4μs | 13.1ns | 48.9ns | 0.497 | 0 | 0 | 3.18 KB |
Benchmarks.Trace.Iast.StringAspectsBenchmark - Same speed ✔️ More allocations ⚠️
More allocations ⚠️ in #7869
Benchmark
Base Allocated
Diff Allocated
Change
Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net472
57.34 KB
65.54 KB
8.19 KB
14.29%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net6.0
250.62 KB
259.52 KB
8.9 KB
3.55%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net6.0
43.36 KB
44.84 KB
1.48 KB
3.41%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net472
278.53 KB
286.72 KB
8.19 KB
2.94%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1
272.86 KB
276.57 KB
3.71 KB
1.36%
Fewer allocations 🎉 in #7869
Benchmark
Base Allocated
Diff Allocated
Change
Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑netcoreapp3.1
44.04 KB
42.85 KB
-1.19 KB
-2.71%
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net472 | 57.34 KB | 65.54 KB | 8.19 KB | 14.29% |
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net6.0 | 250.62 KB | 259.52 KB | 8.9 KB | 3.55% |
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net6.0 | 43.36 KB | 44.84 KB | 1.48 KB | 3.41% |
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net472 | 278.53 KB | 286.72 KB | 8.19 KB | 2.94% |
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1 | 272.86 KB | 276.57 KB | 3.71 KB | 1.36% |
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑netcoreapp3.1 | 44.04 KB | 42.85 KB | -1.19 KB | -2.71% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | StringConcatBenchmark |
net6.0 | 45μs | 249ns | 1.41μs | 0 | 0 | 0 | 43.36 KB |
| master | StringConcatBenchmark |
netcoreapp3.1 | 48.4μs | 200ns | 720ns | 0 | 0 | 0 | 44.04 KB |
| master | StringConcatBenchmark |
net472 | 57.5μs | 127ns | 459ns | 0 | 0 | 0 | 57.34 KB |
| master | StringConcatAspectBenchmark |
net6.0 | 445μs | 2.37μs | 12.1μs | 0 | 0 | 0 | 250.62 KB |
| master | StringConcatAspectBenchmark |
netcoreapp3.1 | 528μs | 2.53μs | 10.1μs | 0 | 0 | 0 | 272.86 KB |
| master | StringConcatAspectBenchmark |
net472 | 411μs | 2.21μs | 12.5μs | 0 | 0 | 0 | 278.53 KB |
| #7869 | StringConcatBenchmark |
net6.0 | 44.3μs | 195ns | 703ns | 0 | 0 | 0 | 44.84 KB |
| #7869 | StringConcatBenchmark |
netcoreapp3.1 | 55.2μs | 1.03μs | 10.1μs | 0 | 0 | 0 | 42.85 KB |
| #7869 | StringConcatBenchmark |
net472 | 57.3μs | 220ns | 853ns | 0 | 0 | 0 | 65.54 KB |
| #7869 | StringConcatAspectBenchmark |
net6.0 | 459μs | 2.04μs | 7.36μs | 0 | 0 | 0 | 259.52 KB |
| #7869 | StringConcatAspectBenchmark |
netcoreapp3.1 | 545μs | 1.39μs | 5.57μs | 0 | 0 | 0 | 276.57 KB |
| #7869 | StringConcatAspectBenchmark |
net472 | 404μs | 2.1μs | 9.85μs | 0 | 0 | 0 | 286.72 KB |
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net6.0 | 2.64μs | 13.6ns | 67.9ns | 0 | 0 | 0 | 1.7 KB |
| master | EnrichedLog |
netcoreapp3.1 | 3.56μs | 15.7ns | 60.6ns | 0 | 0 | 0 | 1.7 KB |
| master | EnrichedLog |
net472 | 3.82μs | 2.9ns | 11.2ns | 0.245 | 0 | 0 | 1.64 KB |
| #7869 | EnrichedLog |
net6.0 | 2.67μs | 14ns | 68.7ns | 0 | 0 | 0 | 1.7 KB |
| #7869 | EnrichedLog |
netcoreapp3.1 | 3.6μs | 16.6ns | 68.4ns | 0 | 0 | 0 | 1.7 KB |
| #7869 | EnrichedLog |
net472 | 3.97μs | 5.1ns | 19.1ns | 0.259 | 0 | 0 | 1.64 KB |
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net6.0 | 124μs | 129ns | 483ns | 0 | 0 | 0 | 4.31 KB |
| master | EnrichedLog |
netcoreapp3.1 | 127μs | 70.9ns | 256ns | 0 | 0 | 0 | 4.31 KB |
| master | EnrichedLog |
net472 | 168μs | 128ns | 495ns | 0 | 0 | 0 | 4.52 KB |
| #7869 | EnrichedLog |
net6.0 | 124μs | 473ns | 1.77μs | 0 | 0 | 0 | 4.31 KB |
| #7869 | EnrichedLog |
netcoreapp3.1 | 129μs | 199ns | 743ns | 0 | 0 | 0 | 4.31 KB |
| #7869 | EnrichedLog |
net472 | 167μs | 65.9ns | 255ns | 0 | 0 | 0 | 4.52 KB |
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net6.0 | 4.91μs | 23.1ns | 92.4ns | 0 | 0 | 0 | 2.26 KB |
| master | EnrichedLog |
netcoreapp3.1 | 6.93μs | 26.5ns | 103ns | 0 | 0 | 0 | 2.26 KB |
| master | EnrichedLog |
net472 | 7.38μs | 5.92ns | 22.9ns | 0.297 | 0 | 0 | 2.08 KB |
| #7869 | EnrichedLog |
net6.0 | 5.05μs | 22.8ns | 88.2ns | 0 | 0 | 0 | 2.26 KB |
| #7869 | EnrichedLog |
netcoreapp3.1 | 6.93μs | 24ns | 93ns | 0 | 0 | 0 | 2.26 KB |
| #7869 | EnrichedLog |
net472 | 7.42μs | 7.32ns | 28.3ns | 0.296 | 0 | 0 | 2.08 KB |
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendReceive |
net6.0 | 1.94μs | 8.91ns | 34.5ns | 0 | 0 | 0 | 1.2 KB |
| master | SendReceive |
netcoreapp3.1 | 2.54μs | 10.8ns | 41.9ns | 0 | 0 | 0 | 1.2 KB |
| master | SendReceive |
net472 | 2.96μs | 2.36ns | 8.82ns | 0.191 | 0 | 0 | 1.2 KB |
| #7869 | SendReceive |
net6.0 | 1.98μs | 10ns | 46.9ns | 0 | 0 | 0 | 1.2 KB |
| #7869 | SendReceive |
netcoreapp3.1 | 2.5μs | 12.1ns | 50ns | 0 | 0 | 0 | 1.2 KB |
| #7869 | SendReceive |
net472 | 3.07μs | 5.82ns | 22.5ns | 0.182 | 0 | 0 | 1.2 KB |
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net6.0 | 4.29μs | 1.1ns | 4.11ns | 0 | 0 | 0 | 1.58 KB |
| master | EnrichedLog |
netcoreapp3.1 | 5.94μs | 15.6ns | 60.6ns | 0 | 0 | 0 | 1.63 KB |
| master | EnrichedLog |
net472 | 6.55μs | 5.18ns | 20.1ns | 0.293 | 0 | 0 | 2.03 KB |
| #7869 | EnrichedLog |
net6.0 | 4.43μs | 12.4ns | 46.5ns | 0 | 0 | 0 | 1.58 KB |
| #7869 | EnrichedLog |
netcoreapp3.1 | 5.9μs | 17.5ns | 67.8ns | 0 | 0 | 0 | 1.63 KB |
| #7869 | EnrichedLog |
net472 | 6.63μs | 6.9ns | 26.7ns | 0.298 | 0 | 0 | 2.03 KB |
Benchmarks.Trace.SpanBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | StartFinishSpan |
net6.0 | 790ns | 3.61ns | 14.4ns | 0 | 0 | 0 | 576 B |
| master | StartFinishSpan |
netcoreapp3.1 | 960ns | 0.356ns | 1.38ns | 0 | 0 | 0 | 576 B |
| master | StartFinishSpan |
net472 | 917ns | 0.121ns | 0.471ns | 0.0916 | 0 | 0 | 578 B |
| master | StartFinishScope |
net6.0 | 937ns | 0.434ns | 1.68ns | 0 | 0 | 0 | 696 B |
| master | StartFinishScope |
netcoreapp3.1 | 1.13μs | 5.83ns | 26.7ns | 0 | 0 | 0 | 696 B |
| master | StartFinishScope |
net472 | 1.1μs | 0.186ns | 0.721ns | 0.0993 | 0 | 0 | 658 B |
| #7869 | StartFinishSpan |
net6.0 | 798ns | 0.173ns | 0.647ns | 0 | 0 | 0 | 576 B |
| #7869 | StartFinishSpan |
netcoreapp3.1 | 979ns | 1.1ns | 4.25ns | 0 | 0 | 0 | 576 B |
| #7869 | StartFinishSpan |
net472 | 912ns | 1.19ns | 4.62ns | 0.0914 | 0 | 0 | 578 B |
| #7869 | StartFinishScope |
net6.0 | 952ns | 0.183ns | 0.711ns | 0 | 0 | 0 | 696 B |
| #7869 | StartFinishScope |
netcoreapp3.1 | 1.16μs | 6.22ns | 31.7ns | 0 | 0 | 0 | 697 B |
| #7869 | StartFinishScope |
net472 | 1.11μs | 1.24ns | 4.82ns | 0.101 | 0 | 0 | 658 B |
| #7869 | StartFinishTwoScopes |
net6.0 | 1.69μs | 8.12ns | 31.5ns | 0 | 0 | 0 | 1.19 KB |
| #7869 | StartFinishTwoScopes |
netcoreapp3.1 | 2.12μs | 9.43ns | 35.3ns | 0 | 0 | 0 | 1.19 KB |
| #7869 | StartFinishTwoScopes |
net472 | 2.1μs | 4.27ns | 16.5ns | 0.168 | 0 | 0 | 1.08 KB |
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | RunOnMethodBegin |
net6.0 | 1.08μs | 1.43ns | 5.15ns | 0 | 0 | 0 | 696 B |
| master | RunOnMethodBegin |
netcoreapp3.1 | 1.38μs | 6.5ns | 25.2ns | 0 | 0 | 0 | 696 B |
| master | RunOnMethodBegin |
net472 | 1.44μs | 1.51ns | 5.85ns | 0.101 | 0 | 0 | 658 B |
| #7869 | RunOnMethodBegin |
net6.0 | 1.07μs | 4.23ns | 16.4ns | 0 | 0 | 0 | 696 B |
| #7869 | RunOnMethodBegin |
netcoreapp3.1 | 1.41μs | 7.14ns | 34.3ns | 0 | 0 | 0 | 696 B |
| #7869 | RunOnMethodBegin |
net472 | 1.43μs | 1.65ns | 6.38ns | 0.1 | 0 | 0 | 658 B |
NachoEchevarria
approved these changes
Nov 26, 2025
lucaspimentel
approved these changes
Nov 26, 2025
This was referenced Nov 27, 2025
andrewlock
added a commit
that referenced
this pull request
Dec 3, 2025
## Summary of changes Replace `ArraySegment<Span>` with `SpanCollection` ## Reason for change `ArraySegment<Span>` is a wrapper around an array, and by design, always requires allocating an array. However, if we look at the [distribution of traces](https://app.datadoghq.com/notebook/13270656/partial-flush-worth-it-or-not?computational_onboarding=true&fullscreen_end_ts=1760111663000&fullscreen_paused=true&fullscreen_refresh_mode=paused&fullscreen_start_ts=1759829808000&fullscreen_widget=3c8idtpl) received for processing, we see that 50% of traces only have a single span. Consequently, `SpanCollection` takes a similar approach [to `StringValues`](https://andrewlock.net/a-brief-look-at-stringvalues/), in which it is an abstraction around _either_ a single `Span` _or_ a `Span[]`. This means we can avoid allocating the array entirely until we need to. For small traces (with a single span), this saves 56 Bytes per scope/trace or ~8% of the basic trace size. For larger traces, `SpanCollection` and `ArraySegment<Span>` are essentially identical, so the allocation is the same. Given `SpanCollection` (and `ArraySegment` actually) are `readonly struct`, also added `in` to the signatures (given that both structs are the same size and > pointer size). > The only practical way I could see to actually make `SpanCollection` pointer-sized is to remove the `Count` parameter. But that means we _either_ need to allocate an "ArraySegment" wrapper around the Array, to hold the count, _or_ we always allocate an array of the "correct" length. I explored the latter in a separate PR, using an array pool during the "builder" step, and then allocating an array of the correct size subsequently, but the allocation gains were marginal, and it didn't ## Implementation details The changes are essentially: - `SpanCollection` holds _either_ a `Span` _or_ a `Span[]` (_or_ `null`) - We store this in the same field (much like `StringValues` does), as it reduces the size of the struct which brings small perf benefits - Pass the span around via `in` to reduce chance of defensive copies - Fix/replace uses of Moq which requires different usage for `in`/`ref` fields, and can't provide the same functionality as a stub ## Test coverage Added some unit tests for the implementation, but the important thing is the benchmarks. We see an 8-8.5% reduction in the allocations for create span/create scope: | Benchmark | Base Allocated | Diff Allocated | Change | Change % | |:----------|-----------:|-----------:|--------:|--------:| | Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net6.0 | 696 B | 640 B | -56 B | -8.05% | Benchmarks.Trace.SpanBenchmark.StartFinishScope‑netcoreapp3.1 | 696 B | 640 B | -56 B | -8.05% | Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net472 | 658 B | 602 B | -56 B | -8.51% | Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net472 | 578 B | 522 B | -56 B | -9.69% | Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net6.0 | 576 B | 520 B | -56 B | -9.72% | Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑netcoreapp3.1 | 576 B | 520 B | -56 B | -9.72% Other benchmarks which create a single span see similar improvements. Note that the _two_ scope benchmark (added in #7869) shows essentially no change (as expected). ## Other details I tried a variety of variations on this approach: - Keep separate fields for `Span` and `Span[]` - Nicer as it's type safe again, but increases allocations (by a pointer) so prob not worth it as this is hot path - Don't pass via `in` - Slows things down slightly - Remove the `Count` field (and make `SpanCollection` pointer-sized) - Requires allocating exact-sized arrays, so not practical to handle array growth - Same as above, but use an array pool for the build stage, and then only allocate the fixed size on close - Does show improvements in allocation, but more complexity. May be worth considering (I'll create a separate PR for it) - Don't have a builder, just use an array pool + a Count field, and rely on reliably cleaning up the pooling, https://datadoghq.atlassian.net/browse/LANGPLAT-841
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of changes
Reason for change
We have a benchmark for creating a span, and a scope, but I'm working on some perf improvements, and I want to be able to see the improvements specifically when there are two scopes in a trace.
Implementation details
Add a new simple benchmark
Test coverage
Not really, this is so that there's something to compare against in my update!