Putting all my external code into an asmdef reduce my compile time by 75%

“30 second build times!” I told my cats. “What’s going on here.” Thus began my week long adventure to speed up my build times.

I’m not sure why Unity was taking 30 seconds then. Under test conditions my build took more like 8 seconds. In the end, I got it down to around 5 seconds. Was this worth it?

“I have a need for speed”

For normal C# projects, we can call MSBuild directly a get a Performance Summary for a build. Unfortunately, it seems Unity doesn’t use MSBuild (or at least I can’t figure out how to get Unity to output a MSBuild Performance Summary.) So instead, I scraped Unity editor logs to figure out what Unity does.

What Unity Does

Step one, Unity does a refresh. The Unity refresh looks for all the files that have changed, and makes a list of the projects that depend on those files. Most build systems keep track of time stamps and rebuild if the change time of the file is different. Unity being different, reads the entirety of every file that has changed to compute a hash. Unity will only build the file if the new hash is different. Even so, for a single file, this is really fast.

Step two, Unity does a compile. The Unity compile step calls the C# compiler to build the projects the Unity refresh determined need to be compiled. This is the step Asmdef files should help with. Everything not included in a folder covered by an asmdef file is built into the Assembly-CSharp or Assembly-CSharp.Editor assemblies. The docs say that they reference all asmdef files, but it practice it seems that only asmdef files with the "Auto Referenced" checkbox marked.

Step three, Unity does an update. The Unity update step puts the game and everything all back together again. Lots of stuff happens here, but Asmdef files shouldn’t impact this step too much.

Asmdef files to the rescue

Asmdef files allow us to break up our game up into smaller assemblies. We then manually configure the dependencies between the assemblies. How we do this will impact our compile times.

If we make our dependencies the code that doesn’t change much, this should speed up incremental builds.

Assembly-CSharp automatically takes dependencies on everything. Replacing this with our own asmdef with explicit dependencies might speed up incremental builds.

Spliting up independent code should speed up incremental builds as well.

Phase 0: Benchmark no asmdef files

We need a benchmark to compare to. This build has no asmdefs.

Phase 1: Put Unity asset store stuff into one asmdef