The [.NET Framework 4.6](http://blogs.msdn.com/b/dotnet/archive/2015/07/20/announcing-net-framework-4-6.aspx#net-framework-46) includes a new Just-In-Time (JIT) compiler for 64-bit processes, called RyuJIT. It is enabled by default. Note that the 32-bit JIT in .NET Framework 4.6 is not significantly changed from previous releases. This document does not describe troubleshooting problems with the 32-bit JIT.
This document provides instructions to disable RyuJIT or one of its optimizations. This is useful if you experience unexpected product behavior after installing .NET Framework 4.6 and want to determine if RyuJIT is the cause of that behavioral change.
If you find a problem that appears to be a bug with the .NET JIT compiler, we want to know about it! Please report the bug here: https://connect.microsoft.com/VisualStudio.
**Note** The registry methods below use either `HKEY_LOCAL_MACHINE` or `HKEY_CURRENT_USER`. Using `HKEY_LOCAL_MACHINE` makes the setting applicable to the entire machine and all users. Using `HKEY_CURRENT_USER` makes the setting applicable to just the current user. If using the registry methods, the latter is generally preferable.
In general, you should choose the least impactful option. Choose a per-application setting if possible, and only move to a per-user or per-machine setting if necessary. Note that per-application settings are not available for ASP.NET applications.
If you encounter a bug when you use the new JIT, and if the bug manifests itself in a function in an NGEN native image (see [here](https://msdn.microsoft.com/en-us/library/6t9t5wcf(v=vs.110).aspx) for details), use any of the following methods to force certain named assemblies to be recompiled by the JIT and not use the existing native images. You will generally pair one of these methods with the same numbered method above to get an NGEN image to fall back to JIT compilation, and, in addition, do that JIT compilation with the legacy JIT.
In the examples below, we wish to prevent using the NGEN images of three assemblies, named `assembly_one.dll`, `assembly_two.dll`, and `assembly_three.dll`. We specify the assemblies using simple assembly names (no public key token, no architecture, and so on). The assembly names are specified without using the `.dll` file name extension.
To prevent any NGEN native image from being used, and force all code to be compiled with the JIT compiler, you can use the ZapDisable configuration variable, as follows. You might choose to do this as an experiment, to see if any NGEN native image contains generated code that is inducing a bug in your application. Generally, if an NGEN native image does have a problem, and the identity of that native image can be determined, using one of the `DisableNativeImageLoadList` mechanisms described above is preferable.
**Note** This setting applies to both the 32-bit and 64-bit JIT. Thus, setting this globally will affect all 32-bit .NET applications as well. This is particularly true for **Method 2: environment variable**.
**Note 2** NGEN provides significant performance improvements to .NET applications. Disabling the use of NGEN may result in significantly slower application startup times.
**Note** Windows has both 32-bit and 64-bit registry sections. The addresses shown above use the 64-bit registry path, so are appropriate for troubleshooting RyuJIT and not affecting 32-bit .NET applications. On a 64-bit machine, the 32-bit registry path for the `HKEY_LOCAL_MACHINE` case is `HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework`.
"Tail call" is a code pattern that the JIT compiler can sometimes optimize to improve code performance. You can see some discussion about JIT and tail call [here](http://blogs.msdn.com/b/clrcodegeneration/archive/2010/05/07/jit-etw-tail-call-event-fail-reasons.aspx). You can disable tail call optimization in RyuJIT with the following instructions.
**Note** This will disable tail call optimization of a function when the JIT is invoked to compile it. Note that if your application is NGEN compiled, the JIT is not invoked after the NGEN compilation has completed. To affect the code compiled for NGEN, you must first remove your application from the NGEN native image cache using `ngen uninstall MyApp`. Then, set the registry key shown here. Finally, optionally, you can re-NGEN your app using `ngen install MyApp.exe`.
If you determine that the JIT is incorrectly optimizing a particular function, you can selectively disable JIT optimization for that function by annotating that function with `MethodImplOptions.NoOptimization`. For example, in C#:
This is only effective in solving a code generation problem if the incorrect code being generated by the JIT is due to optimization, as opposed to being due to unoptimized code generation.
**Note** This method applies to all .NET JIT compilers.
Disabling optimization of all functions
=======================================
While troubleshooting, it might be useful to determine if *any* JIT optimization is causing problems. Instead of using the above `MethodImplAttribute` method above, you can set a single environment variable to disable all JIT optimization. Set this variable:
Note that when you run your application under the Visual Studio debugger, it might disable JIT optimization to improve the debugging experience. In Visual Studio 2013 and before, JIT optimization is disabled by default. In Visual Studio 2015, it is not disabled by default. The option in Visual Studio is called "Suppress JIT optimization on module load". You can read about that [here](https://msdn.microsoft.com/en-us/library/ms241594.aspx). Note that the MSDN documentation is incorrect about the Visual Studio 2015 default.
Before .NET Framework 4.6 was released with RyuJIT as the default .NET JIT for the x64 architecture, RyuJIT was shipped several times as a CTP ("Community Technology Preview") release. For example, see the RyuJIT CTP5 release announcement [here](http://blogs.msdn.com/b/clrcodegeneration/archive/2014/10/31/ryujit-ctp5-getting-closer-to-shipping-and-with-better-simd-support.aspx).
If you previously installed a RyuJIT CTP, you must remove any manually created configuration related to using the RyuJIT CTP, before upgrading to .NET Framework 4.6. If you don't, all managed applications will immediately crash on startup.
To fix this issue, delete the following registry value (if it exists):
Secondly, ensure that the following environment variable is not set:
COMPLUS_AltJit
## More information
In order to enable the JIT shipped with a RyuJIT CTP, you had to manually create the registry value or set the environment variable that is indicated above. If this registry value or environment variable exists after you install .NET Framework 4.6, the system looks for a CTP version of the JIT compiler instead of the newly installed version. Because the RyuJIT CTP releases are incompatible with .NET Framework 4.6, this causes managed applications to crash.
Note that the .NET Framework 4.6 installer does not change or delete these manually created configuration settings. Similarly, uninstalling the RyuJIT CTP also does not change these configuration settings.