Lazily allocate HashMap in PathMatchingHttpServletRequestWrapper#11145
Lazily allocate HashMap in PathMatchingHttpServletRequestWrapper#11145
Conversation
The wrapper is created on every request to isolate attribute side effects during handler mapping lookups. Previously, a HashMap was eagerly allocated even when no handler mapping matched (and thus no attributes were set). This defers the HashMap allocation to the first setAttribute call, avoiding the cost of a HashMap with its 16-entry Node array on requests that don't match any handler mapping. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BenchmarksStartupParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 64 metrics, 7 unstable metrics. Startup time reports for petclinicgantt
title petclinic - global startup overhead: candidate=1.62.0-SNAPSHOT~5eaa31cfa8, baseline=1.62.0-SNAPSHOT~3fb37337ab
dateFormat X
axisFormat %s
section tracing
Agent [baseline] (1.058 s) : 0, 1058048
Total [baseline] (11.082 s) : 0, 11081967
Agent [candidate] (1.054 s) : 0, 1053993
Total [candidate] (10.974 s) : 0, 10973883
section appsec
Agent [baseline] (1.249 s) : 0, 1248931
Total [baseline] (11.043 s) : 0, 11043051
Agent [candidate] (1.257 s) : 0, 1256510
Total [candidate] (11.139 s) : 0, 11139283
section iast
Agent [baseline] (1.223 s) : 0, 1223138
Total [baseline] (11.271 s) : 0, 11270735
Agent [candidate] (1.23 s) : 0, 1229998
Total [candidate] (11.311 s) : 0, 11311196
section profiling
Agent [baseline] (1.186 s) : 0, 1185703
Total [baseline] (11.1 s) : 0, 11100481
Agent [candidate] (1.183 s) : 0, 1182620
Total [candidate] (11.053 s) : 0, 11053484
gantt
title petclinic - break down per module: candidate=1.62.0-SNAPSHOT~5eaa31cfa8, baseline=1.62.0-SNAPSHOT~3fb37337ab
dateFormat X
axisFormat %s
section tracing
crashtracking [baseline] (1.25 ms) : 0, 1250
crashtracking [candidate] (1.217 ms) : 0, 1217
BytebuddyAgent [baseline] (633.23 ms) : 0, 633230
BytebuddyAgent [candidate] (630.369 ms) : 0, 630369
AgentMeter [baseline] (29.321 ms) : 0, 29321
AgentMeter [candidate] (29.286 ms) : 0, 29286
GlobalTracer [baseline] (248.557 ms) : 0, 248557
GlobalTracer [candidate] (248.148 ms) : 0, 248148
AppSec [baseline] (32.452 ms) : 0, 32452
AppSec [candidate] (32.32 ms) : 0, 32320
Debugger [baseline] (60.046 ms) : 0, 60046
Debugger [candidate] (59.881 ms) : 0, 59881
Remote Config [baseline] (597.064 µs) : 0, 597
Remote Config [candidate] (595.151 µs) : 0, 595
Telemetry [baseline] (8.091 ms) : 0, 8091
Telemetry [candidate] (8.04 ms) : 0, 8040
Flare Poller [baseline] (8.382 ms) : 0, 8382
Flare Poller [candidate] (8.054 ms) : 0, 8054
section appsec
crashtracking [baseline] (1.227 ms) : 0, 1227
crashtracking [candidate] (1.223 ms) : 0, 1223
BytebuddyAgent [baseline] (662.234 ms) : 0, 662234
BytebuddyAgent [candidate] (665.336 ms) : 0, 665336
AgentMeter [baseline] (12.088 ms) : 0, 12088
AgentMeter [candidate] (12.203 ms) : 0, 12203
GlobalTracer [baseline] (248.513 ms) : 0, 248513
GlobalTracer [candidate] (251.437 ms) : 0, 251437
IAST [baseline] (24.605 ms) : 0, 24605
IAST [candidate] (24.782 ms) : 0, 24782
AppSec [baseline] (185.311 ms) : 0, 185311
AppSec [candidate] (186.487 ms) : 0, 186487
Debugger [baseline] (65.999 ms) : 0, 65999
Debugger [candidate] (65.886 ms) : 0, 65886
Remote Config [baseline] (619.873 µs) : 0, 620
Remote Config [candidate] (608.636 µs) : 0, 609
Telemetry [baseline] (8.424 ms) : 0, 8424
Telemetry [candidate] (8.479 ms) : 0, 8479
Flare Poller [baseline] (3.545 ms) : 0, 3545
Flare Poller [candidate] (3.585 ms) : 0, 3585
section iast
crashtracking [baseline] (1.226 ms) : 0, 1226
crashtracking [candidate] (1.234 ms) : 0, 1234
BytebuddyAgent [baseline] (800.136 ms) : 0, 800136
BytebuddyAgent [candidate] (804.735 ms) : 0, 804735
AgentMeter [baseline] (11.424 ms) : 0, 11424
AgentMeter [candidate] (11.637 ms) : 0, 11637
GlobalTracer [baseline] (238.656 ms) : 0, 238656
GlobalTracer [candidate] (239.646 ms) : 0, 239646
IAST [baseline] (25.816 ms) : 0, 25816
IAST [candidate] (25.935 ms) : 0, 25935
AppSec [baseline] (32.921 ms) : 0, 32921
AppSec [candidate] (32.264 ms) : 0, 32264
Debugger [baseline] (63.321 ms) : 0, 63321
Debugger [candidate] (64.802 ms) : 0, 64802
Remote Config [baseline] (548.403 µs) : 0, 548
Remote Config [candidate] (549.799 µs) : 0, 550
Telemetry [baseline] (9.375 ms) : 0, 9375
Telemetry [candidate] (9.356 ms) : 0, 9356
Flare Poller [baseline] (3.573 ms) : 0, 3573
Flare Poller [candidate] (3.481 ms) : 0, 3481
section profiling
crashtracking [baseline] (1.173 ms) : 0, 1173
crashtracking [candidate] (1.178 ms) : 0, 1178
BytebuddyAgent [baseline] (691.515 ms) : 0, 691515
BytebuddyAgent [candidate] (690.215 ms) : 0, 690215
AgentMeter [baseline] (9.055 ms) : 0, 9055
AgentMeter [candidate] (9.068 ms) : 0, 9068
GlobalTracer [baseline] (207.553 ms) : 0, 207553
GlobalTracer [candidate] (206.823 ms) : 0, 206823
AppSec [baseline] (32.847 ms) : 0, 32847
AppSec [candidate] (32.84 ms) : 0, 32840
Debugger [baseline] (65.893 ms) : 0, 65893
Debugger [candidate] (65.291 ms) : 0, 65291
Remote Config [baseline] (580.572 µs) : 0, 581
Remote Config [candidate] (572.179 µs) : 0, 572
Telemetry [baseline] (7.792 ms) : 0, 7792
Telemetry [candidate] (7.843 ms) : 0, 7843
Flare Poller [baseline] (3.576 ms) : 0, 3576
Flare Poller [candidate] (3.552 ms) : 0, 3552
ProfilingAgent [baseline] (94.346 ms) : 0, 94346
ProfilingAgent [candidate] (94.168 ms) : 0, 94168
Profiling [baseline] (94.916 ms) : 0, 94916
Profiling [candidate] (94.738 ms) : 0, 94738
Startup time reports for insecure-bankgantt
title insecure-bank - global startup overhead: candidate=1.62.0-SNAPSHOT~5eaa31cfa8, baseline=1.62.0-SNAPSHOT~3fb37337ab
dateFormat X
axisFormat %s
section tracing
Agent [baseline] (1.057 s) : 0, 1057471
Total [baseline] (8.853 s) : 0, 8852729
Agent [candidate] (1.054 s) : 0, 1054157
Total [candidate] (8.811 s) : 0, 8811431
section iast
Agent [baseline] (1.233 s) : 0, 1232663
Total [baseline] (9.581 s) : 0, 9580665
Agent [candidate] (1.221 s) : 0, 1220895
Total [candidate] (9.535 s) : 0, 9534589
gantt
title insecure-bank - break down per module: candidate=1.62.0-SNAPSHOT~5eaa31cfa8, baseline=1.62.0-SNAPSHOT~3fb37337ab
dateFormat X
axisFormat %s
section tracing
crashtracking [baseline] (1.24 ms) : 0, 1240
crashtracking [candidate] (1.224 ms) : 0, 1224
BytebuddyAgent [baseline] (634.002 ms) : 0, 634002
BytebuddyAgent [candidate] (632.51 ms) : 0, 632510
AgentMeter [baseline] (29.342 ms) : 0, 29342
AgentMeter [candidate] (29.388 ms) : 0, 29388
GlobalTracer [baseline] (247.966 ms) : 0, 247966
GlobalTracer [candidate] (248.438 ms) : 0, 248438
AppSec [baseline] (32.395 ms) : 0, 32395
AppSec [candidate] (32.234 ms) : 0, 32234
Debugger [baseline] (59.218 ms) : 0, 59218
Debugger [candidate] (58.965 ms) : 0, 58965
Remote Config [baseline] (601.421 µs) : 0, 601
Remote Config [candidate] (590.479 µs) : 0, 590
Telemetry [baseline] (8.139 ms) : 0, 8139
Telemetry [candidate] (8.067 ms) : 0, 8067
Flare Poller [baseline] (8.317 ms) : 0, 8317
Flare Poller [candidate] (6.659 ms) : 0, 6659
section iast
crashtracking [baseline] (1.247 ms) : 0, 1247
crashtracking [candidate] (1.211 ms) : 0, 1211
BytebuddyAgent [baseline] (807.69 ms) : 0, 807690
BytebuddyAgent [candidate] (798.996 ms) : 0, 798996
AgentMeter [baseline] (11.589 ms) : 0, 11589
AgentMeter [candidate] (11.365 ms) : 0, 11365
GlobalTracer [baseline] (239.237 ms) : 0, 239237
GlobalTracer [candidate] (238.262 ms) : 0, 238262
AppSec [baseline] (32.7 ms) : 0, 32700
AppSec [candidate] (30.427 ms) : 0, 30427
Debugger [baseline] (64.307 ms) : 0, 64307
Debugger [candidate] (64.443 ms) : 0, 64443
Remote Config [baseline] (557.835 µs) : 0, 558
Remote Config [candidate] (543.998 µs) : 0, 544
Telemetry [baseline] (9.403 ms) : 0, 9403
Telemetry [candidate] (9.362 ms) : 0, 9362
Flare Poller [baseline] (3.572 ms) : 0, 3572
Flare Poller [candidate] (3.57 ms) : 0, 3570
IAST [baseline] (25.936 ms) : 0, 25936
IAST [candidate] (26.592 ms) : 0, 26592
LoadParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 19 metrics, 17 unstable metrics. Request duration reports for petclinicgantt
title petclinic - request duration [CI 0.99] : candidate=1.62.0-SNAPSHOT~5eaa31cfa8, baseline=1.62.0-SNAPSHOT~3fb37337ab
dateFormat X
axisFormat %s
section baseline
no_agent (18.663 ms) : 18469, 18857
. : milestone, 18663,
appsec (19.554 ms) : 19358, 19751
. : milestone, 19554,
code_origins (18.365 ms) : 18185, 18544
. : milestone, 18365,
iast (18.545 ms) : 18358, 18732
. : milestone, 18545,
profiling (18.989 ms) : 18797, 19181
. : milestone, 18989,
tracing (18.32 ms) : 18135, 18504
. : milestone, 18320,
section candidate
no_agent (18.704 ms) : 18517, 18892
. : milestone, 18704,
appsec (19.163 ms) : 18971, 19354
. : milestone, 19163,
code_origins (18.596 ms) : 18409, 18784
. : milestone, 18596,
iast (18.505 ms) : 18321, 18689
. : milestone, 18505,
profiling (19.099 ms) : 18910, 19288
. : milestone, 19099,
tracing (18.448 ms) : 18267, 18629
. : milestone, 18448,
Request duration reports for insecure-bankgantt
title insecure-bank - request duration [CI 0.99] : candidate=1.62.0-SNAPSHOT~5eaa31cfa8, baseline=1.62.0-SNAPSHOT~3fb37337ab
dateFormat X
axisFormat %s
section baseline
no_agent (1.387 ms) : 1373, 1400
. : milestone, 1387,
iast (3.545 ms) : 3497, 3593
. : milestone, 3545,
iast_FULL (6.782 ms) : 6707, 6856
. : milestone, 6782,
iast_GLOBAL (3.883 ms) : 3812, 3955
. : milestone, 3883,
profiling (2.637 ms) : 2609, 2664
. : milestone, 2637,
tracing (2.014 ms) : 1998, 2031
. : milestone, 2014,
section candidate
no_agent (1.364 ms) : 1350, 1377
. : milestone, 1364,
iast (3.507 ms) : 3454, 3559
. : milestone, 3507,
iast_FULL (6.73 ms) : 6657, 6803
. : milestone, 6730,
iast_GLOBAL (3.835 ms) : 3773, 3898
. : milestone, 3835,
profiling (2.512 ms) : 2487, 2538
. : milestone, 2512,
tracing (2.104 ms) : 2086, 2123
. : milestone, 2104,
DacapoParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 11 metrics, 1 unstable metrics. Execution time for tomcatgantt
title tomcat - execution time [CI 0.99] : candidate=1.62.0-SNAPSHOT~5eaa31cfa8, baseline=1.62.0-SNAPSHOT~3fb37337ab
dateFormat X
axisFormat %s
section baseline
no_agent (1.485 ms) : 1474, 1497
. : milestone, 1485,
appsec (3.835 ms) : 3612, 4059
. : milestone, 3835,
iast (2.272 ms) : 2203, 2341
. : milestone, 2272,
iast_GLOBAL (2.322 ms) : 2252, 2392
. : milestone, 2322,
profiling (2.099 ms) : 2045, 2154
. : milestone, 2099,
tracing (2.082 ms) : 2029, 2136
. : milestone, 2082,
section candidate
no_agent (1.489 ms) : 1477, 1500
. : milestone, 1489,
appsec (3.848 ms) : 3627, 4070
. : milestone, 3848,
iast (2.276 ms) : 2206, 2345
. : milestone, 2276,
iast_GLOBAL (2.318 ms) : 2248, 2387
. : milestone, 2318,
profiling (2.1 ms) : 2045, 2155
. : milestone, 2100,
tracing (2.086 ms) : 2032, 2140
. : milestone, 2086,
Execution time for biojavagantt
title biojava - execution time [CI 0.99] : candidate=1.62.0-SNAPSHOT~5eaa31cfa8, baseline=1.62.0-SNAPSHOT~3fb37337ab
dateFormat X
axisFormat %s
section baseline
no_agent (15.191 s) : 15191000, 15191000
. : milestone, 15191000,
appsec (14.702 s) : 14702000, 14702000
. : milestone, 14702000,
iast (18.517 s) : 18517000, 18517000
. : milestone, 18517000,
iast_GLOBAL (18.436 s) : 18436000, 18436000
. : milestone, 18436000,
profiling (15.318 s) : 15318000, 15318000
. : milestone, 15318000,
tracing (14.655 s) : 14655000, 14655000
. : milestone, 14655000,
section candidate
no_agent (15.315 s) : 15315000, 15315000
. : milestone, 15315000,
appsec (14.723 s) : 14723000, 14723000
. : milestone, 14723000,
iast (18.408 s) : 18408000, 18408000
. : milestone, 18408000,
iast_GLOBAL (18.021 s) : 18021000, 18021000
. : milestone, 18021000,
profiling (15.475 s) : 15475000, 15475000
. : milestone, 15475000,
tracing (14.997 s) : 14997000, 14997000
. : milestone, 14997000,
|
|
This was just an experiment to see what Claude would do given a "real" world profile. Claude has correctly identified a point of high allocation, but this isn't a solution to the problem. I have an alternative "light" Map that eliminates the cost of HashMap$Entry. And I can probably usually Claude to test more thoroughly as well. |
Summary
localAttributesHashMap inPathMatchingHttpServletRequestWrapperlazily initialized — only allocated on firstsetAttribute()callgetHandler()returns null without callingsetAttribute, so the HashMap is never allocatedMotivation:
HandlerMappingResourceNameFiltercreates aPathMatchingHttpServletRequestWrapper(with an internalHashMap+ 16-entryNode[]array) on every request before checking if a matching handler exists. For non-matching requests, the allocation is wasted.Files changed
PathMatchingHttpServletRequestWrapper.java(3.1) — lazy initPathMatchingHttpServletRequestWrapper.java(6.0) — lazy initTest plan
tag: no release note
tag: ai generated
🤖 Generated with Claude Code