[Debugger] Harden SnapshotPruner fallback handling#8567
Conversation
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8567) 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 (8567) - mean (74ms) : 69, 78
master - mean (75ms) : 70, 79
section Bailout
This PR (8567) - mean (80ms) : 75, 84
master - mean (78ms) : 76, 80
section CallTarget+Inlining+NGEN
This PR (8567) - mean (1,136ms) : 1067, 1204
master - mean (1,124ms) : 1081, 1168
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 (8567) - mean (118ms) : 112, 124
master - mean (113ms) : 110, 117
section Bailout
This PR (8567) - mean (115ms) : 111, 120
master - mean (118ms) : 112, 124
section CallTarget+Inlining+NGEN
This PR (8567) - mean (813ms) : 791, 836
master - mean (810ms) : 782, 838
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8567) - mean (105ms) : 99, 111
master - mean (102ms) : 98, 106
section Bailout
This PR (8567) - mean (104ms) : 101, 107
master - mean (104ms) : 99, 110
section CallTarget+Inlining+NGEN
This PR (8567) - mean (950ms) : 911, 988
master - mean (944ms) : 909, 980
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8567) - mean (102ms) : 96, 108
master - mean (100ms) : 97, 104
section Bailout
This PR (8567) - mean (104ms) : 98, 109
master - mean (103ms) : 99, 108
section CallTarget+Inlining+NGEN
This PR (8567) - mean (834ms) : 772, 896
master - mean (833ms) : 792, 874
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 (8567) - mean (195ms) : 189, 201
master - mean (196ms) : 192, 199
section Bailout
This PR (8567) - mean (197ms) : 195, 199
master - mean (198ms) : 196, 201
section CallTarget+Inlining+NGEN
This PR (8567) - mean (1,214ms) : 1153, 1274
master - mean (1,209ms) : 1158, 1259
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 (8567) - mean (277ms) : 272, 282
master - mean (279ms) : 274, 285
section Bailout
This PR (8567) - mean (277ms) : 274, 280
master - mean (279ms) : 276, 283
section CallTarget+Inlining+NGEN
This PR (8567) - mean (957ms) : 939, 975
master - mean (962ms) : 934, 990
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8567) - mean (271ms) : 267, 276
master - mean (271ms) : 267, 275
section Bailout
This PR (8567) - mean (274ms) : 270, 278
master - mean (271ms) : 268, 274
section CallTarget+Inlining+NGEN
This PR (8567) - mean (1,150ms) : 1100, 1199
master - mean (1,147ms) : 1107, 1187
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8567) - mean (270ms) : 266, 274
master - mean (273ms) : 267, 278
section Bailout
This PR (8567) - mean (269ms) : 266, 272
master - mean (269ms) : 266, 273
section CallTarget+Inlining+NGEN
This PR (8567) - mean (1,027ms) : 985, 1069
master - mean (1,022ms) : 986, 1059
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BenchmarksBenchmark execution time: 2026-05-11 11:08:31 Comparing candidate commit 84f3ac7 in PR branch Some scenarios are present only in baseline or only in candidate runs. If you didn't create or remove some scenarios in your branch, this maybe a sign of crashed benchmarks 💥💥💥 Scenarios present only in baseline:
Found 3 performance improvements and 3 performance regressions! Performance is the same for 51 metrics, 15 unstable metrics, 84 known flaky benchmarks, 42 flaky benchmarks without significant changes.
|
efe5f6d to
7e388cc
Compare
| if (nextSegmentStart < 0 || nextSegmentStart > snapshot.Length || nextSegmentLength < 0 || (nextSegmentStart + nextSegmentLength) > snapshot.Length) | ||
| { | ||
| // Malformed segment boundaries - abort pruning | ||
| StringBuilderCache.Release(sb); |
There was a problem hiding this comment.
why not used a try/finally for releasing sb?
if there is any exception during the process you may leak a sb, no?
There was a problem hiding this comment.
It wouldn’t be a leak because Acquire() makes sure the local sb becomes eligible for GC. But we would fail to return it to the cache. I updated this to use try/finally. 84f3ac7
* Null-input guard at the top of Prune. * Early-out when no leaves are found (invalid JSON / shallow object graph). * Defensive bounds checks before sb.Append(snapshot, start, length) calls - Node.Start/End are char indices, but were compared against Encoding.UTF8.GetByteCount(snapshot), which can be larger than snapshot.Length for non-ASCII content. Fall back to the original snapshot if any boundary is out of range. * Replace Encoding.UTF8.GetByteCount(...) with .Length on the two char-index comparisons that were checking against the wrong unit. Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
7e388cc to
84f3ac7
Compare
Summary of changes
SnapshotPruner.Pruneso known fallback cases return the original snapshot instead of throwing.nullinput and snapshots that produce no pruneable leaves.snapshot.Length/_matchingString.Lengthfor checks that operate on char indexes.Reason for change
SnapshotPrunerworks with char indexes into the snapshot string, so checks that compare against those indexes should use string length, not UTF-8 byte length.Returning the original snapshot is preferable for known no-op fallback cases, because the caller already treats pruning failures as non-fatal and falls back to the original payload.
Implementation details
_matchingStringcomparison now uses.Lengthfor consistency with char-based parsing.Test coverage
nullsnapshot input returningnull