Ticking der Uhr: So optimieren Sie die Kompilierungszeit in Unity

Am vergangenen Freitag erschien Unity 5.3.5p7, ein kleiner Patch, der ohne Vorankündigung oder Fanfare vergangen ist. In diesem Patch befindet sich jedoch ein Stichpunkt unter den zahlreichen anderen Korrekturen, der viel mehr Aufmerksamkeit verdient.

Stimmt. Die Optimierung Ihrer Kompilierungszeit ist zurück! * Nach dem Upgrade ist meine Kompilierungszeit von ungefähr 17 Sekunden auf 6,3 Sekunden gesunken.

* (Nach Unity 5.2.4 haben die meisten Versionen einen Compiler-Fehler, der die effektivste Strategie zur Optimierung der Kompilierungszeit zunichte macht.)

Aber ich bin nicht nur hier, um zu beschreiben, wie erstaunlich es ist, jedes Mal, wenn Sie einen Code ändern, 10 Sekunden weniger zu warten. Ich bin hier, um zu fragen: Warum freuen sich nicht mehr Menschen, diesen Fehler zu beheben? Regt der Gedanke an verkürzte Kompilierzeiten nicht die Freude anderer an?

Im Bild: Zu wenig Freude.

Meine einzige Schlussfolgerung ist, dass die meisten Benutzer nicht erkennen, dass sie die Kompilierungszeit optimieren können. Es gibt keine offizielle Dokumentation und relevante Forenbeiträge sind veraltet. Daher ist es nicht einfach, den Überblick zu behalten. Aber sobald Sie das haben, ist die Reduzierung der Kompilierzeit einfach und die Vorteile sind enorm.

Hier ist meine persönliche Strategie im Kampf gegen die Kompilierungszeit:

1. Holen Sie sich die Fakten

Zuerst müssen Sie herausfinden, wie lange es dauert, bis Ihr Code kompiliert ist. Für meine eigene Ein-Personen-Codebasis bewegte sie sich um 17 Sekunden. Für größere Teams wäre eine angemessene Schätzung etwa 30 Sekunden. Um das in die richtige Perspektive zu rücken, nehme ich ungefähr 20 bis 30 Änderungen pro Stunde vor. Wenn ich 30 Sekunden anstatt 6,3 Sekunden warten muss, werden meinem Stundenplan ungefähr 10 zusätzliche Minuten Wartezeit hinzugefügt.

Stellen Sie sich vor, wie viel sich im Laufe des Tages summiert. Die ganze Woche lang. Jeden Monat. Dann multiplizieren Sie diese Zahl mit der Anzahl der Personen im Team. Und es geht nicht nur um die verschwendete Zeit: Eine längere Kompilierungszeit bedeutet, dass Sie viel häufiger abgelenkt werden und Ihre E-Mails oder Facebook-Nachrichten abrufen.

Aber zuerst müssen Sie Ihre Kompilierzeit kennen. Und Sie möchten immer den Überblick behalten, damit Sie nichts einchecken, was den Wert drastisch erhöht. Erinnerst du dich an die verschwendete Zeit? Um das zu lösen, habe ich eine Editorerweiterung geschrieben, die Sie von meinem Github hier herunterladen können.

2. Optimieren!

Bevor wir optimieren, möchte ich Ihnen einige Hintergrundinformationen dazu geben, wie dies alles funktioniert. In dem Moment, in dem Sie eine Codeänderung vornehmen, kompiliert Unity Ihren Code in eine .dll (kompilierter Code) namens Assembly-CSharp.dll (oder Assembly-UnityScript usw., wenn Sie nicht in C # schreiben).

Um den Zeitaufwand für die Neukompilierung zu verringern, können Sie spezielle Ordner verwenden, die Unity in einer separaten DLL mit dem Namen Assembly-CSharp-firstpass.dll kompiliert. Der Schlüssel ist, dass der Code in dieser DLL nicht neu kompiliert wird, wenn Sie ihn nicht ändern. Diese speziellen Ordner heißen Plugins und Standard-Assets und müssen im obersten Verzeichnis unter Assets vorhanden sein.

Dinge zu beachten:

  • Aufgrund der Reihenfolge, in der diese DLLs kompiliert werden, kann Code in dieser firstpass.dll nicht auf Code außerhalb verweisen.
  • Das Ändern des Codes in den speziellen Ordnern kompiliert beide DLLs neu und negiert alle Optimierungsgewinne.

In diesem Sinne sind die besten Kandidaten für die Optimierung Codeabschnitte, die nicht von anderem Code abhängig sind und sich wahrscheinlich nicht ändern. Vermögenswerte von Drittanbietern sind perfekt. Andere Teile Ihrer Codebasis sind möglicherweise auch für die Optimierung sinnvoll.

Es gab jedoch ein Problem beim einfachen Ziehen und Ablegen aller Assets von Drittanbietern in den Plugins-Ordner. Einige dieser Assets hängen von ihren Ressourcen ab, die sich auf ihrem ursprünglich importierten Pfad befinden, und brechen schrecklich, wenn dies nicht der Fall ist. Um mir Zeit zu sparen, kaufte ich mir Mad Compile Time Optimizer (15 US-Dollar) ***, da es die Nicht-Code-Dateien dort belässt, wo sie sind und auch eine nette Funktion zum Zurücksetzen enthält.

*** Ich bin in keiner Weise mit Mad Compile Time Optimizer verbunden.

3. Sehen Sie sich andere Verdächtige an

Nachdem Ihre Assets von Drittanbietern optimiert wurden, sollte sich die Kompilierungszeit erheblich verkürzen. Hier hören normalerweise die Leute auf, aber es gibt immer noch einige Stellen, an denen wir nach Leistungsgewinnen suchen können.

Das Attribut [InitializeOnLoad] ist eine solche Stelle. Für Unbekannte ist InitializeOnLoad ein Unity-Attribut, das jeder Klasse hinzugefügt werden kann, damit der statische Konstruktor beim Starten des Editors (oder beim Beenden der Kompilierung) aufgerufen wird. Jeder ineffiziente Code dort kann Ihre Kompilierungszeit um eine nicht unbedeutende Menge an Zeit verlängern.

Nach einigen Experimenten wurde festgestellt, dass Code, der während InitializeOnLoad ausgeführt wird, für die gesamte Kompilierungszeit berücksichtigt wird.

Um Instanzen von InitializeOnLoad zu analysieren, habe ich die vom Anfang bis zum Ende eines statischen Konstruktors benötigte Zeit mit verdächtig aussehendem Code protokolliert. Die meisten Instanzen von InitializeOnLoad waren harmlos (0.0–0.2s), aber ich bin auf eine Klasse gestoßen, die sie zum Laden und Zwischenspeichern von Ressourcen missbraucht hat. Ich habe den fehlerhaften Code geändert, um ihn bei Bedarf träge zwischenzuspeichern, und bin dann weitergegangen.

Als letztes müssen Sie Ihren eigenen Code überprüfen. Gibt es Klassen, die nicht verwendet werden? Sie brauchen wahrscheinlich keine Zeit für Ihr Projekt. Ich habe keine gute Möglichkeit gefunden, die Kompilierungszeit pro Klassendatei zu protokollieren, aber als Faustregel gilt, dass die Dateigröße ein guter Näherungswert für die Komplexität ist.

Eine Visualisierung ist der einfachste Weg, um zu priorisieren, welche Dateien einen Blick wert sind. Ich habe GrandPerspective (Mac) verwendet, da es Ergebnisse nach benutzerdefinierten Regeln filtern kann. Am Ende habe ich einen Filter erstellt, der mit Namen übereinstimmt, die mit .cs enden, und einen anderen, um Dateien mit Pfaden zu entfernen, die "Plugins" oder "Standard-Assets" enthalten.

So sah die Codebasis meines Projekts am Ende der Optimierung aus. Beachten Sie, dass mein persönlicher Code der einzige Code ist, der nach einer Änderung kompiliert wird!

Ja, das ist alles Code. Einige dieser TextMeshPro-Klassen sind sehr umfangreich.

TL; DR:

  • Spezielle Ordner sind in Unity 5.3.5p7 behoben
  • Verfolgen Sie immer Ihre Kompilierzeit (Compile Time Tracker)
  • Optimieren Sie, indem Sie Assets von Drittanbietern in Assets / Plugins oder Assets / Standard-Assets verschieben. (Ich empfehle Mad Compile Time Optimizer.)
  • Nicht missbrauchen [InitializeOnLoad]

Sind Sie daran interessiert, Ihr Spiel automatisch zu validieren, um fehlerhafte Builds zu verhindern? Oder vielleicht den Animator als Finite-State-Maschine verwenden, anstatt eine eigene Implementierung zu erstellen? Schau dir meine anderen Artikel an!