Ladezeiten einst und jetzt

Wenn ich mich dazu entscheide zwei Sprachen in einem Programm zu verwenden dann meist weil ich meinen Kern in einer kompilierten Hochsprache (wie z.B. C++, Java oder C#) schreibe… und Scriptanteile die zur Laufzeit neu geladen und interpretiert werden können in einer anderen Sprache belasse, die ggf. auch interpretiert werden kann. Da kommen dann oft Sprachen wie Lua, Ruby oder - Gott bewahre - JavaScript ins Spiel. Warum macht man das? Weil man flexible Änderungen ermöglichen will die nicht immer zur Neukompilation (quasi Neuerstellung der Programms) führen sollen und natürlich auch für Mods.

Für dynamischen Anteil außerhalb des Programmkerns muss man keine Scriptsprache nehmen. Es gibt durchaus die Möglichkeiten bei C+ Sourcen Just In Time (JIT) zu kompilieren. Interpretierte Skripte haben dadurch, dass sie live im Spiel gelesen und interpretiert werden natürlich den Nachteil, dass sie langsamer sind, weil sie erst von einem Interpreter in Befehle umgesetzt werden müssen, während C++ Programme logischerweise schon in Maschinensprache vorliegen (C# und Java Programme werden in ein Zwischenformat kompiliert welches dann von den entsprechenden Runtimes übersetzt wird… ist definitiv schneller als direktes Interpretieren).

Was Argumentationen wie das Verteilen von Objekten durch den Speicher angeht… ja… das ist ein bisschen auf der Detailebene. Wenn man quer durch den RAM muss kostet das Zeit… aber nicht so viel wie beschissene Laufzeiten oder eine fragmentierte HDD. Generell ist die Logik, dass im Speicher nebeneinanderliegende Objekte schneller zugreifbar sind als durch Adresssprünge voneinander gentrennte. Menschen wie ich ärgern Informatikstudenten immer mit der Frage warum eine Liste auf Array-Basis besser ist als eine durch den Speicher verkettete Liste - im Grunde weil bei der ArrayList alle Items nebeneinander im Speicher liegen obwohl bestimmte Operationen von der Laufzeit in der verketteten Liste schneller sind. Das sollte man aber nicht generell auf alles anwenden :slight_smile: Man bewegt sich hier im Detailbereich.

Warum das Lesen von Spielständen so lange dauert hängt glaube ich gar nicht so sehr mit dem Spielstand zusammen, sondern mit den Daten und der Umgebung, die aus dem Spielstand abgeleitet werden. Das Spiel suggeriert dir, dass es nur einen Spielstand lädt… du weißt aber nicht wie das Laden eines Spielstandes mit dem Speicher umgeht. Sagen wir z.B. bei einer komplett geladenen 3d Umgebung mit allen aktuellen Objekten lädst du einen Spielstand mit einem vollständig anderen Status. Um das sauber zu machen wummst man alle Daten aus dem Speicher und baut die Spielumgebung komplett neu auf - also quasi das was sonst passiert während du 2-3 Schritte durch die Umgebung machst. Die Daten, die sich in einem Spielstand befinden sind ja im erster Linie eine Ableitung des aktuellen Spielzustandes und grade dann wenn wir über 3d Spiele reden wo mal eben ein paar 100 KIs in deiner Umgebung mit einem Zustand gesichert sind, der mal eben widerhergestellt werden muss, kommen wir in ein komplexes Muster wo das komplette Spiel ggf. entladen werden muss.

Auch hier: denkt PARETO… 80% der Umsetzung sind mit 20% Aufwand / Komplexität zu machen… das was fehlt ist dann der harte Scheiß. Wenn Vorausgesetzt wird, dass das Spiel nach dem Laden nahtlos fortgesetzt wird, muss da bei heutigen Games schon einiges passieren. Dazu kommt, dass man natürlich die Engine befüttern muss.

Ich finde es eigentlich fast schon dreist Engines als Bloatware zu bezeichnen. Meiner Meinung nach steckt da eigentlich die hohe Programmierkunst drin. Ohne Engines hätten wir bei Weitem nicht die Masse an Spielen. Klar gibts auch Menschen wie Jeff Vogel die seit 30 Jahren Indy-RPGs im Solo-Modus raushauen. Aber für die großen Produktionen von denen hier gesprochen wird gehts eben nicht ohne koordiniertes Teamwork. Da liegt der Anspruch sehr stark im Organisatorischem.

Anmerkung: Vieles sind „Vermutungen“ - ich arbeite nicht im Spielebereich. Ich bin leitender Softwarearchitekt für Business Applikationen. Da es sich hier um Programmierung handelt kann ich aber ein paar Parallelen ableiten. Menschen aus der jeweiligen Branche können mich gerne korrigieren :wink:

6 „Gefällt mir“

Das wollte ich nicht suggerieren. Ich wollte eher sagen, dass diese fertigen Engines Bloat haben, nicht dass sie komplette Bloatware sind. Zum Beispiel hatte Unreal Engine lange Zeit Probleme mit Texture Pop-In, also dem Nachladen von Texturen, und Ladezeiten allgemein. Man kann glaube ich aus solchen Gründen kein Open World Spiel in UE 4 schreiben, außer man macht immer so Grenzen, wo geladen wird, wenn man sie überschreitet. :slight_smile:

Dagegen sind die Engines von ID Software spezieller und haben weniger Bloat, finde ich. Dadurch sind sie auch performanter als sowas wie UE. Ich denke zum Beispiel an Rage damals. Bloat ist für mich, wenn man versucht, die eierlegende Wollmilchsau zu programmieren, die alles kann, und das Ding wird immer grösser und dadurch langsamer. ID Software kann Ihre Engines dagegen auf den ganz bestimmten Spieltyp, Egoshooter, optimieren.

Es stimmt wie Du sagst, ohne Engine ist ein modernes großes Spiel kaum machbar. Jonathan Blow hat für Witness damals seine eigene, speziell für dieses Spiel optimierte, Engine geschrieben. Das war allerdings „nur“ ein Indietitel, und das hat Jahre gedauert. Das Spiel ist dadurch jetzt nicht gerade besonders performant. Dafür hat es aber interessante Licht- und Schatteneffekte und Weitsicht von Objekten in der Welt, die auch für Rätsel benutzt werden, und daher auf ganz bestimmte Art funktionieren mussten. :slight_smile:

Ums nochmal zu sagen, ich glaube auch nicht, dass das hauptsächlich an vermeintlich langsamen Script-Sprachen liegt (zumal LUA, je nach Ausführung, extrem schnell sein kann).

Sondern eher an - absichtlich oder versehentlich - quadratischen Algorithmen und ähnlichem.

Shader compilieren ist auch noch ein Beispiel. Bei X-Plane dauert der erste Start in ein neues Szenario bis zu Minuten in denen gar nix vorangeht. Dafür muss während des Spiels nix ruckelnd nachcompilieren, und wenn man nix verändert sind beim nächsten Start die Shader zum Glück gecached.

Bei Sim City 2000 konnte man statt „Loading…“ noch halbwegs sehen, was tatsächlich gerade passiert. Reticulating Splines!

2 „Gefällt mir“

Ich weiss nicht mehr obs Wing Commander 3 oder 4 war, aber auf meinem 486 DX2 66MHz hat das damalsTM absolut keinen Spass gemacht! Jeder Missionsstart hat mehrere Minuten auf sich warten lassen, und stockte selbst dann noch bis man einmal alle Waffen abgefeuert, und somit die entsprechenden Sounds ins RAM geladen, hatte. Es war also nicht alles besser. (Von Kassettenlaufwerken reden wir erst gar nicht.)

Einen dokumentierten Fall von Schlamperei beim Programmieren gabs vor ein paar Jahren noch mit GTA V, wo eine 10MB Datei mit 63000 Eintraegen JSON Daten beim Laden mehrere Minuten verschwendete und von einem Modder auf 25% der Zeit gekuerzt wurde (was die Entwickler dann spaeter als offiziellen Patch nachgebaut haben).

1 „Gefällt mir“

Übrigens, manchmal verbergen sich auch hinter diesen unskippbaren Logo-Animationen am Start irgendwelche Vorberechnungs-Vorgänge.

Zumindest lässt das der CPU-Last-Monitor vermuten, wenn er derweil läuft. Das Abspielen der Animation alleine sollte heutzutage vermutlich nicht alle Cores, und dann irgendwie auch nur für einen Teil der Zeit, voll auslasten, heheh…

1 „Gefällt mir“

Der Zeitdruck in der Entwicklung von Business Software ist oft hoch - ich glaube, dass es bei Spielen noch schlimmer ist, da man sich ja viel Freiheit nimmt um Dinge nachzupatchen und nicht jeder den MVP Weg geht, der für Business Software heutzutage als Best Practice gilt (das kleinst-mögliche Produkt ausrollen, dass irgendwie einen Nutzen bringt um möglichst früh an Bugs und Problemen zu arbeiten und die Anwendung bei vollkommener Fehlinterpretation der Anforderungen noch umsteuern zu können. Der beste Vergleich bei Games dürfte da Early Access sein).

Ich gehöre ja zu den großen Verfechtern von MVPs mit kleinen Iterationen - so wie das in der rein agilen Lehre eigentlich ist. Big Bangs sind gefürchtet und sind im Release immer eine Katastrophe - grade weil die benötigte Entwicklungszeit extrem schwierig zu schätzen ist oder die Zeiten von den falschen Menschen „korrigiert“ werden.

Große Spieleproduktionen sind per sé noch Big Bangs… Klar wird da viel nachgereicht und nachgepatched aber man bringt trotzdem ein großes Produkt an den Start. Das alte Entwicklungsdreieck nach Quantität, Zeit und Kosten, wie das Projektmanagement es früher mal gepredigt hat funktioniert nicht gut, weil Qualität nicht berücksichtig wird oder nur als eine andere Form von Quantität auftritt. Da kommen wir dann zu dem Performance-Testing von dem du sprichst. Im Businessbereich gibt es schlichtweg Teams und Unternehmen die Load- und Performancetests gar nicht oder nur sehr geringwertig mit schlechter Methodik vornehmen. Da schleichen sich dann halt hier und Flüchtigkeitsfehler ein, die zu schlechten Laufzeiten und Memory Leaks führen. Playtesting für ein lauffähiges Spiel gibt es aber dennoch ist glaube ich nochmal ein eigenes Feld für sich. Das genaue Aufspüren von Performance Problemen ist jedoch keine so einfache Angelegenheit. Grade wenn wir hier von Spielen die an sich schlechter testbar sein dürften als Webanwendungen oder verteilte Systeme.

Da kommt jetzt weiteres Halbwissen von mir: Ich vermute, dass Spiele in sich noch Monolithen sind die an vielen Stellen nur über eingeschränkte Testbarkeit verfügen und dass viele Techniken, die ich z.B. aus dem klassischen Test Engineering kenne, dort gar nicht greifen können. Aufgrund der schwierigen Bedingungen und des unwahrscheinlich hohen Zeit- und Ressourcendrucks in der Spieleentwicklung ist für mich klar, dass die Qualität oft der Faktor ist, den man zurücknimmt. Das macht psychologisch auch Sinn: gehypte Spiele verkaufen sich trotzdem… und für die Leute die Spiele später kaufen (ich z.B.) gibt es dann eine gepolishte Erfahrung.

Ist nur dann doof wenn alles an einem Spiel hängt und die Firma nach Release quasi dicht macht (siehe Troika damals). Da bleibt dann nur eine unfertige Ruine zurück wenn eine Community das Ding nicht patched.

Interpreter für Skriptsprachen sollten alle soweit optimiert sein, dass da keine großen Performance Issues drin sind. Das gilt insbesondere für die großen Engines :wink:

Ich möchte hier als Spieleprogrammierer mal meine Ansichten zu diesem Thema äußern, vor allem weil ich es hochspannend finde.

Zum eigentlichen Anliegen des Fragestellers:

Ladezeiten von 24 Minuten sind indiskutabel, das ist keine Frage. Aber zu vermuten, dass hier künstlich gewartet wird ist nicht plausibel, es ist nicht im Interesse eines Spieleherstellers seine Kunden zu verärgern. Es gibt eine Reihe von Faktoren, die zu derartigen Ladezeiten führen können.

Zum Einem darf man nicht den Fehler machen und vermuten das Laden eines Spielstandes sei damit erledigt, dass man die Dateien von der Festplatte in den Speicher kopiert. In den meisten Fällen sind gerade Spielstände in einem flexiblen Datenformat kodiert, das es ermöglicht das Datenformat mit neuen Versionen des Spiels zu verändern, ohne das alte Spielstände unlesbar werden. Daher gibt es nach dem Laden in der Regel einen zusätzliche Vorgang der die geladenen Daten in ein nutzbares Laufzeitformat umwandelt. Die Flexibilität erkauft man sich mit einem Verlust an Laufzeiteffizienz.

Dies gilt in den meisten Fällen auch für Assets, auch die liegen zumeist nicht als Speicherabbild auf der Festplatte, sondern müssen zusätzlich vor der Verwendung konvertiert werden. Ganz zu schweigen von anderen Initialisierungsschritten wie z.B. dem Anlegen von Texturen (API-Overhead) und dem Kopieren von Texturdaten ins VRAM.

Weiterhin ist es mit dem Laden des eigentlich Spielstandes auch nicht getan, der Spielstand enthält nur den abgespeicherten Zustand des Spiels. Den Löwenanteil der zu Ladenen Daten entfällt auf die Assets, die vom Spielstand referenziert werden. Vermutlich ist das Laden der Assets im vorliegenden Fall ineffizient gelößt und in einer Weise umgesetzt, die vom der Geschwindigkeit einer SSD nicht profitiert.

Eine SSD mag zwar sehr schnell sein, aber es ist nicht trivial sie auch auszulasten. SSDs sind eben so schweineschnell, dass es häufig weit mehr CPU-Zeit kostest I/O-Requests abzusetzen als die SSD zum erfüllen dieser Requests benötigt. Es ist nicht möglich das Potential einer SSD voll zu nutzen ohne fundamentale Systeme der Engine speziell hierauf auszulegen.

Gewissheiten die Jahrzehnte lang bestand hatten und die das Design von Engines bestimmt haben gelten nun nicht mehr. Um nur mal einen Datenpunkt zu nennen: eine PS5 SSD mit ihren Hardware Decompression-Engines lädt Daten um den Faktor 100 schneller als eine PS4 von ihrer HDD. Früher hat man große Anstregungen unternommen so wenig Daten wie nötig von der Festplatte zu lesen und dabei z.B. aufwändige Kompressionsverfahren eingesetzt, denn es war schneller die stark komprimierten Daten auf der CPU zu dekomprimieren als große unkomprimierte Daten von der Festplatte zu lesen. Ebenso hat man flexible aber langsam zu dekodierende Datenformate verwendet, da die Kosten hierfür im Verhältnis zu den anderen Aufwänden vernachlässigbar waren. Datenkompression lohnt sich jetzt kaum noch, die SSD liest die Daten so schnell, dass eine dekomprimierende CPU zum Flaschenhals wird. Ebenso ist es extrem wichtig effiziente Datenformate zu verwenden, da ansonsten wiederrum die CPU zum limitierenden Faktor wird. Es gibt auch noch weitere Unterschiede (z.B. Seek Times) auf die ich hier nicht eingehe.

Man muss eine Engine also grundlegend auf SSDs anpassen. Ich vermute, dass dies bei vielen Engines noch nicht vollständig geschehen ist. Bei einigen anderen, wie Source, wird das vermutlich niemals passieren. Leider ist es auch so, dass Anpassungen an eine SSD die Benutzung einer HDD noch unterträglicher machen, vielleicht ist manch einer daher auch zögerlich.

Daher verwundert es mich nicht, das ältere Engines wenig von einer SSD profitieren. Die hier viel gescholtene Unreal Engine hingegen hat mit ihrem Zen Loader eine zeitgemäße Lösung parat, die auch von APIs wie DirectStorage und ihr PS5-Äquivalent nutzt.

Ich glaube der eigentlich Pferdefuß in diesem konkreten Fall sind aber die 900 Mods die verwendet werden. Selbst wenn man postuliert, dass das Laden des eigentlichen Spielstandes gar keine Zeit in Anspruch nimmt, kommt man für das Laden einer einzelnen Mod auf nur 1,6 Sekunden. Das ist jetzt nicht absurd lang. Vermutlich ist das Laden der Mods nicht parallelisiert und es muss für jede Mod eine oder mehrere Definitionsdateien geladen, geparsed und entsprechende Assets geladen und initialisiert werden.

Was beim Laden der Mods vermutlich auch ins Gewicht fällt ist, dass das Öffnen von Dateien unter Windows absurd lange dauert. Hierauf hat man als Entwickler leider gar keinen Einfluss hat. Dies liegt in erste Linie an Windows Defender, der jede einzelne Datei beim Öffnen auf Viren scannt. Dies kann man mit einer schnellen Festplatte auch nicht kompensieren, hauptsächlich wird hiermit die CPU belastet. Aus diesem Grund verwenden viele Spiele sogenannte Packfiles, das sind Dateien die viele kleine Dateien zu einer großen Datei zusammenfassen. Man muss damit nur wenige Dateien öffnen und umgeht so dieses Problem. Mods sind jedoch vermutlich in jeweils (mehreren?) Einzeldateien abgelegt was bei der schieren Anzahl ins Gewicht fallen wird.

Wenn dann das Laden von Assets zusätzlich nicht sehr effizient ist, sind die 24 Minuten nicht unrealistisch, auch mit einer SSD.

Ich möchte noch mal betonen, dass ich diese langen Ladezeiten nicht verteidigen will. Es geht besser und der Entwickler muss hier tätig werden. Ich will nur plausibel machen, dass das beobachtete Verhalten ohne absichtlichen „Leerlauf“ möglich ist. Die Formel SSD = schnell gilt nun mal nicht, das Laden von Spielständen ist eine wesentlich komplexere Angelegenheit als man auf den ersten Blick vielleicht denkt.

13 „Gefällt mir“

Ich habe vor ein par Jahren noch recht intensiv Cities Skylines gespielt und da verhielt es sich mit den Mods sehr ähnlich bzw. ist es eigentlich bei allen Spielen dieser Art so. Das war schon fast eine Wissenschaft für sich und es gab rege Diskussionen um die Kompatibilität der einzelnen Mods untereinander und die Ladezeiten. Es dauerte auch nicht lange bis es Mods gab die die Ladezeiten analysierten, reduzierten und auch Manager damit man das Spiel nur mit den benötigten Mods starten konnte.
(Mit Mods meine ich auch Assets)

Nach dem letzten Post weiß ich auch nicht ob man das Problem überhaupt so einfach lösen kann.

Mega interessanter Beitrag, vielen Dank dafür!

Ich kenne das Problem mit den Mods auch. Wir spielen ab und an mal Ark: Survival Evolved. Im Standard lädt das einigermaßen fix, sowohl was den Spielstand selbst angeht als auch das Starten des Servers. Mit jedem Mod den man dazu lädt kann man zugucken wie die Ladezeiten deutlich hochgehen, eher unabhängig von der eigentlichen Größe des Mods. Absoluter „Spitzenreiter“ ist dann ein Total Conversion Mod, der aus mehreren Tausend einzelnen Dateien / Assets besteht - die für sich betrachtet immernoch überschaubar groß sind. Die werden vermutlich nicht alle auf einmal geladen, aber die Ladezeit geht da um Minuten hoch.
Die Erklärung mit dem (vermutlich) sequentiellen Lesen der Daten + Windows Defender leuchtet ein.

Hallo zusammen,

Ich erinner mich noch an die Ladezeit beim Spielstart von Civilizaton 1 beim Amiga 500, (glaube 30 min oder ähnlich), dagegen ist alles andere ein Klacks. :joy:

Ne, so schlimm war es nicht. 5 Minuten etwa, wenn ich es richtig im Kopf habe. Aber ja, es war ganz schön lang. War aber ganz nett ins Intro integriert.

1 „Gefällt mir“

Aber die Intro in Civilization 1 konnte man doch überspringen, nicht? Zumindest in der DOS-Version

Beim Amiga konnte erstmal übersprungen werden wenn die Welt fertig geladen war. Und das hat gedauert. :slightly_smiling_face:

Bei der Amiga 500 Diskettenversion waren es glaube zwischen 20-30 min.
Aber vielleicht war mein Zeitempfinden vor 30 Jahren anders. :grinning:

Vorsicht vor dem „Äpfel und Birnen“ Vergleich. Ja, die Erstellung einer neuen Welt in Civ I war auf dem Amiga 500 eine Geduldsprobe. Aber es ist auch stark von der Kartengröße abhängig. So gesehen können 5 min bzw. 20 min durchaus passen. Kann man ja mal im Emulator nachstellen (Original CPU- und Disk-Speed).
Es war ein Segen, dann irgendwann auf dem PC zu spielen. :upside_down_face:

1 „Gefällt mir“