RyuJIT: The next-generation JIT compiler for .NET

RyuJIT: The next-generation JIT compiler for .NET

Rate This
  • Comments 45

This post introduces the .NET team’s new 64-bit Just-In-Time (JIT) compiler. It was written by Andrew Pardoe, PM Manager for the CLR Runtime PM team.

The world is moving to 64-bit computing even though it isn’t always faster or more efficient than 32-bit. A lot of programs run faster on 32-bit than on 64-bit, for a variety of reasons. One example of this is the 64-bit JIT compiler in .NET. It does a great job of making your program run fast, but it’s not a fast program itself. All that’s about to change: a new, next-generation x64 JIT compiler that compiles code twice as fast is ready to change your impressions of 64-bit .NET code.

Remind me again about 64-bit

It seems like the 32-bit x86 computer has been around since the dawn of time. It’s a great computer architecture, but it has one big problem: a 32-bit pointer can only address 4 GB of RAM. 64-bit computers, with their wider pointers, can address practically unlimited amounts of RAM. RAM was relatively expensive when 64-bit Windows was new so 64-bit machines were originally just used as servers. Nowadays 64-bit computing has gone mainstream and computers routinely ship with more than 4 GB of RAM. Even some smartphones have moved to 64 bit, despite the fact that they only have 1 GB of RAM installed.

The .NET 64-bit JIT was originally designed to produce very efficient code throughout the long run of a server process. This differs from the .NET x86 JIT, which was optimized to produce code quickly so that the program starts up fast. Taking time to compile efficient code made sense when 64-bit was primarily for server code. But “server code” today includes web apps that have to start fast. The 64-bit JIT currently in .NET isn’t always fast to compile your code, meaning you have to rely on other technologies such as NGen or background JIT to achieve fast program startup.

RyuJIT to the rescue!

RyuWHAT? The .NET Code Generation team has been working on a new, next-generation x64 compiler, codenamed RyuJIT. This new JIT is twice as fast, meaning apps compiled with RyuJIT start up to 30% faster (Time spent in the JIT compiler is only one component of startup time, so the app doesn’t start twice as fast just because the JIT is twice as fast.) Moreover, the new JIT still produces great code that runs efficiently throughout the long run of a server process.

This graph compares the compile time (“throughput”) ratio of JIT64 to RyuJIT on a variety of code samples. Each line shows the multiple of how much faster RyuJIT is than JIT64, so higher numbers are better.

clip_image002[1]

While all the code samples compile faster with RyuJIT, you should note the second line—RFC822 e-mail RegEx. It’s literally off the chart! That’s because regular expressions (a.k.a. RegEx) tend to perform especially badly on JIT64. Compiling this benchmark on JIT64 takes 60 seconds and consumes 1.4 GB of peak working set. With RyuJIT, it only takes 1.8 seconds and uses 199 MB of peak working set.

Paint.NET is a more normal example of RyuJIT wins. Its startup time went from 2.3 seconds on our test machine to 1.8 seconds. That indicates a compilation time decrease from 1510 ms on JIT64 to 970 ms on RyuJIT. Faster compilation with less memory usage makes everyone’s code run better.

The best is yet to come

The performance gains and working set reductions of RyuJIT are fantastic, but they’re not the best part of RyuJIT. When JIT64 was developed, we decided to base it off of the C++ team’s optimizing compiler instead of basing it off of the existing 32-bit x86 JIT which is more optimized for dynamic compilation scenarios. Most 64-bit computers were being used as servers so it made sense to emphasize compiled code quality over compiler throughput. But this left the .NET CodeGen team with two compiler codebases to maintain. Adding features (and fixing bugs!) in two places slowed down the pace of innovation. Adding the ARM architecture and MDIL for Windows Phone 8.0 in recent years made it even harder to keep up.

RyuJIT is based off of the same codebase as the x86 JIT. While it’s only for x64 right now, it’s a modern compiler that will be the basis of all our JIT compilers in the future: x86, ARM, MDIL and whatever else comes along. Having a single codebase means that .NET programs are more consistent between architectures—put another way, you generally get bug-for-bug compatibility. But having a single codebase also means we can innovate faster and bring you more code generation features more quickly.

What do I need to do to get this?

RyuJIT is available right now as a CTP that you can try out in your non-production environment. It’s not supported for production code right now but we definitely want to hear about any issues, bugs or behavioral differences that you encounter. Send feedback and questions to ryujit@microsoft.com. 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 change NGen on your system—we wanted to keep the CTP install clean. Lastly, if you enable RyuJIT while writing code, you’ll find that Edit & Continue doesn’t work on 64-bit (that’s so 2012!)

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, that is.)

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. We’ll answer questions and explain design decisions there. (If you look right now, you’ll see a post that explains the funny codename!) And remember to send us mail at ryujit@microsoft.com after you download and install the CTP. We want to hear from you!

Leave a Comment
  • Please add 6 and 6 and type the answer here:
  • Post
  • @Another Jon Harrop: I don't remember if F#-style tail-calls (IL tail-prefix calls) were supported when we cut this build. Support was either just finished, or finished a little bit afterward. I'll check tomorrow morning and post it here. I know that 'opportunistic' tail call elimination isn't in the first CTP, because we're finishing it up right now.

    Second, no, we don't have any F# benchmarks that we track, but I'd love to add something to our (very slowly growing) set of benchmarks. Do you have a recommendation?

  • Nice work! Very good to see JIT improvements in .NET.

    Do you plan to add other goodies, like SIMD support, auto vectorization, real native compiler like bartok, ...  ?

  • Awesome!

    "Most 64-bit computers were being used as servers so it made sense to emphasize compiled code quality over compiler throughput. But this left the .NET CodeGen team with two compiler codebases to maintain."

    Does this mean that runtime is now slower? As the "code quality" has gone down?

  • May I inquire as to the technical reasons for working only with Windows 8.1 or Windows Server 2012 R2? Is that because all three are not released yet? The follow-up question is, will it work with the larger install bases of Windows 7/Windows 8, Server 2008/2012? Thanks.

  • @Moondevil: We have plans for many "other goodies". As goodies get baked, and are ready for consumption, we'll begin talking about them, and tossing them up here for folks to try.

  • @Johnathan Dickinson: In it's current form, if you use it to NGen the .NET framework, performance drops a little bit. That's one of the reasons why we don't support it for NGen publicly yet. We have no intention of leaving it like that, though: we have a handful of known bugs, a few missing features, and the rest of our focus is on driving code quality beyond both JIT64 & JIT32.

  • @Jesse Slicer: We targeted our CTP at Windows 8.1/Windows Server 2012 R2 for strictly tactical reasons: from a code-generation perspective, .NET 4.5.1 that's included in Windows 8.1 is quite different from .NET 4.5.1 for Windows 7/8. In order to reduce our up-front dev & test costs, we decided to focus just on Windows 8.1.

    When we're ready, it will be part of the full .NET Runtime, fully supported on all platforms that .NET supports.

  • @Another Jon Harrop: Yes, F# tail-calls work. We don't (yet) do tail-calls unless they're explicit in the IL stream (C++ and F# are the only two languages I know of that use it)

  • Awesome!

  • This is great! I'm developing a C# psp emulator and I had some problems with JIT's performance when switched to x64. I'm heavily using JIT specially on the cpu's dynarec and vertex decoding. And I noticed that JITter had exponential times, and I didn't know why. So I had to disable optimizations for larger functions to make games playable. I was also considering to split large functions with loops into smaller functions to get it usable and in order to be able to specially get inlining instead of just disabling the optimizations entirely. Also I'm using tail calling to simulate fast jumps.

    It would be great to have some stuff like Moondevil said. SIMD/native vector types (float4 specially for my case) would be fantastic.

    I have Windows 8.1 on this machine so I'm looking forward to test it. When I have some time I will measure JIT and execution performance and will send some feedback and times to the posted address.

    Thank you very much! And keep up the good work! :)

  • "When we're ready, it will be part of the full .NET Runtime, fully supported on all platforms that .NET supports."

    Will this include the upcoming XBox One?

    visualstudio.uservoice.com/.../4233646-allow-net-games-on-xbox-one

  • Why not support Windows 8? Does RyuJIT uses a feature that is only in Win 8.1?

  • " .NET 4.5.1 that's included in Windows 8.1 is quite different from .NET 4.5.1 for Windows 7/8"

    Can you tell us more about what the differences in .NET 4.5.1 are between Win8.1 and Win8? What areas of the framework/CLR are different?

  • Will the new x64 JIT eventually outperform the existing x64 JIT? Any chance for the kind of optimization we see in C++, i.e. unrolling loops, auto-vectorization, etc.? It would be nice if an application could specify whether it prefers fast startup time and sacrifice code quality or slower startup time and better code quality. For numerical or real-time simulations I'd certainly give up a few seconds of startup time for 2x faster code.

  • A faster JIT is nice.  Having it available on Win 8.1 only makes it a non-starter for me.  Hopefully when it's production ready it'll be supported on all .NET 4 platforms.

Page 2 of 3 (45 items) 123