Skip to content

Enable performance analyzers for Datadog.Trace#8276

Merged
dudikeleti merged 63 commits into
masterfrom
andrew/more-analyzers
Mar 17, 2026
Merged

Enable performance analyzers for Datadog.Trace#8276
dudikeleti merged 63 commits into
masterfrom
andrew/more-analyzers

Conversation

@andrewlock

@andrewlock andrewlock commented Mar 6, 2026

Copy link
Copy Markdown
Member

Summary of changes

Enables (most of) the performance rule analyzers

Reason for change

We should be following performance best-practices, and these are easy wins in most cases. In many cases, we don't have any violations. In some cases there are many violations 😅

Implementation details

I started doing this by hand, delegated the rest to 🤖, then reviewed them all (and fixed some more) by hand. Every commit handles a single analyzer

I strongly recommend reviewing commit-by-commit

There are basically 4 different types of commit:

  • Analyzer enabled as error, no violations.
  • Analyzer enabled, small fixes required.
  • Analyzer not enabled (added commented out), because we have too many violation and it's not worth fixing them because it's minimal gains.
  • Analyzer not enabled (added commented out), because fixing the violations would be too distracting and far reaching. I will enable and fix each of these in subsequent PRs

Test coverage

All our current tests should cover these changes. The vast majority of the "fixes" are mechanical changes (have code fixes) so should be safe, but do keep your eye out.

Other details

https://datadoghq.atlassian.net/browse/LANGPLAT-813

Just to repeat, review this commit-by-commit, you'll have a much easier time 😄

Tip

Click on Commits above, then use n and p to navigate between the commits

@andrewlock andrewlock force-pushed the andrew/more-analyzers branch 3 times, most recently from 37e4b3e to aa429c3 Compare March 10, 2026 08:24
@pr-commenter

pr-commenter Bot commented Mar 10, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-03-13 18:08:39

Comparing candidate commit 5c769bb in PR branch andrew/more-analyzers with baseline commit 53edb3f in branch master.

Found 6 performance improvements and 6 performance regressions! Performance is the same for 167 metrics, 13 unstable metrics.

scenario:Benchmarks.Trace.AgentWriterBenchmark.WriteAndFlushEnrichedTraces netcoreapp3.1

  • 🟩 execution_time [-111.407ms; -111.221ms] or [-50.552%; -50.468%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody net6.0

  • 🟥 execution_time [+12.896ms; +18.776ms] or [+6.489%; +9.449%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorMoreComplexBody netcoreapp3.1

  • 🟩 execution_time [-16.294ms; -11.873ms] or [-7.646%; -5.571%]

scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorSimpleBody net6.0

  • 🟥 execution_time [+11.510ms; +16.112ms] or [+5.831%; +8.162%]

scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces netcoreapp3.1

  • 🟩 execution_time [-57.542ms; -51.788ms] or [-28.628%; -25.766%]
  • 🟩 throughput [+76.788op/s; +125.488op/s] or [+5.355%; +8.752%]

scenario:Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark netcoreapp3.1

  • 🟥 execution_time [+2.828µs; +6.542µs] or [+5.587%; +12.924%]

scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore net6.0

  • 🟥 execution_time [+106.485ms; +108.156ms] or [+113.700%; +115.483%]

scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore netcoreapp3.1

  • 🟥 throughput [-16564876.641op/s; -15083037.518op/s] or [-6.866%; -6.252%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishScope netcoreapp3.1

  • 🟥 execution_time [+11.663ms; +17.202ms] or [+5.902%; +8.705%]
  • 🟩 throughput [+42908.821op/s; +66786.009op/s] or [+5.244%; +8.162%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishTwoScopes netcoreapp3.1

  • 🟩 execution_time [-16.609ms; -10.949ms] or [-7.912%; -5.215%]

@dd-trace-dotnet-ci-bot

dd-trace-dotnet-ci-bot Bot commented Mar 10, 2026

Copy link
Copy Markdown

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing This PR (8276) and master.

✅ No regressions detected - check the details below

Full Metrics Comparison

FakeDbCommand

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration76.31 ± (76.21 - 76.56) ms76.19 ± (76.14 - 76.46) ms-0.2%
.NET Framework 4.8 - Bailout
duration80.63 ± (80.48 - 80.88) ms81.27 ± (81.12 - 81.45) ms+0.8%✅⬆️
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1112.97 ± (1111.38 - 1117.18) ms1112.10 ± (1110.84 - 1116.62) ms-0.1%
.NET Core 3.1 - Baseline
process.internal_duration_ms23.51 ± (23.45 - 23.57) ms23.51 ± (23.46 - 23.56) ms-0.0%
process.time_to_main_ms89.34 ± (89.15 - 89.52) ms89.42 ± (89.22 - 89.63) ms+0.1%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.91 ± (10.91 - 10.92) MB10.90 ± (10.89 - 10.90) MB-0.2%
runtime.dotnet.threads.count12 ± (12 - 12)12 ± (12 - 12)+0.0%
.NET Core 3.1 - Bailout
process.internal_duration_ms23.69 ± (23.63 - 23.76) ms23.45 ± (23.39 - 23.51) ms-1.0%
process.time_to_main_ms91.31 ± (91.09 - 91.54) ms90.87 ± (90.65 - 91.09) ms-0.5%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.95 ± (10.95 - 10.96) MB10.92 ± (10.92 - 10.93) MB-0.3%
runtime.dotnet.threads.count13 ± (13 - 13)13 ± (13 - 13)+0.0%
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms226.72 ± (225.25 - 228.19) ms224.68 ± (222.96 - 226.39) ms-0.9%
process.time_to_main_ms512.74 ± (511.73 - 513.75) ms508.50 ± (507.52 - 509.47) ms-0.8%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed47.22 ± (47.20 - 47.25) MB47.13 ± (47.10 - 47.15) MB-0.2%
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)+0.1%✅⬆️
.NET 6 - Baseline
process.internal_duration_ms22.23 ± (22.18 - 22.28) ms22.23 ± (22.19 - 22.27) ms-0.0%
process.time_to_main_ms77.41 ± (77.24 - 77.58) ms77.73 ± (77.53 - 77.93) ms+0.4%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.63 ± (10.63 - 10.63) MB10.62 ± (10.62 - 10.62) MB-0.1%
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 6 - Bailout
process.internal_duration_ms22.28 ± (22.23 - 22.33) ms22.16 ± (22.12 - 22.21) ms-0.5%
process.time_to_main_ms79.63 ± (79.43 - 79.83) ms78.99 ± (78.82 - 79.17) ms-0.8%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.74 ± (10.74 - 10.75) MB10.73 ± (10.73 - 10.74) MB-0.1%
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms219.89 ± (218.61 - 221.16) ms220.83 ± (219.63 - 222.03) ms+0.4%✅⬆️
process.time_to_main_ms486.17 ± (485.49 - 486.85) ms485.75 ± (485.03 - 486.48) ms-0.1%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed48.08 ± (48.06 - 48.10) MB48.07 ± (48.05 - 48.09) MB-0.0%
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)-0.1%
.NET 8 - Baseline
process.internal_duration_ms20.50 ± (20.41 - 20.59) ms20.34 ± (20.30 - 20.37) ms-0.8%
process.time_to_main_ms77.77 ± (77.43 - 78.11) ms77.32 ± (77.15 - 77.49) ms-0.6%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.66 ± (7.66 - 7.67) MB7.67 ± (7.67 - 7.68) MB+0.1%✅⬆️
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 8 - Bailout
process.internal_duration_ms20.44 ± (20.39 - 20.49) ms20.39 ± (20.33 - 20.46) ms-0.2%
process.time_to_main_ms78.18 ± (77.98 - 78.37) ms78.03 ± (77.87 - 78.19) ms-0.2%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.68 ± (7.68 - 7.69) MB7.71 ± (7.71 - 7.72) MB+0.4%✅⬆️
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms171.06 ± (170.20 - 171.92) ms169.63 ± (168.85 - 170.40) ms-0.8%
process.time_to_main_ms472.18 ± (471.35 - 473.01) ms472.63 ± (471.75 - 473.52) ms+0.1%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed35.77 ± (35.74 - 35.79) MB35.73 ± (35.71 - 35.75) MB-0.1%
runtime.dotnet.threads.count27 ± (27 - 27)26 ± (26 - 26)-0.4%

HttpMessageHandler

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration198.54 ± (198.51 - 199.88) ms193.82 ± (193.53 - 194.31) ms-2.4%
.NET Framework 4.8 - Bailout
duration201.64 ± (201.62 - 202.60) ms197.67 ± (197.40 - 198.10) ms-2.0%
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1159.58 ± (1161.78 - 1170.43) ms1146.33 ± (1148.48 - 1155.29) ms-1.1%
.NET Core 3.1 - Baseline
process.internal_duration_ms191.04 ± (190.60 - 191.48) ms188.80 ± (188.43 - 189.17) ms-1.2%
process.time_to_main_ms81.87 ± (81.66 - 82.09) ms81.59 ± (81.36 - 81.81) ms-0.4%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.11 ± (16.09 - 16.13) MB16.09 ± (16.06 - 16.11) MB-0.1%
runtime.dotnet.threads.count20 ± (20 - 20)20 ± (20 - 20)+0.2%✅⬆️
.NET Core 3.1 - Bailout
process.internal_duration_ms191.11 ± (190.65 - 191.58) ms188.99 ± (188.54 - 189.43) ms-1.1%
process.time_to_main_ms83.57 ± (83.33 - 83.81) ms82.77 ± (82.54 - 82.99) ms-1.0%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.14 ± (16.12 - 16.17) MB16.19 ± (16.16 - 16.22) MB+0.3%✅⬆️
runtime.dotnet.threads.count21 ± (21 - 21)21 ± (21 - 21)-0.1%
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms400.29 ± (398.74 - 401.83) ms396.66 ± (395.14 - 398.18) ms-0.9%
process.time_to_main_ms480.89 ± (480.20 - 481.59) ms478.12 ± (477.37 - 478.88) ms-0.6%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed58.34 ± (58.30 - 58.38) MB58.09 ± (57.98 - 58.20) MB-0.4%
runtime.dotnet.threads.count30 ± (30 - 30)30 ± (30 - 30)-0.1%
.NET 6 - Baseline
process.internal_duration_ms194.34 ± (193.87 - 194.82) ms194.60 ± (194.22 - 194.98) ms+0.1%✅⬆️
process.time_to_main_ms70.70 ± (70.49 - 70.90) ms70.98 ± (70.75 - 71.21) ms+0.4%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.31 ± (16.27 - 16.36) MB16.20 ± (16.09 - 16.32) MB-0.7%
runtime.dotnet.threads.count19 ± (19 - 19)19 ± (19 - 19)-0.1%
.NET 6 - Bailout
process.internal_duration_ms194.35 ± (193.84 - 194.86) ms193.42 ± (193.02 - 193.82) ms-0.5%
process.time_to_main_ms71.71 ± (71.52 - 71.90) ms71.46 ± (71.32 - 71.60) ms-0.3%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.37 ± (16.34 - 16.40) MB16.31 ± (16.21 - 16.42) MB-0.3%
runtime.dotnet.threads.count20 ± (20 - 20)20 ± (20 - 20)-2.2%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms431.15 ± (429.55 - 432.74) ms429.05 ± (427.35 - 430.74) ms-0.5%
process.time_to_main_ms459.16 ± (458.39 - 459.93) ms456.24 ± (455.52 - 456.97) ms-0.6%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed59.35 ± (59.27 - 59.42) MB59.32 ± (59.23 - 59.41) MB-0.0%
runtime.dotnet.threads.count29 ± (29 - 30)29 ± (29 - 29)-0.3%
.NET 8 - Baseline
process.internal_duration_ms197.09 ± (196.64 - 197.54) ms194.46 ± (193.98 - 194.94) ms-1.3%
process.time_to_main_ms71.53 ± (71.29 - 71.77) ms71.18 ± (70.93 - 71.43) ms-0.5%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.72 ± (11.70 - 11.74) MB11.73 ± (11.72 - 11.75) MB+0.1%✅⬆️
runtime.dotnet.threads.count18 ± (18 - 18)18 ± (18 - 18)-0.2%
.NET 8 - Bailout
process.internal_duration_ms196.44 ± (195.96 - 196.93) ms190.88 ± (190.39 - 191.37) ms-2.8%
process.time_to_main_ms73.32 ± (73.12 - 73.52) ms71.23 ± (71.07 - 71.39) ms-2.8%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.74 ± (11.72 - 11.76) MB11.78 ± (11.75 - 11.80) MB+0.3%✅⬆️
runtime.dotnet.threads.count19 ± (19 - 20)19 ± (19 - 19)-1.1%
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms356.99 ± (355.81 - 358.16) ms352.61 ± (351.15 - 354.07) ms-1.2%
process.time_to_main_ms443.14 ± (442.25 - 444.02) ms438.63 ± (437.98 - 439.29) ms-1.0%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed47.83 ± (47.80 - 47.87) MB47.85 ± (47.82 - 47.88) MB+0.0%✅⬆️
runtime.dotnet.threads.count29 ± (29 - 29)29 ± (29 - 29)+0.1%✅⬆️
Comparison explanation

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 highlighted 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).

Duration charts
FakeDbCommand (.NET Framework 4.8)
gantt
    title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8276) - mean (76ms)  : 74, 79
    master - mean (76ms)  : 74, 79

    section Bailout
    This PR (8276) - mean (81ms)  : 79, 83
    master - mean (81ms)  : 78, 83

    section CallTarget+Inlining+NGEN
    This PR (8276) - mean (1,114ms)  : 1073, 1155
    master - mean (1,114ms)  : 1073, 1155

Loading
FakeDbCommand (.NET Core 3.1)
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8276) - mean (120ms)  : 116, 124
    master - mean (120ms)  : 116, 124

    section Bailout
    This PR (8276) - mean (121ms)  : 119, 124
    master - mean (122ms)  : 119, 126

    section CallTarget+Inlining+NGEN
    This PR (8276) - mean (769ms)  : 747, 791
    master - mean (775ms)  : 751, 800

Loading
FakeDbCommand (.NET 6)
gantt
    title Execution time (ms) FakeDbCommand (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8276) - mean (107ms)  : 103, 110
    master - mean (107ms)  : 103, 110

    section Bailout
    This PR (8276) - mean (108ms)  : 105, 111
    master - mean (109ms)  : 106, 111

    section CallTarget+Inlining+NGEN
    This PR (8276) - mean (735ms)  : 700, 770
    master - mean (732ms)  : 704, 760

Loading
FakeDbCommand (.NET 8)
gantt
    title Execution time (ms) FakeDbCommand (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8276) - mean (106ms)  : 102, 110
    master - mean (107ms)  : 96, 118

    section Bailout
    This PR (8276) - mean (106ms)  : 104, 109
    master - mean (107ms)  : 104, 109

    section CallTarget+Inlining+NGEN
    This PR (8276) - mean (672ms)  : 651, 693
    master - mean (673ms)  : 654, 693

Loading
HttpMessageHandler (.NET Framework 4.8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8276) - mean (194ms)  : 190, 198
    master - mean (199ms)  : 189, 210

    section Bailout
    This PR (8276) - mean (198ms)  : 194, 201
    master - mean (202ms)  : 196, 208

    section CallTarget+Inlining+NGEN
    This PR (8276) - mean (1,152ms)  : 1102, 1201
    master - mean (1,166ms)  : 1102, 1231

Loading
HttpMessageHandler (.NET Core 3.1)
gantt
    title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8276) - mean (279ms)  : 273, 285
    master - mean (281ms)  : 273, 290

    section Bailout
    This PR (8276) - mean (280ms)  : 272, 289
    master - mean (283ms)  : 273, 293

    section CallTarget+Inlining+NGEN
    This PR (8276) - mean (905ms)  : 875, 936
    master - mean (913ms)  : 882, 943

Loading
HttpMessageHandler (.NET 6)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8276) - mean (275ms)  : 266, 283
    master - mean (273ms)  : 267, 279

    section Bailout
    This PR (8276) - mean (273ms)  : 268, 278
    master - mean (274ms)  : 268, 281

    section CallTarget+Inlining+NGEN
    This PR (8276) - mean (913ms)  : 890, 935
    master - mean (921ms)  : 895, 948

Loading
HttpMessageHandler (.NET 8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (8276) - mean (276ms)  : 266, 285
    master - mean (279ms)  : 271, 286

    section Bailout
    This PR (8276) - mean (272ms)  : 264, 280
    master - mean (280ms)  : 272, 288

    section CallTarget+Inlining+NGEN
    This PR (8276) - mean (823ms)  : 803, 842
    master - mean (833ms)  : 810, 856

Loading

}));

Log.Debug(
Log.Debug<int, string>(

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

unrelated fix, but it was calling the wrong overload previously!

@andrewlock andrewlock force-pushed the andrew/more-analyzers branch 5 times, most recently from 74132e3 to bf90963 Compare March 12, 2026 15:31
@andrewlock andrewlock changed the title Andrew/more analyzers Enable performance analyzers for Datadog.Trace Mar 12, 2026
@andrewlock andrewlock added area:builds project files, build scripts, pipelines, versioning, releases, packages type:performance Performance, speed, latency, resource usage (CPU, memory) AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos labels Mar 12, 2026
@andrewlock andrewlock force-pushed the andrew/more-analyzers branch from bf90963 to df58165 Compare March 12, 2026 16:09
@andrewlock andrewlock marked this pull request as ready for review March 12, 2026 16:09
@andrewlock andrewlock requested review from a team as code owners March 12, 2026 16:09
andrewlock and others added 22 commits March 13, 2026 17:20
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…IfNull

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@andrewlock andrewlock force-pushed the andrew/more-analyzers branch from c344219 to 5c769bb Compare March 13, 2026 17:23
@@ -2,3 +2,67 @@

[*.{cs,vb}]
dotnet_diagnostic.DDSEAL001.severity = error # types should be sealed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is not a change in this PR, but related. Should we replace the custom DDSEAL001 with CA1852?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

tl;dr; Nope 😄 They're basically the same - DDSEAL001 was essentially written as a clone of CA1852, but accounting for the subtleties of our codebase, i.e. we want to make all our types sealed, not just the internal ones.

@dudikeleti dudikeleti merged commit efb6c5c into master Mar 17, 2026
149 checks passed
@dudikeleti dudikeleti deleted the andrew/more-analyzers branch March 17, 2026 14:59
@github-actions github-actions Bot added this to the vNext-v3 milestone Mar 17, 2026
andrewlock added a commit that referenced this pull request Mar 18, 2026
…CA1850` (#8303)

## Summary of changes

Enables the CA1850 analyzer, and fixes the two existing violations

## Reason for change

The CA1850 analyzer says "use the static `MD5.HashData` instead of
`MD5.Create()` etc. We need to use `#if` because it's only in .NET Core.

However, in looking at the violations, I saw there was a big opportunity
for allocation and speed improvements too, so did them together

## Implementation details

- Added basic tests for existing code that was to be refactored
- Create an `Md5Helper.ComputeMd5Hash()` method that takes a `string`,
converts to UTF-8, and computes the hash, as efficiently as possibly
(stackalloc where possible etc)
- Update existing usages to use the new helper
- "Fix" other allocatey paths that were using the hash output to be
"better" 😄

## Test coverage

- Added some unit tests to ensure correctness. They're not extensive,
but they're good enough I think
- Ran some basic benchmarks, I think the results speak for themselves 😉 


| Method | Runtime | Mean | Error | Allocated |
| --------------------- | ------------------ | ---------: | -------: |
--------: |
| FeatureFlags_Original | .NET 10.0 | 632.3 ns | 5.64 ns | 1120 B |
| FeatureFlags_Updated | .NET 10.0 | 204.4 ns | 3.78 ns | - |
| FeatureFlags_Original | .NET 6.0 | 672.5 ns | 7.59 ns | 1112 B |
| FeatureFlags_Updated | .NET 6.0 | 223.7 ns | 4.34 ns | - |
| FeatureFlags_Original | .NET Core 2.1 | 1,102.5 ns | 21.09 ns | 1128 B
|
| FeatureFlags_Updated | .NET Core 2.1 | 565.7 ns | 9.12 ns | 208 B |
| FeatureFlags_Original | .NET Core 3.1 | 899.9 ns | 17.84 ns | 1112 B |
| FeatureFlags_Updated | .NET Core 3.1 | 366.3 ns | 7.26 ns | 128 B |
| FeatureFlags_Original | .NET Framework 4.8 | 2,822.1 ns | 53.48 ns |
1444 B |
| FeatureFlags_Updated | .NET Framework 4.8 | 1,861.8 ns | 36.68 ns |
522 B |
| | | | | |
| ToUUID_Original | .NET 10.0 | 860.4 ns | 17.27 ns | 1024 B |
| ToUUID_Updated | .NET 10.0 | 333.6 ns | 5.05 ns | 96 B |
| ToUUID_Original | .NET 6.0 | 815.5 ns | 14.31 ns | 1016 B |
| ToUUID_Updated | .NET 6.0 | 365.3 ns | 2.66 ns | 96 B |
| ToUUID_Original | .NET Core 2.1 | 1,055.6 ns | 20.77 ns | 1048 B |
| ToUUID_Updated | .NET Core 2.1 | 733.5 ns | 13.69 ns | 408 B |
| ToUUID_Original | .NET Core 3.1 | 876.6 ns | 13.99 ns | 1016 B |
| ToUUID_Updated | .NET Core 3.1 | 498.1 ns | 9.36 ns | 224 B |
| ToUUID_Original | .NET Framework 4.8 | 2,365.0 ns | 46.94 ns | 1484 B
|
| ToUUID_Updated | .NET Framework 4.8 | 2,305.9 ns | 45.79 ns | 722 B |


## Other details

https://datadoghq.atlassian.net/browse/LANGPLAT-813

Stacked on other analyzer enablement tests:

- #8276 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos area:builds project files, build scripts, pipelines, versioning, releases, packages type:performance Performance, speed, latency, resource usage (CPU, memory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants