A first hand look from the .NET engineering teams
This post announces an updated preview of the .NET team’s new 64-bit Just-In-Time (JIT) compiler. It was written by Mani Ramaswamy, Program Manager for the .NET Dynamic Code Execution Team.
Note: RyuJIT CTP3 is available here: http://blogs.msdn.com/b/dotnet/archive/2014/04/03/the-next-generation-of-net.aspx.
The developer preview of RyuJIT, CTP1, received a thunderous response (so much so we had to post a FAQ soon after). Two questions commonly asked were when would there be an update and when would it support feature X or Y that is in the existing 64-bit .NET JIT compiler. CTP2 answers both questions. This release of RyuJIT has equivalent functionality of existing JIT64: there aren’t any feature differences between RyuJIT and the existing JIT64 at this point. RyuJIT generates code that’s on average better than the existing JIT64, while it continues to maintain the 2X throughput wins over JIT64.
The two main features which weren’t supported in CTP1 were “opportunistic” tail calls and Edit & Continue. With CTP2, both of these features are supported. Additionally, a host of other features have been added to achieve functional parity with JIT64. Along the way, we’ve (the .NET Code Generation team) also added a number of performance tweaks and optimizations so that code generated using RyuJIT is generated fast (the throughput metric) and runs fast (the code quality metric).
But why stop there? We have thrown every test at our disposal at RyuJIT and it has come out with flying colors – whether it be running common server software using IKVM.NET (a Java Virtual Machine implemented in .NET), or complex ASP.NET workloads, or even simple Windows Store apps. Thanks to everyone who tried out the first CTP of RyuJIT and filed bug reports – we’ve fixed every single one of them, and at this point, RyuJIT doesn’t have any known bugs.
We continue to look at ways to improve the overall quality of RyuJIT, and will likely discover a few more bugs along the way. From the enthusiastic response we got from the first CTP, we’ll surely hear back with a few more bugs from our early adopters, i.e. you.
When it comes to performance, CTP1 demonstrated that RyuJIT handily beats JIT64 on throughput (how fast the compiler generates code) by a factor of 2X. We’ve been careful to maintain our throughput wins, and this CTP should yield similar throughput numbers. With CTP1, the focus was on throughput and to get some early feedback, and not so much on code quality (how fast the generated code executes).
While with CTP1, we were in the same ball park as JIT64, we were still 10-20% slower on code quality, with some outliers. With CTP2, we’ve addressed that – at this point, on average we should be at par or beating JIT64 on code quality. If during your evaluation, you find a benchmark where RyuJIT is trailing JIT64 performance significantly, please reach out to us – by the time we’re done, RyuJIT should be producing code that’s better than what JIT64 produced. This is not to say that there couldn’t be a few micro-benchmarks where JIT64 produces more optimal code, but rather to say that on average RyuJIT should be on par or better, and in the few (rare) cases it does trail JIT64 performance, it trails by only a few percentage points. We tried out many common code quality benchmark suites internally, and found that RyuJIT code quality on average is better than the existing .NET JIT64 compiler – thus if you do find an outlier, we’re most interested.
The chart below shows our performance, relative to JIT64’s across a number of benchmarks, some very small, others fairly large. Positive numbers indicate RyuJIT performing better than JIT64. Negative numbers indicate the opposite. The gray section is the limit of “statistical noise” for each benchmark, so any bar that is within the gray area indicates effectively identical performance. Check the CodeGen blog within a day or two for a detailed description of the methodology and specifics about the benchmarks we’re running. Overall, we’re doing quite well, with only a handful of losses, and some very nice wins!
While we needed to first get all the functionality and quality metrics lined up and achieve parity on performance (code quality) with JIT64 (we’re already 2X faster on throughput, in case you forgot), our re-architecture puts us in a great place for optimizing .NET dynamic code execution scenarios. Over the next few months, you will continue to hear from us as we move forward on quality and performance.
The process to install RyuJIT remains simple and is the same as that for CTP1. While it’s not for production code yet, we look forward to hearing from you on functionality, quality and performance. Send feedback and questions to firstname.lastname@example.org. Even if you’ve figured out the issue or a workaround yourself we want to hear from you.
You can download the RyuJIT installer now. RyuJIT only works on 64-bit editions of Windows 8.1 or Windows Server 2012 R2. Also, RyuJIT doesn’t impact NGen to keep your system isolated.
After installation, there are two ways to turn on RyuJIT. If you just want to enable RyuJIT for one application, set an environment variable: COMPLUS_AltJit=*. If you want to enable RyuJIT for your entire machine, set the registry key HKLM\SOFTWARE\Microsoft\.NETFramework\AltJit to the string "*". Both methods cause the 64-bit CLR to use RyuJIT instead of JIT64. And both are temporary settings—installing RyuJIT doesn’t make any permanent changes to your machine (aside from installing the RyuJIT files in a directory)
Stay tuned to this blog for more on RyuJIT as it progresses from a CTP to become the One True .NET JIT Compiler. If you want to dive more deeply into the geeky details behind RyuJIT’s development, you can do that at the .NET CodeGen blog. For example, here's more detail on performance numbers. We’ll answer questions and explain design decisions there. And remember to send us mail at email@example.com after you download and install the CTP. We want to hear from you!
@LKeene: To enable RyuJIT on the entire machine (we don't recommend that you do this if you have any business impact managed applications in the machine):
1) Install RyuJIT CTP2 in the machine
2) Open an elevated command prompt Window (windows key->q, type cmd on the search text box, right click on "Command Prompt" and select "Run as administrator")
3) Turn on the registry Key to enable RyuJIT in the entire machine from the command prompt as follows (reg add HKLM\Software\Microsoft\.NETFramework /reg:64 /v AltJit /t REG_SZ /d * /f)
4) After evaluating managed applications running under RyuJIT, you can turn it off from the registry setting as follows (reg delete HKLM\Software\Microsoft\.NETFramework /reg:64 /v AltJit /f)
Kevin Frei has uploaded a script that does this for you at kscdg.codeplex.com/.../latest
Download the script and from your elevated command prompt run "protojit on" to turn on the registry setting, "protojit off" to turn it off, "protojit" to see if its currently turned off or not, "protojit proc" to see the processes that have protojit.dll currently loaded.
If you want to use a debugger, WinDBG, to break when RyuJIT gets loaded for a managed app that can be run from the commandline,
1) Install WinDBG from msdn.microsoft.com/.../ff551063(v=vs.85).aspx
2) Enable RyuJIT using one of the options above
3) Run the application from the command prompt using the debugger (ex. c:\Debuggers\windbg.exe test.exe)
4) On the windbg command window, type "sxe ld:protojit" and enter
5) On the windbg command window, type "g" and enter and you should see a break when protojit.dll gets loaded to compile a method
Kevin's script will allow you to see this much easily with "protojit proc"
Hope this helps.
Final note: If you want details about the benchmarks, check out the codegen blog: blogs.msdn.com/.../lies-damn-lies-and-benchmarks.aspx
When trying to run our application with RyuJIT I get stack overflow crashes, but only in Release builds without the debugger attached (i.e. release mode JIT). It is a big mixed native/managed app. Any ideas on how to debug this?
This is what I get from the debugger:
Unhandled exception at 0x00007FF9420B5684 (clr.dll) in MyApp.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
000000A6AA04D420 00007FF8E4FE3396 mscorlib!System.Security.CodeAccessSecurityEngine.Assert(System.Security.CodeAccessPermission, System.Threading.StackCrawlMark ByRef)+0x46
000000A6AA04D460 00007FF8E4FE3333 mscorlib!System.Security.CodeAccessPermission.Assert()+0x23
000000A6AA04D4A0 00007FF8E5CE9CAF Infragistics4_Win_UltraWinDock_v13_1!Infragistics.Win.UltraWinDock.Utilities.GetParent(System.Windows.Forms.Control)+0x6f
Child-SP RetAddr Call Site
000000a6`aa04b910 00007ff9`448835de clr!_report_gsfailure+0x1c
000000a6`aa04b950 00007ff9`4455994c clr!StackFrameIterator::NextRaw+0xdb7
000000a6`aa04ba90 00007ff9`4455967e clr!Thread::StackWalkFramesEx+0x174
000000a6`aa04be60 00007ff9`4462cb73 clr!Thread::StackWalkFrames+0xbe
000000a6`aa04cf70 00007ff8`e4fe3396 clr!SecurityStackWalk::CheckNReturnSO+0x293
000000a6`aa04d420 00007ff8`e4fe3333 0x00007ff8`e4fe3396
@Ståle L. Hansen:
It looks like there's some stack corruption going on, which makes it particularly nasty to debug. I'd give even odds that it's a problem with your code, or a problem with RyuJIT. We lay out the stack quite a bit differently than JIT64 did, so you may have had minor stack corruption occurring, but the contents of the stack that were getting overwritten were no longer used. The first step to tracking the issue down is to try to get the debugger attached. From inside Visual Studio, you can turn on 'retail' debugging by unchecking the "Suppress JIT optimization on module load (Managed only)" box in the Tools=>Options=>Debugging dialog. Once you're there, make sure you can reproduce the issue. Feel free to hit me up directly. My e-mail address is firstname.lastname (@microsoft.com).
Will RyuJIT support plugins for code generation in the llvm sense? //llvm.org/docs/Passes.html
I have sent a bug report to 'firstname.lastname@example.org' but I have got no answer back. Is the mail box still in use?
Is it possible to open source this like the rest of the related products which were open sourced.
Will there be plans to expand support to Windows 7?