Skip to content

Reducing memory allocation from client-side stats#10705

Open
dougqh wants to merge 6 commits intomasterfrom
dougqh/client-side-stats-overhead
Open

Reducing memory allocation from client-side stats#10705
dougqh wants to merge 6 commits intomasterfrom
dougqh/client-side-stats-overhead

Conversation

@dougqh
Copy link
Contributor

@dougqh dougqh commented Feb 27, 2026

What Does This Do

Introduces DDCache-s around UTF8BytesString construction

Motivation

UTF8BytesString are advantageous for serialization, but that only applies to the MetricKey instance that is actually serialized

Most MetricKey instances are only created to do a look-up into the map. so the UTF8BytesString creation was just extra work

This change reduces allocation by 6% and GC time by 7% in span creation stress test.
This change reduces impact on application throughput by 5-20% depending on heap size.

Additional Notes

This change is intended as a quick fix. I think there's still a lot of room for improvement by restructuring the code further, but that is left for a future PR.

Contributor Checklist

Jira ticket: [PROJ-IDENT]

Note: Once your PR is ready to merge, add it to the merge queue by commenting /merge. /merge -c cancels the queue request. /merge -f --reason "reason" skips all merge queue checks; please use this judiciously, as some checks do not run at the PR-level. For more information, see this doc.

Introduced DDCache-s around UTF8BytesString construction

UTF8BytesString are advantageous for serialization, but that only applies to the key instance that is actually serialized

Most key instances here are being created to do a look-up into the map. so the UTF8BytesString creation was extra work.

This change is intended as a quick fix.  I think there's still a lot of room for improvement by restructuring the code further, but that is left for a future PR.

As is this changer reduces the impact on application throughput by 5-20% depending on the heap size.
@dougqh dougqh requested a review from a team as a code owner February 27, 2026 21:19
@dougqh dougqh requested a review from amarziali February 27, 2026 21:19
@dougqh dougqh added type: enhancement Enhancements and improvements tag: performance Performance related changes comp: metrics Metrics labels Feb 27, 2026
@pr-commenter
Copy link

pr-commenter bot commented Feb 27, 2026

Benchmarks

Startup

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master dougqh/client-side-stats-overhead
git_commit_date 1773155932 1773158244
git_commit_sha c04d61b 419a462
release_version 1.61.0-SNAPSHOT~c04d61b318 1.60.0-SNAPSHOT~419a462a59
See matching parameters
Baseline Candidate
application insecure-bank insecure-bank
ci_job_date 1773160262 1773160262
ci_job_id 1493234433 1493234433
ci_pipeline_id 101656327 101656327
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
kernel_version Linux runner-zfyrx7zua-project-304-concurrent-3-pjmboxh5 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux Linux runner-zfyrx7zua-project-304-concurrent-3-pjmboxh5 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
module Agent Agent
parent None None

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 66 metrics, 5 unstable metrics.

Startup time reports for petclinic
gantt
    title petclinic - global startup overhead: candidate=1.60.0-SNAPSHOT~419a462a59, baseline=1.61.0-SNAPSHOT~c04d61b318

    dateFormat X
    axisFormat %s
section tracing
Agent [baseline] (1.058 s) : 0, 1058393
Total [baseline] (11.001 s) : 0, 11000773
Agent [candidate] (1.058 s) : 0, 1058485
Total [candidate] (11.007 s) : 0, 11007454
section appsec
Agent [baseline] (1.246 s) : 0, 1246132
Total [baseline] (11.172 s) : 0, 11171522
Agent [candidate] (1.244 s) : 0, 1244422
Total [candidate] (11.154 s) : 0, 11154275
section iast
Agent [baseline] (1.225 s) : 0, 1225146
Total [baseline] (11.29 s) : 0, 11289807
Agent [candidate] (1.233 s) : 0, 1232797
Total [candidate] (11.343 s) : 0, 11343473
section profiling
Agent [baseline] (1.182 s) : 0, 1182434
Total [baseline] (10.97 s) : 0, 10969563
Agent [candidate] (1.181 s) : 0, 1181073
Total [candidate] (11.042 s) : 0, 11041774
Loading
  • baseline results
Module Variant Duration Δ tracing
Agent tracing 1.058 s -
Agent appsec 1.246 s 187.739 ms (17.7%)
Agent iast 1.225 s 166.754 ms (15.8%)
Agent profiling 1.182 s 124.041 ms (11.7%)
Total tracing 11.001 s -
Total appsec 11.172 s 170.749 ms (1.6%)
Total iast 11.29 s 289.034 ms (2.6%)
Total profiling 10.97 s -31.21 ms (-0.3%)
  • candidate results
Module Variant Duration Δ tracing
Agent tracing 1.058 s -
Agent appsec 1.244 s 185.936 ms (17.6%)
Agent iast 1.233 s 174.312 ms (16.5%)
Agent profiling 1.181 s 122.587 ms (11.6%)
Total tracing 11.007 s -
Total appsec 11.154 s 146.822 ms (1.3%)
Total iast 11.343 s 336.019 ms (3.1%)
Total profiling 11.042 s 34.321 ms (0.3%)
gantt
    title petclinic - break down per module: candidate=1.60.0-SNAPSHOT~419a462a59, baseline=1.61.0-SNAPSHOT~c04d61b318

    dateFormat X
    axisFormat %s
section tracing
crashtracking [baseline] (1.192 ms) : 0, 1192
crashtracking [candidate] (1.182 ms) : 0, 1182
BytebuddyAgent [baseline] (628.345 ms) : 0, 628345
BytebuddyAgent [candidate] (627.002 ms) : 0, 627002
AgentMeter [baseline] (29.198 ms) : 0, 29198
AgentMeter [candidate] (29.102 ms) : 0, 29102
GlobalTracer [baseline] (257.145 ms) : 0, 257145
GlobalTracer [candidate] (256.654 ms) : 0, 256654
AppSec [baseline] (31.577 ms) : 0, 31577
AppSec [candidate] (31.402 ms) : 0, 31402
Debugger [baseline] (59.777 ms) : 0, 59777
Debugger [candidate] (59.445 ms) : 0, 59445
Remote Config [baseline] (596.963 µs) : 0, 597
Remote Config [candidate] (581.85 µs) : 0, 582
Telemetry [baseline] (8.713 ms) : 0, 8713
Telemetry [candidate] (8.596 ms) : 0, 8596
Flare Poller [baseline] (5.801 ms) : 0, 5801
Flare Poller [candidate] (8.65 ms) : 0, 8650
section appsec
crashtracking [baseline] (1.192 ms) : 0, 1192
crashtracking [candidate] (1.185 ms) : 0, 1185
BytebuddyAgent [baseline] (658.215 ms) : 0, 658215
BytebuddyAgent [candidate] (657.656 ms) : 0, 657656
AgentMeter [baseline] (11.994 ms) : 0, 11994
AgentMeter [candidate] (12.025 ms) : 0, 12025
GlobalTracer [baseline] (257.906 ms) : 0, 257906
GlobalTracer [candidate] (257.686 ms) : 0, 257686
AppSec [baseline] (177.519 ms) : 0, 177519
AppSec [candidate] (177.137 ms) : 0, 177137
Debugger [baseline] (65.154 ms) : 0, 65154
Debugger [candidate] (65.51 ms) : 0, 65510
Remote Config [baseline] (580.65 µs) : 0, 581
Remote Config [candidate] (570.64 µs) : 0, 571
Telemetry [baseline] (9.786 ms) : 0, 9786
Telemetry [candidate] (8.943 ms) : 0, 8943
Flare Poller [baseline] (3.6 ms) : 0, 3600
Flare Poller [candidate] (3.585 ms) : 0, 3585
IAST [baseline] (23.938 ms) : 0, 23938
IAST [candidate] (23.94 ms) : 0, 23940
section iast
crashtracking [baseline] (1.184 ms) : 0, 1184
crashtracking [candidate] (1.196 ms) : 0, 1196
BytebuddyAgent [baseline] (794.809 ms) : 0, 794809
BytebuddyAgent [candidate] (800.519 ms) : 0, 800519
AgentMeter [baseline] (11.315 ms) : 0, 11315
AgentMeter [candidate] (11.539 ms) : 0, 11539
GlobalTracer [baseline] (246.82 ms) : 0, 246820
GlobalTracer [candidate] (248.102 ms) : 0, 248102
AppSec [baseline] (26.449 ms) : 0, 26449
AppSec [candidate] (26.515 ms) : 0, 26515
Debugger [baseline] (63.217 ms) : 0, 63217
Debugger [candidate] (63.348 ms) : 0, 63348
Remote Config [baseline] (541.977 µs) : 0, 542
Remote Config [candidate] (538.707 µs) : 0, 539
Telemetry [baseline] (14.681 ms) : 0, 14681
Telemetry [candidate] (14.898 ms) : 0, 14898
Flare Poller [baseline] (4.915 ms) : 0, 4915
Flare Poller [candidate] (4.893 ms) : 0, 4893
IAST [baseline] (25.164 ms) : 0, 25164
IAST [candidate] (25.278 ms) : 0, 25278
section profiling
ProfilingAgent [baseline] (93.85 ms) : 0, 93850
ProfilingAgent [candidate] (93.576 ms) : 0, 93576
crashtracking [baseline] (1.168 ms) : 0, 1168
crashtracking [candidate] (1.169 ms) : 0, 1169
BytebuddyAgent [baseline] (683.21 ms) : 0, 683210
BytebuddyAgent [candidate] (682.336 ms) : 0, 682336
AgentMeter [baseline] (8.604 ms) : 0, 8604
AgentMeter [candidate] (8.586 ms) : 0, 8586
GlobalTracer [baseline] (215.309 ms) : 0, 215309
GlobalTracer [candidate] (215.376 ms) : 0, 215376
AppSec [baseline] (32.032 ms) : 0, 32032
AppSec [candidate] (31.918 ms) : 0, 31918
Debugger [baseline] (62.887 ms) : 0, 62887
Debugger [candidate] (62.873 ms) : 0, 62873
Remote Config [baseline] (586.981 µs) : 0, 587
Remote Config [candidate] (579.334 µs) : 0, 579
Telemetry [baseline] (9.746 ms) : 0, 9746
Telemetry [candidate] (10.411 ms) : 0, 10411
Flare Poller [baseline] (4.306 ms) : 0, 4306
Flare Poller [candidate] (3.554 ms) : 0, 3554
Profiling [baseline] (94.411 ms) : 0, 94411
Profiling [candidate] (94.136 ms) : 0, 94136
Loading
Startup time reports for insecure-bank
gantt
    title insecure-bank - global startup overhead: candidate=1.60.0-SNAPSHOT~419a462a59, baseline=1.61.0-SNAPSHOT~c04d61b318

    dateFormat X
    axisFormat %s
section tracing
Agent [baseline] (1.066 s) : 0, 1066102
Total [baseline] (8.895 s) : 0, 8894684
Agent [candidate] (1.063 s) : 0, 1063281
Total [candidate] (8.803 s) : 0, 8802710
section iast
Agent [baseline] (1.225 s) : 0, 1224996
Total [baseline] (9.552 s) : 0, 9552138
Agent [candidate] (1.224 s) : 0, 1224428
Total [candidate] (9.571 s) : 0, 9571258
Loading
  • baseline results
Module Variant Duration Δ tracing
Agent tracing 1.066 s -
Agent iast 1.225 s 158.894 ms (14.9%)
Total tracing 8.895 s -
Total iast 9.552 s 657.454 ms (7.4%)
  • candidate results
Module Variant Duration Δ tracing
Agent tracing 1.063 s -
Agent iast 1.224 s 161.147 ms (15.2%)
Total tracing 8.803 s -
Total iast 9.571 s 768.548 ms (8.7%)
gantt
    title insecure-bank - break down per module: candidate=1.60.0-SNAPSHOT~419a462a59, baseline=1.61.0-SNAPSHOT~c04d61b318

    dateFormat X
    axisFormat %s
section tracing
crashtracking [baseline] (1.202 ms) : 0, 1202
crashtracking [candidate] (1.213 ms) : 0, 1213
BytebuddyAgent [baseline] (633.259 ms) : 0, 633259
BytebuddyAgent [candidate] (631.018 ms) : 0, 631018
AgentMeter [baseline] (29.278 ms) : 0, 29278
AgentMeter [candidate] (29.262 ms) : 0, 29262
GlobalTracer [baseline] (258.51 ms) : 0, 258510
GlobalTracer [candidate] (257.756 ms) : 0, 257756
AppSec [baseline] (31.86 ms) : 0, 31860
AppSec [candidate] (31.761 ms) : 0, 31761
Debugger [baseline] (59.268 ms) : 0, 59268
Debugger [candidate] (59.076 ms) : 0, 59076
Remote Config [baseline] (590.816 µs) : 0, 591
Remote Config [candidate] (598.962 µs) : 0, 599
Telemetry [baseline] (8.735 ms) : 0, 8735
Telemetry [candidate] (8.684 ms) : 0, 8684
Flare Poller [baseline] (7.26 ms) : 0, 7260
Flare Poller [candidate] (7.838 ms) : 0, 7838
section iast
crashtracking [baseline] (1.191 ms) : 0, 1191
crashtracking [candidate] (1.2 ms) : 0, 1200
BytebuddyAgent [baseline] (795.605 ms) : 0, 795605
BytebuddyAgent [candidate] (794.212 ms) : 0, 794212
AgentMeter [baseline] (11.278 ms) : 0, 11278
AgentMeter [candidate] (11.321 ms) : 0, 11321
GlobalTracer [baseline] (246.708 ms) : 0, 246708
GlobalTracer [candidate] (246.802 ms) : 0, 246802
IAST [baseline] (25.175 ms) : 0, 25175
IAST [candidate] (25.132 ms) : 0, 25132
AppSec [baseline] (26.42 ms) : 0, 26420
AppSec [candidate] (26.391 ms) : 0, 26391
Debugger [baseline] (62.48 ms) : 0, 62480
Debugger [candidate] (63.016 ms) : 0, 63016
Remote Config [baseline] (520.959 µs) : 0, 521
Remote Config [candidate] (516.654 µs) : 0, 517
Telemetry [baseline] (14.717 ms) : 0, 14717
Telemetry [candidate] (14.935 ms) : 0, 14935
Flare Poller [baseline] (4.896 ms) : 0, 4896
Flare Poller [candidate] (4.919 ms) : 0, 4919
Loading

Load

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master dougqh/client-side-stats-overhead
git_commit_date 1773155932 1773158244
git_commit_sha c04d61b 419a462
release_version 1.61.0-SNAPSHOT~c04d61b318 1.60.0-SNAPSHOT~419a462a59
See matching parameters
Baseline Candidate
application insecure-bank insecure-bank
ci_job_date 1773160744 1773160744
ci_job_id 1493234434 1493234434
ci_pipeline_id 101656327 101656327
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
kernel_version Linux runner-zfyrx7zua-project-304-concurrent-4-fya5tub8 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux Linux runner-zfyrx7zua-project-304-concurrent-4-fya5tub8 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

Summary

Found 3 performance improvements and 2 performance regressions! Performance is the same for 14 metrics, 17 unstable metrics.

scenario Δ mean agg_http_req_duration_p50 Δ mean agg_http_req_duration_p95 Δ mean throughput candidate mean agg_http_req_duration_p50 candidate mean agg_http_req_duration_p95 candidate mean throughput baseline mean agg_http_req_duration_p50 baseline mean agg_http_req_duration_p95 baseline mean throughput
scenario:load:insecure-bank:iast:high_load better
[-168.529µs; -55.242µs] or [-6.730%; -2.206%]
same
[-205.782µs; +173.383µs] or [-2.853%; +2.404%]
unstable
[-110.244op/s; +199.119op/s] or [-7.726%; +13.954%]
2.392ms 7.196ms 1471.406op/s 2.504ms 7.213ms 1426.969op/s
scenario:load:insecure-bank:iast_GLOBAL:high_load better
[-268.991µs; -161.206µs] or [-9.461%; -5.670%]
unstable
[-903.572µs; +1855.902µs] or [-11.601%; +23.828%]
unstable
[-86.024op/s; +209.774op/s] or [-6.674%; +16.275%]
2.628ms 8.265ms 1350.844op/s 2.843ms 7.789ms 1288.969op/s
scenario:load:insecure-bank:iast_FULL:high_load better
[-323.202µs; -151.058µs] or [-6.186%; -2.891%]
unsure
[-713.773µs; -247.004µs] or [-5.743%; -1.987%]
unstable
[-42.970op/s; +114.033op/s] or [-5.464%; +14.501%]
4.988ms 11.948ms 821.906op/s 5.225ms 12.428ms 786.375op/s
scenario:load:petclinic:tracing:high_load worse
[+0.735ms; +1.643ms] or [+4.264%; +9.525%]
worse
[+0.967ms; +2.765ms] or [+3.423%; +9.785%]
unstable
[-43.663op/s; +9.101op/s] or [-16.453%; +3.429%]
18.436ms 30.124ms 248.094op/s 17.247ms 28.257ms 265.375op/s
Request duration reports for insecure-bank
gantt
    title insecure-bank - request duration [CI 0.99] : candidate=1.60.0-SNAPSHOT~419a462a59, baseline=1.61.0-SNAPSHOT~c04d61b318
    dateFormat X
    axisFormat %s
section baseline
no_agent (1.232 ms) : 1220, 1244
.   : milestone, 1232,
iast (3.204 ms) : 3160, 3248
.   : milestone, 3204,
iast_FULL (5.878 ms) : 5819, 5937
.   : milestone, 5878,
iast_GLOBAL (3.557 ms) : 3504, 3610
.   : milestone, 3557,
profiling (2.051 ms) : 2031, 2072
.   : milestone, 2051,
tracing (1.801 ms) : 1786, 1816
.   : milestone, 1801,
section candidate
no_agent (1.213 ms) : 1200, 1225
.   : milestone, 1213,
iast (3.108 ms) : 3068, 3148
.   : milestone, 3108,
iast_FULL (5.625 ms) : 5569, 5681
.   : milestone, 5625,
iast_GLOBAL (3.392 ms) : 3337, 3447
.   : milestone, 3392,
profiling (2.146 ms) : 2125, 2166
.   : milestone, 2146,
tracing (1.766 ms) : 1750, 1781
.   : milestone, 1766,
Loading
  • baseline results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 1.232 ms [1.22 ms, 1.244 ms] -
iast 3.204 ms [3.16 ms, 3.248 ms] 1.972 ms (160.0%)
iast_FULL 5.878 ms [5.819 ms, 5.937 ms] 4.646 ms (377.0%)
iast_GLOBAL 3.557 ms [3.504 ms, 3.61 ms] 2.325 ms (188.7%)
profiling 2.051 ms [2.031 ms, 2.072 ms] 818.922 µs (66.5%)
tracing 1.801 ms [1.786 ms, 1.816 ms] 568.561 µs (46.1%)
  • candidate results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 1.213 ms [1.2 ms, 1.225 ms] -
iast 3.108 ms [3.068 ms, 3.148 ms] 1.895 ms (156.3%)
iast_FULL 5.625 ms [5.569 ms, 5.681 ms] 4.412 ms (363.9%)
iast_GLOBAL 3.392 ms [3.337 ms, 3.447 ms] 2.179 ms (179.7%)
profiling 2.146 ms [2.125 ms, 2.166 ms] 932.904 µs (76.9%)
tracing 1.766 ms [1.75 ms, 1.781 ms] 553.241 µs (45.6%)
Request duration reports for petclinic
gantt
    title petclinic - request duration [CI 0.99] : candidate=1.60.0-SNAPSHOT~419a462a59, baseline=1.61.0-SNAPSHOT~c04d61b318
    dateFormat X
    axisFormat %s
section baseline
no_agent (18.06 ms) : 17875, 18245
.   : milestone, 18060,
appsec (18.688 ms) : 18499, 18878
.   : milestone, 18688,
code_origins (17.738 ms) : 17563, 17914
.   : milestone, 17738,
iast (17.826 ms) : 17645, 18006
.   : milestone, 17826,
profiling (18.809 ms) : 18622, 18997
.   : milestone, 18809,
tracing (17.581 ms) : 17411, 17752
.   : milestone, 17581,
section candidate
no_agent (18.077 ms) : 17893, 18261
.   : milestone, 18077,
appsec (18.703 ms) : 18515, 18891
.   : milestone, 18703,
code_origins (17.827 ms) : 17648, 18007
.   : milestone, 17827,
iast (17.814 ms) : 17637, 17992
.   : milestone, 17814,
profiling (18.614 ms) : 18430, 18799
.   : milestone, 18614,
tracing (18.813 ms) : 18619, 19006
.   : milestone, 18813,
Loading
  • baseline results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 18.06 ms [17.875 ms, 18.245 ms] -
appsec 18.688 ms [18.499 ms, 18.878 ms] 627.958 µs (3.5%)
code_origins 17.738 ms [17.563 ms, 17.914 ms] -321.858 µs (-1.8%)
iast 17.826 ms [17.645 ms, 18.006 ms] -234.551 µs (-1.3%)
profiling 18.809 ms [18.622 ms, 18.997 ms] 749.312 µs (4.1%)
tracing 17.581 ms [17.411 ms, 17.752 ms] -478.964 µs (-2.7%)
  • candidate results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 18.077 ms [17.893 ms, 18.261 ms] -
appsec 18.703 ms [18.515 ms, 18.891 ms] 625.535 µs (3.5%)
code_origins 17.827 ms [17.648 ms, 18.007 ms] -249.633 µs (-1.4%)
iast 17.814 ms [17.637 ms, 17.992 ms] -262.718 µs (-1.5%)
profiling 18.614 ms [18.43 ms, 18.799 ms] 537.273 µs (3.0%)
tracing 18.813 ms [18.619 ms, 19.006 ms] 735.441 µs (4.1%)

Dacapo

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master dougqh/client-side-stats-overhead
git_commit_date 1773155932 1773158244
git_commit_sha c04d61b 419a462
release_version 1.61.0-SNAPSHOT~c04d61b318 1.60.0-SNAPSHOT~419a462a59
See matching parameters
Baseline Candidate
application biojava biojava
ci_job_date 1773160484 1773160484
ci_job_id 1493234435 1493234435
ci_pipeline_id 101656327 101656327
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
kernel_version Linux runner-zfyrx7zua-project-304-concurrent-2-sfc2x4kv 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux Linux runner-zfyrx7zua-project-304-concurrent-2-sfc2x4kv 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

Summary

Found 1 performance improvements and 0 performance regressions! Performance is the same for 11 metrics, 0 unstable metrics.

scenario Δ mean execution_time candidate mean execution_time baseline mean execution_time
scenario:dacapo:tomcat:appsec better
[-1.437ms; -1.091ms] or [-38.082%; -28.904%]
2.510ms 3.774ms
Execution time for tomcat
gantt
    title tomcat - execution time [CI 0.99] : candidate=1.60.0-SNAPSHOT~419a462a59, baseline=1.61.0-SNAPSHOT~c04d61b318
    dateFormat X
    axisFormat %s
section baseline
no_agent (1.47 ms) : 1458, 1482
.   : milestone, 1470,
appsec (3.774 ms) : 3553, 3995
.   : milestone, 3774,
iast (2.243 ms) : 2174, 2312
.   : milestone, 2243,
iast_GLOBAL (2.289 ms) : 2219, 2358
.   : milestone, 2289,
profiling (2.102 ms) : 2046, 2158
.   : milestone, 2102,
tracing (2.069 ms) : 2016, 2123
.   : milestone, 2069,
section candidate
no_agent (1.474 ms) : 1463, 1486
.   : milestone, 1474,
appsec (2.51 ms) : 2455, 2565
.   : milestone, 2510,
iast (2.256 ms) : 2186, 2325
.   : milestone, 2256,
iast_GLOBAL (2.295 ms) : 2226, 2365
.   : milestone, 2295,
profiling (2.071 ms) : 2016, 2125
.   : milestone, 2071,
tracing (2.071 ms) : 2018, 2125
.   : milestone, 2071,
Loading
  • baseline results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 1.47 ms [1.458 ms, 1.482 ms] -
appsec 3.774 ms [3.553 ms, 3.995 ms] 2.304 ms (156.7%)
iast 2.243 ms [2.174 ms, 2.312 ms] 772.931 µs (52.6%)
iast_GLOBAL 2.289 ms [2.219 ms, 2.358 ms] 818.591 µs (55.7%)
profiling 2.102 ms [2.046 ms, 2.158 ms] 632.186 µs (43.0%)
tracing 2.069 ms [2.016 ms, 2.123 ms] 599.341 µs (40.8%)
  • candidate results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 1.474 ms [1.463 ms, 1.486 ms] -
appsec 2.51 ms [2.455 ms, 2.565 ms] 1.036 ms (70.2%)
iast 2.256 ms [2.186 ms, 2.325 ms] 781.206 µs (53.0%)
iast_GLOBAL 2.295 ms [2.226 ms, 2.365 ms] 820.988 µs (55.7%)
profiling 2.071 ms [2.016 ms, 2.125 ms] 596.2 µs (40.4%)
tracing 2.071 ms [2.018 ms, 2.125 ms] 597.02 µs (40.5%)
Execution time for biojava
gantt
    title biojava - execution time [CI 0.99] : candidate=1.60.0-SNAPSHOT~419a462a59, baseline=1.61.0-SNAPSHOT~c04d61b318
    dateFormat X
    axisFormat %s
section baseline
no_agent (14.952 s) : 14952000, 14952000
.   : milestone, 14952000,
appsec (15.074 s) : 15074000, 15074000
.   : milestone, 15074000,
iast (17.92 s) : 17920000, 17920000
.   : milestone, 17920000,
iast_GLOBAL (17.888 s) : 17888000, 17888000
.   : milestone, 17888000,
profiling (15.456 s) : 15456000, 15456000
.   : milestone, 15456000,
tracing (15.333 s) : 15333000, 15333000
.   : milestone, 15333000,
section candidate
no_agent (14.713 s) : 14713000, 14713000
.   : milestone, 14713000,
appsec (14.895 s) : 14895000, 14895000
.   : milestone, 14895000,
iast (18.327 s) : 18327000, 18327000
.   : milestone, 18327000,
iast_GLOBAL (17.8 s) : 17800000, 17800000
.   : milestone, 17800000,
profiling (15.202 s) : 15202000, 15202000
.   : milestone, 15202000,
tracing (15.03 s) : 15030000, 15030000
.   : milestone, 15030000,
Loading
  • baseline results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 14.952 s [14.952 s, 14.952 s] -
appsec 15.074 s [15.074 s, 15.074 s] 122.0 ms (0.8%)
iast 17.92 s [17.92 s, 17.92 s] 2.968 s (19.9%)
iast_GLOBAL 17.888 s [17.888 s, 17.888 s] 2.936 s (19.6%)
profiling 15.456 s [15.456 s, 15.456 s] 504.0 ms (3.4%)
tracing 15.333 s [15.333 s, 15.333 s] 381.0 ms (2.5%)
  • candidate results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 14.713 s [14.713 s, 14.713 s] -
appsec 14.895 s [14.895 s, 14.895 s] 182.0 ms (1.2%)
iast 18.327 s [18.327 s, 18.327 s] 3.614 s (24.6%)
iast_GLOBAL 17.8 s [17.8 s, 17.8 s] 3.087 s (21.0%)
profiling 15.202 s [15.202 s, 15.202 s] 489.0 ms (3.3%)
tracing 15.03 s [15.03 s, 15.03 s] 317.0 ms (2.2%)

public final class MetricKey {
static final DDCache<String, UTF8BytesString> RESOURCE_CACHE = DDCaches.newFixedSizeCache(32);
static final DDCache<String, UTF8BytesString> SERVICE_CACHE = DDCaches.newFixedSizeCache(8);
static final DDCache<String, UTF8BytesString> SERVICE_SOURCE_CACHE = DDCaches.newFixedSizeCache(4);
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be already filled with UTF8BytesString. It can take values of the instrumentation name (that's should also be UTF8BytesString) so I suggest removing caching for this specific one. 4, is also too small

Copy link
Contributor Author

@dougqh dougqh Mar 9, 2026

Choose a reason for hiding this comment

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

The lookup logic accounts for receiving a UTF8BytesString and in that case bypasses the cache entirely.

Also, I erred on the side of keeping the caches small. I just want to eliminate most of the allocation - not all of the allocation.
That said, I may have misunderstood what "serviceSource" is so maybe that one should be larger. If it is instrumentations, then maybe we should increase it to 16. (The thinking being that only a few instrumentations are typically active in a given system.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If it can only be a UTF8BytesString, we could also tighten the type in the constructor. Although in that case, the JIT would dead code eliminate using the cache anyway (except for the initial allocation).

Comment on lines +18 to +21
static final DDCache<String, UTF8BytesString> TYPE_CACHE = DDCaches.newFixedSizeCache(8);
static final DDCache<String, UTF8BytesString> KIND_CACHE = DDCaches.newFixedSizeCache(8);
static final DDCache<String, UTF8BytesString> HTTP_METHOD_CACHE = DDCaches.newFixedSizeCache(8);
static final DDCache<String, UTF8BytesString> HTTP_ENDPOINT_CACHE = DDCaches.newFixedSizeCache(32);
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be possible to widen those a bit? Also, for the http endpoint, I'm wondering if we should just do that caching earlier to make other serialisation benefitting of this (i.e. in EndpointResolver)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I erred on the side of making the caches small.
The thinking is any object reuse is an improvement over what we were doing, but consuming too much memory could be harmful.

}

static UTF8BytesString utf8(DDCache<String, UTF8BytesString> cache, CharSequence charSeq) {
if ( charSeq == null ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

There are things that are supposing to check nullity of this. Now if we replace with empty is not more the same semantic and this will break some code. I suggest to let the caller return the default value so it won't break the existing logic

Copy link
Contributor Author

@dougqh dougqh Mar 9, 2026

Choose a reason for hiding this comment

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

Nevermind - I see that I did accidentally change the semantics for method & endpoint. I'll fix that.

I kept the semantics that already existed. If you look at the prior code, null was replaced with EMPTY, so I did the same.

Copy link
Contributor

Choose a reason for hiding this comment

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

well there are things that are OK to return empty but others needs to be literally null (i.e. service source, httpMethod, httpEndpoint)

Copy link
Contributor Author

@dougqh dougqh Mar 9, 2026

Choose a reason for hiding this comment

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

Yes, I realized after my initial reply. I'll double check all of them.

Copy link
Contributor Author

@dougqh dougqh Mar 9, 2026

Choose a reason for hiding this comment

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

Since the split of EMPTY vs null was about 50 / 50, I decided to just restore the null checks in the constructor.

dougqh added 4 commits March 9, 2026 13:19
- fix null handling for http method & endpoint
- increase service source cache size
Since it about a 50/50 split between cases that use EMPTY vs null, when a null is passed

I decided to just put the null handling back into the constructor.
That makes the choice more explicit, and makes the PR easier to review / compare to the prior logic
public final class MetricKey {
static final DDCache<String, UTF8BytesString> RESOURCE_CACHE = DDCaches.newFixedSizeCache(32);
static final DDCache<String, UTF8BytesString> SERVICE_CACHE = DDCaches.newFixedSizeCache(8);
static final DDCache<String, UTF8BytesString> SERVICE_SOURCE_CACHE =
Copy link
Contributor

Choose a reason for hiding this comment

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

That field does not need to be cached, for two main reasons:

  1. It is already either a UTF8BytesString or null. In fact, it comes from the component() method, which in helpers typically returns a UTF8BytesString.
  2. Its cardinality matches that of the instrumentations, the size of the cache is too small.

The constructor calling UTF8BytesString.create() may look confusing at first glance, but in this case it does not allocate a new object — it simply returns the existing instance. It was kept for consistency with the usual pattern.

Unless there are strong counterarguments, I would suggest removing the cache for this field.

Copy link
Contributor Author

@dougqh dougqh Mar 10, 2026

Choose a reason for hiding this comment

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

I think the key part here is "typically returns a UTF8BytesString".
The static typing doesn't currently guarantee it.

And the caching code accounts for the case of receiving a UTF8BytesString by bypassing the cache. In the same manner as UTF8BytesString.create did previously.

When a UTF8BytesString is passed, the cache incurs no overhead other than the static overhead of the cache array itself. But in the case where something other than UTF8BytesString is passed, the cache can significantly reduce memory consumption.

I think that's important because we need to curtail the worst case outcomes.

As for the size, the cardinality doesn't need to match total instrumentations. That would be too large. The size just needs to accommodate the active span producing instrumentations. As I said, I erred on the small size, since I want to avoid the worst case of consuming a lot of static memory.

And assuming a UTF8BytesString is introducing a subtle form of coupling that could easily be compromised by someone later on.

Copy link
Contributor

@amarziali amarziali left a comment

Choose a reason for hiding this comment

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

Thanks for that improvement. wrt service name source, as per our chat, we might simplify trying changing the signature of that constructor if possible and shortcut the cache if we ensure that every value is already an UTF8BytesString itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: metrics Metrics tag: performance Performance related changes type: enhancement Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants