I am trying to explore ASP.NET Core pipeline by debugging "out-of-the-box" WeatherForecast application based the API project template.
Based on the various resources I setup the following configuration in VS:
Tools->Options->Debugging->General
- Enable .NET Framework source stepping - checked
- Enable Source Link support - checked
- Suppress JIT optimization on module load - checked
- Use Managed Compatibility Mode (tried both combinations checked/unchecked, but it does seem to affect anything)
- Enable .NET Framework source stepping - checked
Tools->Options->Debugging->Symbols
- Load all modules, unless excluded - selected
- As the location for the symbols I tried both Microsoft Symbol Servers and Symbol Server integrated into JetBrains dotPeek
- Load all modules, unless excluded - selected
Project Properties->Debug->Environment Variables
- COMPLUS_JITMinOpts = 1 [as per https://github.com/dotnet/runtime/issues/5767]. In fact I believe it is what 'Suppress JIT optimization on module load' does.
- COMPLUS_ZapDisable = 1 [to avoid the load of native images]
- COMPLUS_JITMinOpts = 1 [as per https://github.com/dotnet/runtime/issues/5767]. In fact I believe it is what 'Suppress JIT optimization on module load' does.
Project Properties->Build
- Optimize Code - unchecked
- Optimize Code - unchecked
When I start the debugger and go to Debug->Windows->Modules I can see that all of ASP.NET Core dlls have symbols loaded and Optimized column is set to 'No'. However when I hit a breakpoint in the controller and traverse through the call stack there are a lot of errors in Locals window:
'Cannot obtain value of the local variable or argument because it is not available at this instruction pointer, possibly because it has been optimized away'
I would think that the optimization wasn't turned off, but I can hit a breakpoint inside of a function in asp.net source code and observe the local variables. The problem comes into play when the execution pointer is moved to a different function. Once it is happened those local variables become unavailable.
In this thread https://github.com/aspnet/Mvc/issues/8375 someone recommends to build the debug version of the assemblies, however I cannot fully grasp why it would be necessary. My understanding that the compiler just makes IL code more clean by removing NOP instructions and the dead code blocks. The real optimization work is done by JIT and can be controlled by COMPLUS_JITMinOpts and COMPLUS_ZapDisable flags.
Is there a way to avoid these 'possibly because it has been optimized away' messages while traversing the stack? It seems I am missing some important concepts here, but I cannot figure out where to look at.
I got the same behavior in both VS2019 (core 3.1) and VS2017(core 2.2)