Using 'DotNetObjectAllocDiagnoser' prevents De-Abstraction optimizations
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
De-Abstraction in .NET 10 is awesome, but it's known to be fragile. Here is another example of its fragility:
Let's say we want to investigate the memory allocations from a benchmark by using `DotNetObjectAllocDiagnoser` (here is a blogpost that explains the usage: https://devblogs.microsoft.com/visualstudio/benchmarking-with-visual-studio-profiler/#getting-insight-into-the-benchmark):
```csharp
[MemoryDiagnoser]
[ShortRunJob]
// Using the following Diagnoser to export benchmark allocations in a profiling session.
[DotNetObjectAllocDiagnoser]
[DotNetObjectAllocJobConfiguration]
public class ForEachBenchmarkWithAllocDiagnoser
{
static List GenerateData() => Enumerable.Range(1, 1000).Select(n => n).ToList();
private IList list = GenerateData();
[Benchmark]
public int Foreach_Over_ListAsIList()
{
int result = 0;
foreach (var e in list)
{
result += e;
}
return result;
}
}
```
And here is the benchmark without the diagnoser:
```csharp
[MemoryDiagnoser]
[ShortRunJob]
public class ForEachBenchmark
{
static List GenerateData() => Enumerable.Range(1, 1000).Select(n => n).ToList();
private IList list = GenerateData();
[Benchmark]
public int Foreach_Over_ListAsIList()
{
int result = 0;
foreach (var e in list)
{
result += e;
}
return result;
}
}
```
Here are the results. The first becnhmark (with the diagnoser):
```
Job=ShortRun EnvironmentVariables=DH_CORPROFILER_START_PAUSED=1,DIAGHUB_CORPROFILER_DISABLE_OBJECTCOUNTER=1,COR_ENABLE_PROFILING=1,COR_PROFILER={B874B9B4-F0B1-4ABF-8D60-126AF315109F},COR_PROFILER_PATH_32=C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Platform\DiagnosticsHub\x86\DiagnosticsHub.CorProfiler.dll,COR_PROFILER_PATH_64=C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Platform\DiagnosticsHub\amd64\DiagnosticsHub.CorProfiler.dll,CORECLR_ENABLE_PROFILING=1,CORECLR_PROFILER={B874B9B4-F0B1-4ABF-8D60-126AF315109F},CORECLR_PROFILER_PATH_32=C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Platform\DiagnosticsHub\x86\DiagnosticsHub.CorProfiler.dll,CORECLR_PROFILER_PATH_64=C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Platform\DiagnosticsHub\amd64\DiagnosticsHub.CorProfiler.dll,CORECLR_PROFILER_PATH_ARM=C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Platform\DiagnosticsHub\arm\DiagnosticsHub.CorProfiler.dll,CORECLR_PROFILER_PATH_ARM64=C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Platform\DiagnosticsHub\arm64\DiagnosticsHub.CorProfiler.dll,COMPlus_ReadyToRun=0,COMPlus_ZapDisable=1,CORPROFILER_SAMPLE_RATE=1,DOTNET_RichDebugInfo=1,COMPlus_TieredCompilation=0 IterationCount=3
LaunchCount=1 WarmupCount=3
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|------------------------- |---------:|---------:|----------:|-------:|----------:|
| Foreach_Over_ListAsIList | 5.483 us | 1.438 us | 0.0788 us | 0.0076 | 40 B |
```
The second results without the diagnoser:
```
| Method | Mean | Error | StdDev | Allocated |
|------------------------- |---------:|---------:|---------:|----------:|
| Foreach_Over_ListAsIList | 485.9 ns | 214.0 ns | 11.73 ns | - |
```
So we have an observer effect here: when we try to collect more infromation about the runtime behavior, the behavior itself changes. In this case it might not be a big deal, but in some other cases, when we analyze the delegate de-allocation it might be very hard to understand what are the allocations.
My guess is that some of the flags used by the diagnoser (like `COR_ENABLE_PROFILING`) are affecting the JIT's behavior.
### Reproduction Steps
See the examples above.
### Expected behavior
The optimizations should work when the diagnoser is enabled.
### Actual behavior
The JIT stops de-abstracting the code when the diagnoser is used.
### Regression?
No. This is a new functionality.
### Known Workarounds
_No response_
### Configuration
_No response_
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.