Reduce payload size sent by agent in remote config#8238
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33707ed9b0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| { | ||
| ArrayPool = JsonArrayPool.Shared, | ||
| }; | ||
| var tufRoot = new JsonSerializer().Deserialize<MinimalTufRoot>(jsonReader); |
There was a problem hiding this comment.
Is this new JsonSerializer().Deserialize() called every 5 secs? Should we cache and reuse the JsonSerializer instance?
There was a problem hiding this comment.
Yes it is 👍 It's a good question - the JsonConvert methods all create a throw-away one, so I'm not sure if we actually need a new one each time or not 🤔 I'll look into it, and see if we can/should cache them in general
33707ed to
c42e395
Compare
BenchmarksBenchmark execution time: 2026-03-10 10:41:12 Comparing candidate commit bc2260d in PR branch Found 6 performance improvements and 10 performance regressions! Performance is the same for 162 metrics, 14 unstable metrics. scenario:Benchmarks.Trace.AgentWriterBenchmark.WriteAndFlushEnrichedTraces net6.0
scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody net6.0
scenario:Benchmarks.Trace.Asm.AppSecBodyBenchmark.ObjectExtractorSimpleBody net6.0
scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeLegacyArgs netcoreapp3.1
scenario:Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack netcoreapp3.1
scenario:Benchmarks.Trace.AspNetCoreBenchmark.SendRequest net6.0
scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces net472
scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces net6.0
scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces netcoreapp3.1
scenario:Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearch net6.0
scenario:Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync netcoreapp3.1
scenario:Benchmarks.Trace.ILoggerBenchmark.EnrichedLog netcoreapp3.1
scenario:Benchmarks.Trace.Log4netBenchmark.EnrichedLog netcoreapp3.1
scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore net6.0
scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore netcoreapp3.1
|
2a6bccf to
6fe01d4
Compare
Previously, we were always sending the same rootversion, which meant that RCM was always sending us the signatures, which significantly increases the payload size sent to us (~35kB of data) We still pay the cost of this the first time _and_ we now materialize the strings, but we avoid it for all subsequent requests
c42e395 to
bc2260d
Compare
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8238) and master. ✅ No regressions detected - check the details below Full Metrics ComparisonFakeDbCommand
HttpMessageHandler
Comparison explanationExecution-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:
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 chartsFakeDbCommand (.NET Framework 4.8)gantt
title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8238) - mean (76ms) : 74, 79
master - mean (75ms) : 73, 77
section Bailout
This PR (8238) - mean (80ms) : 78, 82
master - mean (80ms) : 78, 82
section CallTarget+Inlining+NGEN
This PR (8238) - mean (1,093ms) : 1039, 1147
master - mean (1,083ms) : 1029, 1136
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 (8238) - mean (117ms) : 113, 121
master - mean (116ms) : 111, 121
section Bailout
This PR (8238) - mean (118ms) : 115, 121
master - mean (117ms) : 115, 119
section CallTarget+Inlining+NGEN
This PR (8238) - mean (780ms) : 714, 846
master - mean (765ms) : 696, 833
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8238) - mean (104ms) : 101, 108
master - mean (102ms) : 100, 105
section Bailout
This PR (8238) - mean (106ms) : 103, 108
master - mean (105ms) : 102, 107
section CallTarget+Inlining+NGEN
This PR (8238) - mean (772ms) : 705, 840
master - mean (757ms) : 694, 820
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8238) - mean (104ms) : 101, 107
master - mean (101ms) : 98, 104
section Bailout
This PR (8238) - mean (105ms) : 103, 107
master - mean (103ms) : 100, 105
section CallTarget+Inlining+NGEN
This PR (8238) - mean (690ms) : 670, 710
master - mean (679ms) : 659, 700
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 (8238) - mean (195ms) : 190, 200
master - mean (194ms) : 189, 198
section Bailout
This PR (8238) - mean (199ms) : 195, 203
master - mean (198ms) : 194, 202
section CallTarget+Inlining+NGEN
This PR (8238) - mean (1,166ms) : 1097, 1235
master - mean (1,152ms) : 1098, 1206
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 (8238) - mean (285ms) : 278, 293
master - mean (280ms) : 270, 290
section Bailout
This PR (8238) - mean (287ms) : 279, 296
master - mean (282ms) : 275, 288
section CallTarget+Inlining+NGEN
This PR (8238) - mean (952ms) : 913, 992
master - mean (947ms) : 902, 991
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8238) - mean (271ms) : 266, 277
master - mean (271ms) : 267, 276
section Bailout
This PR (8238) - mean (272ms) : 267, 277
master - mean (273ms) : 266, 279
section CallTarget+Inlining+NGEN
This PR (8238) - mean (932ms) : 901, 963
master - mean (937ms) : 908, 966
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8238) - mean (270ms) : 265, 276
master - mean (270ms) : 264, 276
section Bailout
This PR (8238) - mean (272ms) : 266, 278
master - mean (270ms) : 265, 276
section CallTarget+Inlining+NGEN
This PR (8238) - mean (835ms) : 819, 850
master - mean (833ms) : 807, 859
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Summary of changes
Stop sending the fixed
RootVersion = 1with every remote config requestReason for change
Currently we're sending a fixed value of
RootVersion = 1for all our remote config requests, but doing so causes the agent to repeatedly send us all the root certificates, significantly increasing the payload size, because it thinks we haven't seen them. Sending the "final" version, acknowledges it, and stops all the extra data, saving ~35kB per call.Implementation details
GetRcmResponse, leaving them as base64 encodedstrings (which is how they are sent in the payload)Base64DecodingStreamintroduced in AddBase64DecodingStream#8226 to avoid extra allocationsIArrayPoolfrom Add anIArrayPool<char>implementation for vendored Newtonsoft.JSON #8228MinimalTufRoot(in contrast toTufRoot) so that we only materialize what we need (theroots.signed.versionkey)This implementation avoids ~35kB per call for subsequent remote config requests.
Test coverage
Added unit test, and did manual test with the real agent, to confirm the expected behaviour (reduction in data sent)
Other details
https://datadoghq.atlassian.net/browse/LANGPLAT-940
All part of the Remote Config perf stack