Deprecation Note:
_____________________________________________________________
Unity Incremental Compiler
One solution we are working on to get us closer to our 500ms goal is a new compilation pipeline, which includes a new C# incremental compiler. Built using Microsoft’s Roslyn open source compiler project, our new C# compiler is designed to dramatically accelerate iterating on your C# code as well as giving you access to the latest and greatest C# 7.2 features.
Building our own compiler has several advantages. First, our compiler can cache all kinds of data from one compilation to the next, which means that code and references that didn’t change won’t get reparsed or reloaded (hence the name “incremental compiler”). Second, even though this compiler could be used to compile any dotNET code, it was written with a-priori knowledge about compiling Unity projects, which means we can do things (or skip things) other compilers cannot.
Some Preliminary Numbers
In the image above, you can see the effect the compiler cache has over the compilation time. Notice that the time to compile the first assembly is the same between the built-in Unity compiler and the incremental compiler (about 1.8 seconds). This is because being the first assembly we compile, no caching can occur. Subsequent compilations however benefit tremendously from caching.
As you can see, the most interesting performance gains are achieved on subsequent “incremental” compilations, when iterating back and forth between code and Unity (when it typically hurts the most). The image above shows the effect of changing one file in an assembly which is referenced by many others. The assembly in question (Unity.Mathematics) is rebuilt, then all assemblies dependant on it are quickly re-emitted.
That graph shows a couple of important things. First, it shows that the compiler is optimized for iterative changes where just a few files are changed at a time. Second, it shows that to squeeze the most performance out of the compiler, it is crucial to modularize your code using asmdef files. The compiler heavily relies on analyzing dependencies between assembly to recompile only the bare minimum. Chugging all your code in one big Assembly-CSharp.dll will only result in modest performance gains.
Some disclaimer on the numbers
The numbers you see are numbers we were able to measure in our lab and are subject to change quite a bit, as we add features and make additional changes. Also, the numbers you see are in milliseconds, but adding those numbers together does not equal the total time for recompilation and domain reloading (the time “felt” by the user). This is because even with the built-in compiler, some of these compilations occur in parallel. Furthermore, the new compiler does not impact the time it takes to do a “domain reload” (or enter-playmode).
Other Cool Stuff
Other cool stuff we get from writing our own compiler is support for C# 7.2, which gives you nifty ref returns, readonly and ref structs. We are also giving you the ability to write your own language rules and custom error messages. This is useful if you want to enforce coding conventions or generate compilation errors when, say, GetComponent<> is used in an Update method, or inside a for-loop, etc.
Can I Help?
If you’d like to give this new compiler a try, we are making the early alpha available today. See below for installation instructions. It is still early days for this technology and you might find problems - we’d love to get your feedback, good and bad
Installation Instructions
The incremental compiler comes as a package you can include in your project via the Package Manager manifest.
1- Download and install Unity 2018.1 BETA 12
The compiler might work with earlier 2018 Beta versions of Unity, but you will not be able to debug your code without B12.
2- Add this to your manifest file
{
"dependencies": {
"com.unity.incrementalcompiler": "0.0.30"
},
"registry": "https://staging-packages.unity.com"
}
3- Set your scripting runtime to version 4.x in project’s player settings
The compiler client loaded by Unity needs this.
4- Delete your project’s Library/ScriptAssemblies folder
This will remove the last assemblies compiled built by the built-in compiler and will ensure the new compiler starts with a fresh, full recompilation.
5- Configure the Compiler from the Preference window
A new “Compiler” section is added to the Unity Preference window. You can control some compiler settings from there.
Feedback
And we’d love to hear what you think!
Please feel free to post your questions and comments here.