Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PushStream support to IApiRequest and support chunked-encoding #4989

Merged
merged 9 commits into from
Dec 28, 2023

Conversation

andrewlock
Copy link
Member

@andrewlock andrewlock commented Dec 19, 2023

Summary of changes

  • Adds PushStream support to IApiRequest (in contrast to "pull" Stream support)
  • Add support for writing Transfer-Encoding: chunked with the DatadogHttpClient (UDS <.NET 6/Named Pipes)
  • Add support for reading chunked encoding in the MockTracerAgent (named pipes/UDS)

Reason for change

We don't want to buffer the whole debug log stream in memory as it could be quite large. Unfortunately, our IApiRequest implementations (and even HttpClient itself AFAICT) don't currently support writing to the request stream directly - they all allow reading (pulling) from a Stream, but not pushing to the request stream.

As soon as we enable streaming like that, we need to stop sending content-length (because we don't know it up-front) and use Transfer-Encoding: chunked to send the body of the request.

With chunked encoding, you send the number of bytes in the chunk (encoded as hex), followed by \r\n, then the chunk itself, and finally \r\n. You signify the end of the body by sending a 0-length chunk, e.g.

1E
++++++++++++++++++++++++++++++
1E
++++++++++++++++++++++++++++++
1E
++++++++++++++++++++++++++++++
0

Implementation details

Started by vendoring in PushStreamContent which basically does what we want, and then simplified it by cutting out all the extra cruft and use-cases we don't need. Created something similar for our custom HttpClient

For the chunked encoding writer I based it on the .NET 8 HttpClient implementation with some workarounds for missing APIs.

For the chunked reader I just rolled with something new because it's only used in tests, so if it works for us, that's probably good enough.

Test coverage

Added some unit tests for the chunked reader and writer, but the new APIs are actually tested properly in subsequent stacked PRs.

Other details

Note that tranfer-encoding: chunked isn't supported in HTTP/2.0. I can't see that causing issues for us at this point, just wanted to flag it.

Prerequisite for other stacked PRs

Stacked on

@datadog-ddstaging
Copy link

datadog-ddstaging bot commented Dec 19, 2023

Datadog Report

Branch report: andrew/tracer_flare/chunked_encoding
Commit report: 7d3b360

dd-trace-dotnet: 0 Failed, 0 New Flaky, 303814 Passed, 992 Skipped, 41m 32.05s Wall Time

@andrewlock
Copy link
Member Author

andrewlock commented Dec 19, 2023

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing the following branches/commits:

Execution-time benchmarks measure the whole time it takes to execute a program. And are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are shown in red. The following thresholds were used for comparing the execution times:

  • Welch test with statistical test for significance of 5%
  • Only results indicating a difference greater than 5% and 5 ms are considered.

Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard.

Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph).

gantt
    title Execution time (ms) FakeDbCommand (.NET Framework 4.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (4989) - mean (72ms)  : 62, 82
     .   : milestone, 72,
    master - mean (71ms)  : 63, 80
     .   : milestone, 71,

    section CallTarget+Inlining+NGEN
    This PR (4989) - mean (1,032ms)  : 1014, 1050
     .   : milestone, 1032,
    master - mean (1,018ms)  : 1001, 1034
     .   : milestone, 1018,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (4989) - mean (106ms)  : 104, 109
     .   : milestone, 106,
    master - mean (106ms)  : 102, 110
     .   : milestone, 106,

    section CallTarget+Inlining+NGEN
    This PR (4989) - mean (734ms)  : 715, 753
     .   : milestone, 734,
    master - mean (721ms)  : 699, 744
     .   : milestone, 721,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (4989) - mean (91ms)  : 89, 93
     .   : milestone, 91,
    master - mean (90ms)  : 83, 96
     .   : milestone, 90,

    section CallTarget+Inlining+NGEN
    This PR (4989) - mean (699ms)  : 678, 719
     .   : milestone, 699,
    master - mean (692ms)  : 671, 714
     .   : milestone, 692,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (4989) - mean (189ms)  : 186, 192
     .   : milestone, 189,
    master - mean (188ms)  : 186, 191
     .   : milestone, 188,

    section CallTarget+Inlining+NGEN
    This PR (4989) - mean (1,130ms)  : 1110, 1151
     .   : milestone, 1130,
    master - mean (1,126ms)  : 1098, 1154
     .   : milestone, 1126,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (4989) - mean (273ms)  : 270, 277
     .   : milestone, 273,
    master - mean (273ms)  : 267, 278
     .   : milestone, 273,

    section CallTarget+Inlining+NGEN
    This PR (4989) - mean (1,082ms)  : 1060, 1105
     .   : milestone, 1082,
    master - mean (1,083ms)  : 1058, 1108
     .   : milestone, 1083,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (4989) - mean (263ms)  : 259, 267
     .   : milestone, 263,
    master - mean (262ms)  : 259, 265
     .   : milestone, 262,

    section CallTarget+Inlining+NGEN
    This PR (4989) - mean (1,055ms)  : 1028, 1082
     .   : milestone, 1055,
    master - mean (1,047ms)  : 1023, 1071
     .   : milestone, 1047,

Loading

@andrewlock
Copy link
Member Author

andrewlock commented Dec 19, 2023

Benchmarks Report 🐌

Benchmarks for #4989 compared to master:

  • 3 benchmarks are faster, with geometric mean 1.290
  • 4 benchmarks are slower, with geometric mean 1.144
  • 1 benchmarks have fewer allocations
  • 1 benchmarks have more allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.ActivityBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartStopWithChild net6.0 8.71μs 48.1ns 289ns 0.0212 0.00849 0 7.48 KB
master StartStopWithChild netcoreapp3.1 10.7μs 52.7ns 303ns 0.0176 0.00587 0 7.58 KB
master StartStopWithChild net472 16.9μs 50.7ns 196ns 1.34 0.362 0.109 7.94 KB
#4989 StartStopWithChild net6.0 8.74μs 49.9ns 349ns 0.0228 0.00911 0 7.48 KB
#4989 StartStopWithChild netcoreapp3.1 10.7μs 53.7ns 279ns 0.0271 0.0108 0 7.58 KB
#4989 StartStopWithChild net472 16.9μs 44.7ns 167ns 1.33 0.34 0.119 7.95 KB
Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 452μs 257ns 994ns 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 627μs 249ns 963ns 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 791μs 429ns 1.55μs 0.391 0 0 3.3 KB
#4989 WriteAndFlushEnrichedTraces net6.0 463μs 133ns 499ns 0 0 0 2.7 KB
#4989 WriteAndFlushEnrichedTraces netcoreapp3.1 645μs 277ns 1.03μs 0 0 0 2.7 KB
#4989 WriteAndFlushEnrichedTraces net472 787μs 235ns 879ns 0.391 0 0 3.3 KB
Benchmarks.Trace.Asm.AppSecBodyBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #4989

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorSimpleBody‑netcoreapp3.1 1.300 234.25 180.23

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master AllCycleSimpleBody net6.0 43.6μs 143ns 554ns 0.0221 0 0 1.77 KB
master AllCycleSimpleBody netcoreapp3.1 46.9μs 45.3ns 163ns 0.0235 0 0 1.74 KB
master AllCycleSimpleBody net472 49.3μs 122ns 471ns 0.269 0 0 1.81 KB
master AllCycleMoreComplexBody net6.0 216μs 89.2ns 334ns 0.108 0 0 9.25 KB
master AllCycleMoreComplexBody netcoreapp3.1 228μs 102ns 381ns 0.112 0 0 9.14 KB
master AllCycleMoreComplexBody net472 239μs 72ns 279ns 1.43 0 0 9.32 KB
master ObjectExtractorSimpleBody net6.0 133ns 0.0263ns 0.0982ns 0.00392 0 0 280 B
master ObjectExtractorSimpleBody netcoreapp3.1 234ns 0.155ns 0.599ns 0.00366 0 0 272 B
master ObjectExtractorSimpleBody net472 153ns 0.113ns 0.437ns 0.0446 0 0 281 B
master ObjectExtractorMoreComplexBody net6.0 2.75μs 0.724ns 2.61ns 0.0539 0 0 3.78 KB
master ObjectExtractorMoreComplexBody netcoreapp3.1 3.64μs 0.857ns 3.21ns 0.0508 0 0 3.69 KB
master ObjectExtractorMoreComplexBody net472 3.54μs 5.65ns 21.9ns 0.602 0.0051 0 3.8 KB
#4989 AllCycleSimpleBody net6.0 42.9μs 20.6ns 71.3ns 0.022 0 0 1.77 KB
#4989 AllCycleSimpleBody netcoreapp3.1 46.1μs 35.9ns 139ns 0 0 0 1.74 KB
#4989 AllCycleSimpleBody net472 50μs 10.3ns 38.5ns 0.272 0 0 1.81 KB
#4989 AllCycleMoreComplexBody net6.0 215μs 148ns 571ns 0.108 0 0 9.25 KB
#4989 AllCycleMoreComplexBody netcoreapp3.1 227μs 73.8ns 286ns 0.112 0 0 9.14 KB
#4989 AllCycleMoreComplexBody net472 240μs 1.22μs 5.47μs 1.43 0 0 9.32 KB
#4989 ObjectExtractorSimpleBody net6.0 138ns 0.0442ns 0.165ns 0.00396 0 0 280 B
#4989 ObjectExtractorSimpleBody netcoreapp3.1 180ns 0.141ns 0.526ns 0.00374 0 0 272 B
#4989 ObjectExtractorSimpleBody net472 153ns 0.0615ns 0.238ns 0.0446 0 0 281 B
#4989 ObjectExtractorMoreComplexBody net6.0 2.85μs 0.749ns 2.8ns 0.053 0 0 3.78 KB
#4989 ObjectExtractorMoreComplexBody netcoreapp3.1 3.62μs 1.39ns 5.4ns 0.0505 0 0 3.69 KB
#4989 ObjectExtractorMoreComplexBody net472 3.93μs 3.01ns 11.7ns 0.602 0.00592 0 3.8 KB
Benchmarks.Trace.Asm.AppSecWafBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #4989

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWaf(args: NestedMap (20))‑net6.0 1.117 105,136.67 94,158.91

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunWaf(args=NestedMap (10)) net6.0 51.7μs 158ns 612ns 0.224 0 0 16.06 KB
master RunWaf(args=NestedMap (10)) netcoreapp3.1 67.3μs 386ns 3.18μs 0.193 0 0 16.06 KB
master RunWaf(args=NestedMap (10)) net472 94μs 76.5ns 296ns 2.54 0.0941 0 16.14 KB
master RunWafWithAttack(args=Neste(...)tack) [22]) net6.0 119μs 574ns 2.29μs 0.285 0 0 22.41 KB
master RunWafWithAttack(args=Neste(...)tack) [22]) netcoreapp3.1 137μs 675ns 2.87μs 0.278 0 0 22.36 KB
master RunWafWithAttack(args=Neste(...)tack) [22]) net472 173μs 100ns 389ns 3.57 0.166 0 22.7 KB
master RunWaf(args=NestedMap (100)) net6.0 95.9μs 27.3ns 102ns 0.431 0 0 32.76 KB
master RunWaf(args=NestedMap (100)) netcoreapp3.1 131μs 736ns 5.05μs 0.434 0 0 33.33 KB
master RunWaf(args=NestedMap (100)) net472 183μs 123ns 476ns 5.29 0.365 0 33.67 KB
master RunWafWithAttack(args=Neste(...)tack) [23]) net6.0 163μs 55ns 198ns 0.528 0 0 39.1 KB
master RunWafWithAttack(args=Neste(...)tack) [23]) netcoreapp3.1 213μs 314ns 1.22μs 0.523 0 0 39.63 KB
master RunWafWithAttack(args=Neste(...)tack) [23]) net472 270μs 172ns 666ns 6.3 0.525 0 40.23 KB
master RunWaf(args=NestedMap (20)) net6.0 105μs 222ns 860ns 0.425 0 0 32.18 KB
master RunWaf(args=NestedMap (20)) netcoreapp3.1 130μs 630ns 2.52μs 0.399 0 0 32.3 KB
master RunWaf(args=NestedMap (20)) net472 182μs 140ns 523ns 5.17 0.363 0 32.63 KB
master RunWafWithAttack(args=Neste(...)tack) [22]) net6.0 163μs 181ns 700ns 0.492 0 0 38.53 KB
master RunWafWithAttack(args=Neste(...)tack) [22]) netcoreapp3.1 212μs 1.1μs 5.03μs 0.511 0 0 38.6 KB
master RunWafWithAttack(args=Neste(...)tack) [22]) net472 260μs 120ns 450ns 6.11 0.52 0 39.2 KB
#4989 RunWaf(args=NestedMap (10)) net6.0 50.3μs 27.3ns 98.4ns 0.225 0 0 16.06 KB
#4989 RunWaf(args=NestedMap (10)) netcoreapp3.1 68.9μs 377ns 2.23μs 0.205 0 0 16.06 KB
#4989 RunWaf(args=NestedMap (10)) net472 97.3μs 238ns 923ns 2.56 0.0947 0 16.14 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [22]) net6.0 115μs 48.8ns 169ns 0.308 0 0 22.41 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [22]) netcoreapp3.1 141μs 756ns 4μs 0.269 0 0 22.36 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [22]) net472 169μs 847ns 3.88μs 3.6 0.164 0 22.7 KB
#4989 RunWaf(args=NestedMap (100)) net6.0 97μs 67.9ns 245ns 0.424 0 0 32.76 KB
#4989 RunWaf(args=NestedMap (100)) netcoreapp3.1 134μs 150ns 581ns 0.389 0 0 33.33 KB
#4989 RunWaf(args=NestedMap (100)) net472 189μs 687ns 2.66μs 5.26 0.369 0 33.67 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [23]) net6.0 167μs 87ns 326ns 0.527 0 0 39.1 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [23]) netcoreapp3.1 214μs 1.08μs 4.58μs 0.512 0 0 39.63 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [23]) net472 262μs 362ns 1.4μs 6.38 0.521 0 40.23 KB
#4989 RunWaf(args=NestedMap (20)) net6.0 94.1μs 56.7ns 212ns 0.458 0 0 32.18 KB
#4989 RunWaf(args=NestedMap (20)) netcoreapp3.1 138μs 776ns 5.37μs 0.413 0 0 32.3 KB
#4989 RunWaf(args=NestedMap (20)) net472 187μs 391ns 1.51μs 5.16 0.369 0 32.63 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [22]) net6.0 176μs 110ns 425ns 0.443 0 0 38.53 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [22]) netcoreapp3.1 214μs 762ns 2.95μs 0.424 0 0 38.6 KB
#4989 RunWafWithAttack(args=Neste(...)tack) [22]) net472 268μs 166ns 642ns 6.15 0.512 0 39.2 KB
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 169μs 165ns 641ns 0.255 0 0 18.25 KB
master SendRequest netcoreapp3.1 190μs 363ns 1.41μs 0.189 0 0 20.41 KB
master SendRequest net472 0.000619ns 0.00024ns 0.00093ns 0 0 0 0 b
#4989 SendRequest net6.0 172μs 179ns 692ns 0.173 0 0 18.25 KB
#4989 SendRequest netcoreapp3.1 193μs 374ns 1.45μs 0.193 0 0 20.41 KB
#4989 SendRequest net472 0.00072ns 0.000284ns 0.00102ns 0 0 0 0 b
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 540μs 282ns 1.09μs 0.521 0 0 41.5 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 661μs 1.16μs 4.49μs 0.331 0 0 41.68 KB
master WriteAndFlushEnrichedTraces net472 851μs 3.65μs 14.1μs 8.3 2.62 0.437 53.23 KB
#4989 WriteAndFlushEnrichedTraces net6.0 523μs 313ns 1.21μs 0.541 0 0 41.63 KB
#4989 WriteAndFlushEnrichedTraces netcoreapp3.1 656μs 1.05μs 4.07μs 0.324 0 0 41.76 KB
#4989 WriteAndFlushEnrichedTraces net472 840μs 4.01μs 15.5μs 8.28 2.48 0.414 53.23 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.08μs 0.488ns 1.83ns 0.011 0 0 768 B
master ExecuteNonQuery netcoreapp3.1 1.44μs 0.9ns 3.49ns 0.0101 0 0 768 B
master ExecuteNonQuery net472 1.78μs 0.784ns 2.83ns 0.116 0 0 730 B
#4989 ExecuteNonQuery net6.0 1.07μs 0.778ns 3.01ns 0.0107 0 0 768 B
#4989 ExecuteNonQuery netcoreapp3.1 1.48μs 0.359ns 1.39ns 0.0104 0 0 768 B
#4989 ExecuteNonQuery net472 1.88μs 1.26ns 4.53ns 0.116 0.000942 0 730 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.12μs 0.421ns 1.57ns 0.0132 0 0 936 B
master CallElasticsearch netcoreapp3.1 1.51μs 0.633ns 2.19ns 0.0122 0 0 936 B
master CallElasticsearch net472 2.59μs 0.55ns 2.06ns 0.151 0 0 955 B
master CallElasticsearchAsync net6.0 1.34μs 0.71ns 2.65ns 0.0127 0 0 912 B
master CallElasticsearchAsync netcoreapp3.1 1.66μs 0.766ns 2.97ns 0.0133 0 0 984 B
master CallElasticsearchAsync net472 2.61μs 0.474ns 1.83ns 0.16 0 0 1.01 KB
#4989 CallElasticsearch net6.0 1.18μs 0.523ns 1.96ns 0.0129 0 0 936 B
#4989 CallElasticsearch netcoreapp3.1 1.61μs 2.25ns 8.41ns 0.0127 0 0 936 B
#4989 CallElasticsearch net472 2.55μs 0.958ns 3.71ns 0.151 0 0 955 B
#4989 CallElasticsearchAsync net6.0 1.24μs 1.35ns 5.22ns 0.0124 0 0 912 B
#4989 CallElasticsearchAsync netcoreapp3.1 1.57μs 0.608ns 2.28ns 0.0133 0 0 984 B
#4989 CallElasticsearchAsync net472 2.77μs 1.29ns 5.01ns 0.16 0 0 1.01 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.27μs 0.912ns 3.53ns 0.0127 0 0 912 B
master ExecuteAsync netcoreapp3.1 1.58μs 1.05ns 4.08ns 0.0125 0 0 912 B
master ExecuteAsync net472 1.75μs 0.488ns 1.82ns 0.138 0 0 875 B
#4989 ExecuteAsync net6.0 1.22μs 0.702ns 2.62ns 0.0129 0 0 912 B
#4989 ExecuteAsync netcoreapp3.1 1.63μs 0.735ns 2.85ns 0.0122 0 0 912 B
#4989 ExecuteAsync net472 1.82μs 1.2ns 4.66ns 0.138 0 0 875 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 4.16μs 0.771ns 2.89ns 0.0292 0 0 2.1 KB
master SendAsync netcoreapp3.1 4.84μs 1.72ns 6.66ns 0.0362 0 0 2.63 KB
master SendAsync net472 7.74μs 2.82ns 10.9ns 0.524 0 0 3.31 KB
#4989 SendAsync net6.0 3.87μs 1.73ns 6.71ns 0.0291 0 0 2.1 KB
#4989 SendAsync netcoreapp3.1 4.92μs 2.02ns 7.56ns 0.0346 0 0 2.63 KB
#4989 SendAsync net472 7.65μs 1.65ns 5.94ns 0.524 0 0 3.31 KB
Benchmarks.Trace.Iast.StringAspectsBenchmark - Slower ⚠️ More allocations ⚠️

Slower ⚠️ in #4989

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark(parameters: System.Collections.Generic.List`1[System.String])‑net6.0 1.182 52,150.00 61,650.00

Faster 🎉 in #4989

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark(parameters: System.Collections.Generic.List`1[System.String])‑net472 1.480 73,650.00 49,750.00

More allocations ⚠️ in #4989

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark(parameters: System.Collections.Generic.List`1[System.String])‑net472 59.7 KB 61.3 KB 1.6 KB 2.68%

Fewer allocations 🎉 in #4989

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark(parameters: System.Collections.Generic.List`1[System.String])‑net472 65.54 KB 57.34 KB -8.19 KB -12.50%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StringConcatBenchmark(parameters=Syste(...)ring] [48]) net6.0 52.6μs 302ns 2.14μs 0 0 0 43.44 KB
master StringConcatBenchmark(parameters=Syste(...)ring] [48]) netcoreapp3.1 62.2μs 794ns 7.82μs 0 0 0 42.64 KB
master StringConcatBenchmark(parameters=Syste(...)ring] [48]) net472 38.3μs 114ns 428ns 0 0 0 59.7 KB
master StringConcatAspectBenchmark(parameters=Syste(...)ring] [48]) net6.0 99.8μs 2.81μs 28.1μs 0 0 0 43.29 KB
master StringConcatAspectBenchmark(parameters=Syste(...)ring] [48]) netcoreapp3.1 109μs 4.13μs 40.9μs 0 0 0 42.64 KB
master StringConcatAspectBenchmark(parameters=Syste(...)ring] [48]) net472 76.1μs 845ns 8.1μs 0 0 0 65.54 KB
#4989 StringConcatBenchmark(parameters=Syste(...)ring] [48]) net6.0 63.6μs 933ns 8.65μs 0 0 0 43.44 KB
#4989 StringConcatBenchmark(parameters=Syste(...)ring] [48]) netcoreapp3.1 55.1μs 309ns 2.12μs 0 0 0 42.64 KB
#4989 StringConcatBenchmark(parameters=Syste(...)ring] [48]) net472 37.8μs 185ns 739ns 0 0 0 61.3 KB
#4989 StringConcatAspectBenchmark(parameters=Syste(...)ring] [48]) net6.0 105μs 3.31μs 33.1μs 0 0 0 43.29 KB
#4989 StringConcatAspectBenchmark(parameters=Syste(...)ring] [48]) netcoreapp3.1 118μs 2.26μs 22.5μs 0 0 0 42.64 KB
#4989 StringConcatAspectBenchmark(parameters=Syste(...)ring] [48]) net472 50.2μs 269ns 1.94μs 0 0 0 57.34 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 1.54μs 0.691ns 2.59ns 0.0216 0 0 1.57 KB
master EnrichedLog netcoreapp3.1 2.28μs 0.834ns 3.12ns 0.0213 0 0 1.57 KB
master EnrichedLog net472 2.55μs 2.7ns 10.5ns 0.238 0 0 1.5 KB
#4989 EnrichedLog net6.0 1.5μs 0.484ns 1.81ns 0.0219 0 0 1.57 KB
#4989 EnrichedLog netcoreapp3.1 2.28μs 0.972ns 3.5ns 0.0203 0 0 1.57 KB
#4989 EnrichedLog net472 2.63μs 2.69ns 10.4ns 0.238 0 0 1.5 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 115μs 111ns 431ns 0 0 0 4.21 KB
master EnrichedLog netcoreapp3.1 120μs 144ns 557ns 0.0601 0 0 4.21 KB
master EnrichedLog net472 150μs 170ns 659ns 0.669 0.223 0 4.39 KB
#4989 EnrichedLog net6.0 116μs 121ns 470ns 0.0576 0 0 4.21 KB
#4989 EnrichedLog netcoreapp3.1 121μs 202ns 783ns 0 0 0 4.21 KB
#4989 EnrichedLog net472 149μs 170ns 658ns 0.673 0.224 0 4.39 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 3.05μs 1.5ns 5.6ns 0.029 0 0 2.13 KB
master EnrichedLog netcoreapp3.1 4.31μs 10.6ns 41.1ns 0.0281 0 0 2.13 KB
master EnrichedLog net472 4.85μs 2.31ns 8.94ns 0.308 0 0 1.95 KB
#4989 EnrichedLog net6.0 3.02μs 1.02ns 3.94ns 0.03 0 0 2.13 KB
#4989 EnrichedLog netcoreapp3.1 4.01μs 2ns 7.5ns 0.0284 0 0 2.13 KB
#4989 EnrichedLog net472 4.83μs 1.64ns 6.37ns 0.309 0 0 1.95 KB
Benchmarks.Trace.RedisBenchmark - Slower ⚠️ Same allocations ✔️

Slower ⚠️ in #4989

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.RedisBenchmark.SendReceive‑net6.0 1.142 1,255.41 1,433.27

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendReceive net6.0 1.25μs 2.31ns 8.95ns 0.015 0 0 1.1 KB
master SendReceive netcoreapp3.1 1.81μs 0.44ns 1.71ns 0.0145 0 0 1.1 KB
master SendReceive net472 2.14μs 3.06ns 11.8ns 0.177 0 0 1.12 KB
#4989 SendReceive net6.0 1.43μs 1.64ns 6.37ns 0.0157 0 0 1.1 KB
#4989 SendReceive netcoreapp3.1 1.74μs 0.614ns 2.3ns 0.0149 0 0 1.1 KB
#4989 SendReceive net472 2.16μs 2.4ns 9.3ns 0.177 0 0 1.12 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 2.69μs 0.906ns 3.39ns 0.0205 0 0 1.53 KB
master EnrichedLog netcoreapp3.1 4.02μs 1.84ns 7.12ns 0.02 0 0 1.58 KB
master EnrichedLog net472 4.35μs 2.03ns 7.85ns 0.311 0 0 1.97 KB
#4989 EnrichedLog net6.0 2.71μs 0.791ns 3.06ns 0.0217 0 0 1.53 KB
#4989 EnrichedLog netcoreapp3.1 3.96μs 5.36ns 20.8ns 0.02 0 0 1.58 KB
#4989 EnrichedLog net472 4.43μs 3.71ns 13.9ns 0.312 0 0 1.97 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 452ns 0.162ns 0.628ns 0.00749 0 0 536 B
master StartFinishSpan netcoreapp3.1 704ns 0.154ns 0.576ns 0.0073 0 0 536 B
master StartFinishSpan net472 768ns 0.262ns 1.01ns 0.0853 0 0 538 B
master StartFinishScope net6.0 545ns 0.153ns 0.592ns 0.00904 0 0 656 B
master StartFinishScope netcoreapp3.1 874ns 0.666ns 2.49ns 0.0087 0 0 656 B
master StartFinishScope net472 900ns 0.329ns 1.27ns 0.0981 0 0 618 B
#4989 StartFinishSpan net6.0 476ns 0.437ns 1.69ns 0.00751 0 0 536 B
#4989 StartFinishSpan netcoreapp3.1 737ns 0.429ns 1.66ns 0.00733 0 0 536 B
#4989 StartFinishSpan net472 692ns 0.619ns 2.4ns 0.0853 0 0 538 B
#4989 StartFinishScope net6.0 531ns 0.126ns 0.486ns 0.00917 0 0 656 B
#4989 StartFinishScope netcoreapp3.1 865ns 1.04ns 4.01ns 0.00867 0 0 656 B
#4989 StartFinishScope net472 982ns 0.29ns 1.12ns 0.098 0 0 618 B
Benchmarks.Trace.TraceAnnotationsBenchmark - Slower ⚠️ Same allocations ✔️

Slower ⚠️ in #4989

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin‑netcoreapp3.1 1.135 882.56 1,001.80
Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin‑net6.0 1.116 625.49 698.29

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunOnMethodBegin net6.0 625ns 0.177ns 0.661ns 0.00906 0 0 656 B
master RunOnMethodBegin netcoreapp3.1 883ns 0.265ns 1.03ns 0.00884 0 0 656 B
master RunOnMethodBegin net472 1.14μs 0.382ns 1.48ns 0.0978 0 0 618 B
#4989 RunOnMethodBegin net6.0 698ns 0.122ns 0.474ns 0.00911 0 0 656 B
#4989 RunOnMethodBegin netcoreapp3.1 1μs 1.2ns 4.48ns 0.00884 0 0 656 B
#4989 RunOnMethodBegin net472 1.07μs 0.25ns 0.935ns 0.098 0 0 618 B

@andrewlock
Copy link
Member Author

andrewlock commented Dec 19, 2023

Throughput/Crank Report:zap:

Throughput results for AspNetCoreSimpleController comparing the following branches/commits:

Cases where throughput results for the PR are worse than latest master (5% drop or greater), results are shown in red.

Note that these results are based on a single point-in-time result for each branch. For full results, see one of the many, many dashboards!

gantt
    title Throughput Linux x64 (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    This PR (4989) (10.794M)   : 0, 10793973
    master (11.023M)   : 0, 11023309
    benchmarks/2.9.0 (10.850M)   : 0, 10849500

    section Automatic
    This PR (4989) (7.420M)   : 0, 7420473
    master (7.466M)   : 0, 7466308
    benchmarks/2.9.0 (7.823M)   : 0, 7822730

    section Trace stats
    This PR (4989) (7.778M)   : 0, 7778239
    master (7.718M)   : 0, 7717767

    section Manual
    This PR (4989) (9.382M)   : 0, 9382172
    master (9.430M)   : 0, 9430114

    section Manual + Automatic
    This PR (4989) (6.934M)   : 0, 6933520
    master (7.071M)   : 0, 7071290

    section Version Conflict
    This PR (4989) (6.345M)   : 0, 6345468
    master (6.346M)   : 0, 6345816

Loading
gantt
    title Throughput Linux arm64 (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    This PR (4989) (9.610M)   : 0, 9610019
    master (9.715M)   : 0, 9714686
    benchmarks/2.9.0 (9.680M)   : 0, 9679996

    section Automatic
    This PR (4989) (6.379M)   : 0, 6379253
    master (6.423M)   : 0, 6423186

    section Trace stats
    This PR (4989) (6.903M)   : 0, 6902829
    master (6.963M)   : 0, 6963293

    section Manual
    This PR (4989) (8.242M)   : 0, 8241964
    master (8.450M)   : 0, 8449696

    section Manual + Automatic
    This PR (4989) (6.136M)   : 0, 6135686
    master (5.985M)   : 0, 5984843

    section Version Conflict
    This PR (4989) (5.487M)   : 0, 5487475
    master (5.754M)   : 0, 5753645

Loading
gantt
    title Throughput Windows x64 (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    This PR (4989) (10.620M)   : 0, 10619977
    master (10.285M)   : 0, 10285399
    benchmarks/2.9.0 (10.863M)   : 0, 10863181

    section Automatic
    This PR (4989) (6.797M)   : crit ,0, 6796986
    master (7.225M)   : 0, 7224692
    benchmarks/2.9.0 (8.130M)   : 0, 8129748

    section Trace stats
    This PR (4989) (6.318M)   : crit ,0, 6318298
    master (7.543M)   : 0, 7542799

    section Manual
    This PR (4989) (7.623M)   : crit ,0, 7622997
    master (8.984M)   : 0, 8984036

    section Manual + Automatic
    This PR (4989) (6.410M)   : crit ,0, 6409691
    master (6.977M)   : 0, 6976681

    section Version Conflict
    This PR (4989) (5.915M)   : crit ,0, 5915296
    master (6.364M)   : 0, 6363807

Loading
gantt
    title Throughput Linux x64 (ASM) (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    master (7.339M)   : 0, 7339251
    benchmarks/2.9.0 (7.835M)   : 0, 7834738

    section No attack
    master (1.982M)   : 0, 1982279
    benchmarks/2.9.0 (3.201M)   : 0, 3200714

    section Attack
    master (1.591M)   : 0, 1591401
    benchmarks/2.9.0 (2.469M)   : 0, 2468672

    section Blocking
    master (3.230M)   : 0, 3229524

    section IAST default
    master (6.528M)   : 0, 6527810

    section IAST full
    master (5.692M)   : 0, 5691891

    section Base vuln
    master (0.961M)   : 0, 960692

    section IAST vuln
    master (0.859M)   : 0, 859242

Loading

public override ValueTask DisposeAsync()
{
// Override so that we don't dispose the inner stream
return default;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe less confusing to return ValueTask.CompletedTask?

Copy link
Member Author

Choose a reason for hiding this comment

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

If only ValueTask.CompletedTask existed in .NET Core 3.1... 😶

Comment on lines 101 to 104
if (System.Buffers.Text.Utf8Formatter.TryFormat(count, outputBuffer, out var bytesWritten, 'X'))
{
return bytesWritten;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice


public override int Read(byte[] buffer, int offset, int count)
{
// YOLO
Copy link
Collaborator

Choose a reason for hiding this comment

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

😱

Copy link
Member Author

Choose a reason for hiding this comment

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

It's only in tests 😉 Not worth duplicating all the HTTP parser etc IMO

@andrewlock andrewlock force-pushed the andrew/tracer_flare/mock_agent_prereq branch from 7a6ddd5 to 000ca74 Compare December 20, 2023 17:07
@andrewlock andrewlock force-pushed the andrew/tracer_flare/chunked_encoding branch from 5e4cf30 to 770ab3b Compare December 20, 2023 17:07
@andrewlock andrewlock force-pushed the andrew/tracer_flare/mock_agent_prereq branch from 000ca74 to 25cc2da Compare December 20, 2023 17:32
@andrewlock andrewlock force-pushed the andrew/tracer_flare/chunked_encoding branch from 770ab3b to 81baef5 Compare December 20, 2023 17:32
@andrewlock andrewlock force-pushed the andrew/tracer_flare/mock_agent_prereq branch from 25cc2da to 880fb92 Compare December 21, 2023 13:10
@andrewlock andrewlock force-pushed the andrew/tracer_flare/chunked_encoding branch from 81baef5 to 2a76f33 Compare December 21, 2023 14:30
@andrewlock andrewlock force-pushed the andrew/tracer_flare/mock_agent_prereq branch from 880fb92 to 0ca4914 Compare December 21, 2023 16:44
@andrewlock andrewlock force-pushed the andrew/tracer_flare/chunked_encoding branch from 2a76f33 to dbdfbb6 Compare December 21, 2023 16:44
@andrewlock andrewlock force-pushed the andrew/tracer_flare/mock_agent_prereq branch from 0ca4914 to f8f133f Compare December 27, 2023 10:54
@andrewlock andrewlock force-pushed the andrew/tracer_flare/chunked_encoding branch from dbdfbb6 to 46e27a2 Compare December 27, 2023 10:54
Base automatically changed from andrew/tracer_flare/mock_agent_prereq to master December 27, 2023 13:29
@andrewlock andrewlock force-pushed the andrew/tracer_flare/chunked_encoding branch from 46e27a2 to 7d3b360 Compare December 27, 2023 13:31
Copy link
Contributor

@bouwkast bouwkast left a comment

Choose a reason for hiding this comment

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

Looks good to me

@@ -28,6 +28,7 @@
from a source generator as opposed to something that is coming from some other tool. -->
<Compile Remove="$(GeneratedFolder)/*/**/*.cs" />
<Compile Update="Configuration\ConfigurationKeys.*.cs" DependentUpon="ConfigurationKeys.cs" />
<Compile Remove="Util\Streams\ChunkedEncodingWriteStream.cs" />
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this being removed? Also I don't see this file on that path is it supposed to be the HttpOverStreams\ChunkedEncodingWriteStream.cs?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, looks like it got left over in various rebasing. I'll remove it in a subsequent PR (to save CI). Thanks!

@andrewlock andrewlock merged commit 6726974 into master Dec 28, 2023
55 checks passed
@andrewlock andrewlock deleted the andrew/tracer_flare/chunked_encoding branch December 28, 2023 11:33
@github-actions github-actions bot added this to the vNext milestone Dec 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:tracer The core tracer library (Datadog.Trace, does not include OpenTracing, native code, or integrations)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants