[Debugger] DEBUG-4260 Add capture expression to log probe#8621
Conversation
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8621) 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 (8621) - mean (73ms) : 70, 75
master - mean (73ms) : 68, 77
section Bailout
This PR (8621) - mean (76ms) : 74, 78
master - mean (77ms) : 74, 80
section CallTarget+Inlining+NGEN
This PR (8621) - mean (1,113ms) : 1054, 1172
master - mean (1,106ms) : 1059, 1153
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 (8621) - mean (114ms) : 110, 117
master - mean (113ms) : 109, 116
section Bailout
This PR (8621) - mean (114ms) : 111, 117
master - mean (118ms) : 110, 126
section CallTarget+Inlining+NGEN
This PR (8621) - mean (793ms) : 760, 825
master - mean (785ms) : 758, 812
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8621) - mean (100ms) : 97, 104
master - mean (104ms) : 98, 110
section Bailout
This PR (8621) - mean (101ms) : 98, 103
master - mean (103ms) : 99, 107
section CallTarget+Inlining+NGEN
This PR (8621) - mean (946ms) : 900, 992
master - mean (944ms) : 901, 987
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8621) - mean (103ms) : 97, 109
master - mean (99ms) : 96, 102
section Bailout
This PR (8621) - mean (101ms) : 98, 103
master - mean (104ms) : 98, 110
section CallTarget+Inlining+NGEN
This PR (8621) - mean (823ms) : 787, 859
master - mean (821ms) : 786, 856
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 (8621) - mean (199ms) : 194, 204
master - mean (199ms) : 192, 205
section Bailout
This PR (8621) - mean (203ms) : 198, 209
master - mean (203ms) : 198, 207
section CallTarget+Inlining+NGEN
This PR (8621) - mean (1,200ms) : 1159, 1240
master - mean (1,199ms) : 1157, 1241
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 (8621) - mean (286ms) : 277, 296
master - mean (289ms) : 282, 296
section Bailout
This PR (8621) - mean (287ms) : 279, 296
master - mean (289ms) : 282, 296
section CallTarget+Inlining+NGEN
This PR (8621) - mean (959ms) : 935, 984
master - mean (964ms) : 940, 988
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8621) - mean (278ms) : 270, 286
master - mean (280ms) : 273, 288
section Bailout
This PR (8621) - mean (279ms) : 273, 285
master - mean (281ms) : 276, 286
section CallTarget+Inlining+NGEN
This PR (8621) - mean (1,155ms) : 1119, 1190
master - mean (1,156ms) : 1120, 1193
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8621) - mean (276ms) : 266, 287
master - mean (279ms) : 273, 285
section Bailout
This PR (8621) - mean (278ms) : 272, 284
master - mean (279ms) : 271, 286
section CallTarget+Inlining+NGEN
This PR (8621) - mean (1,042ms) : 999, 1086
master - mean (1,039ms) : 1003, 1076
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
e03064f to
1e4d76d
Compare
BenchmarksBenchmark execution time: 2026-05-15 14:15:27 Comparing candidate commit e0164db 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 47 metrics, 19 unstable metrics, 85 known flaky benchmarks, 41 flaky benchmarks without significant changes.
|
andrewlock
left a comment
There was a problem hiding this comment.
I haven't reviewed the debugger side really, not sure it needs an APM review!
|
|
||
| public CompiledExpression<object>[]? GetOrCompileCaptureExpressions(ProbeExpressionEvaluator evaluator, MethodScopeMembers scopeMembers) | ||
| { | ||
| if (Volatile.Read(ref _captureExpressionsCompiledInitialized) == 1) |
There was a problem hiding this comment.
I would mark the field _captureExpressionsCompiledInitialized as volatile. This could avoid forgetting to use Volatile.Read if used at other places
There was a problem hiding this comment.
I would have to do that for others as well, maybe in a follow-up pr
for example:
if (Volatile.Read(ref _compiledInitialized) == 1)
{
return _compiled;
}
| // The instance is not published until after construction, so a plain assignment is sufficient here. | ||
| _state = ProbeProcessorState.Create(probe); |
There was a problem hiding this comment.
Feels wrong to me. I would declare the field volatile here.
Even if the instance is published after the creation there is no guarantee that the other thread reading through the call to TryBeginProcess.
Do you have strong guarantee that after execution of the constructor all your fields are written and "flushed" via memory barrier? because otherwise this is what can happen with instruction reordering:
| T1 | T2 |
|---|---|
| create ProbeProcessor | - |
| published instance | if (instance != null) |
| - | call to TryBeginProcess() |
| call to constructor and store into _state |
in Java we have this guarantee with final fields ( equivalent of readonly field)
There was a problem hiding this comment.
to be clearer, your code would work on x86 because the writes cannot be reordered on this arch, but not true for ARM and requires a hardware memory barrier.
There was a problem hiding this comment.
You’re right, I improved the comment.
There was a problem hiding this comment.
Even with this comment I found that fragile: The day you change the way your ProbeProcessor is created then you have the publication issue.
I would avoid to rely on external (outside of the class) memory barrier here
There was a problem hiding this comment.
Personally, I think it was ok, but I trust your judgment. Fixed. e0164db
1e4d76d to
c051c9a
Compare
c051c9a to
fcda9a0
Compare
Summary of changes
Reason for change
ProbeProcessorand debugger invocation changes across multiple PRs, which would likely create conflict-heavy follow-up work.Implementation details
UndefinedValueis used as a sentinel for expressions that do not produce a capturable value, sonullcan remain a valid captured value.ProbeProcessorStateinstead of mutating evaluator inputs, expression fields, capture-expression state, andProbeInfoin place.Test coverage
ProbeProcessorTests|DebuggerExpressionLanguageTests|Debugger.DebuggerSnapshotCreatorTests|ProbeConfigurationComparerTests|ProbeConfigurationFileLoaderTestsIntegrationTests.ProbesTests.CaptureExpressionProbeTest