Background-info: the different types of optimizations in .NET
In many compiled languages, like C and C++, often there's only really just one place where optimizations are applied: when you run your compiler (though it's also common for older toolchains, with separate compilers and linkers, to have separate compile-time and link-time optimizations).
...but in the .NET world it's slightly more complicated:
The csc
C#-to-IL (or VB.NET-to-IL, F#, etc) compiler can optimize the IL that's generated from your C# (the /optimize
flag).
- These tend to be simpler optimizations, such as removing dead code (e.g. the contents of a block like
if( false ) { /* here */ }
).
When a built .NET assembly (.NET .dll
or .exe
) is loaded by the CLR then the JIT can apply its own optimizations.
- These tend to be more advanced, such as loop-unrolling and executable code-inlining.
- These JIT-time optimizations are not applied to assemblies with
DebuggableAttribute( DebuggingModes.DisableOptimizations )
or with isJITOptimizerDisabled: false
- this attribute is added to assemblies when using csc.exe
with /debug
.
While strictly-speaking not a compiler "optimization", when a .NET program runs the CLR may load cached native-image versions of managed assemblies, which are specific to your machine.
- For .NET Framework 1.x-4.x assemblies, these native images are generated by
ngen.exe
- which (since Windows 8) may preemptively compile assemblies in the background without needing to run ngen.exe
manually.
- For .NET 5+, see
CrossGen2
.
- This is not the same thing as
readytorun
and/or AOT-compiled assemblies, which have their own optimizations and is out-of-scope for this answer.
Recommended Reading
What settings does "Disable managed optimizations and restart debugging" actually change in Visual Studio?
The message-box lets you change the "Suppress JIT optimization on module load (Managed only)" setting under Tools > Options > Debugging:

However I'm now worried that I've disabled some optimizations which may slow things down
Worry not: the "Suppress JIT optimization..." setting only prevents JIT optimizations for non-project assemblies when debugging - though in many cases ngen'd images will still be used (thus still running optimized cod unless you use COMPlus_ZapDisable
).
What settings does that change in Visual Studio and how can I re-enable the managed optimizations?
Go to Debugger settings and uncheck the "Suppress JIT optimizations..." option.
You can see what's going on if you use the Debugger Modules window to see each .NET assembly that's loaded, along with its JIT optimization status, symbols status, and if VS considers it "user code" or not.

