Warum fastDOOM so schnell ist
(fabiensanglard.net)- Auf einem IBM PS/1 486-DX2 66 MHz, einem High-End-PC von 1993, erreichte das originale DOOM bei
demo121,5 fps, während fastDOOM unter denselben Bedingungen auf 30,1 fps kam – ein deutlicher Unterschied durch Optimierungen des DOS-Ports - fastDOOM entstand aus PCDOOM v2, einer Kombination aus Linux-DOOM-Core, Heretic-I/O, APODMX und Mode-Y-Grafik-I/O auf Basis einer Disassemblierung von
DOOM.EXE - Nach dem Bauen und Benchmarken von 52 Releases und 3.042 Commits zeigte sich: Der Performance-Gewinn kam nicht von einem modernen Compiler allein, sondern durch die Summe vieler kleiner Optimierungen
- Zu den großen Verbesserungen zählen das Überspringen des Statusleisten-Renderings, das Inlining von
FixedDiv, optimierte BSP-Traversierung, das Auslassen von Visplane-Rendering, das Entfernen indirekter Pointer-Zugriffe und separate Executables je Renderer - Welche Grafikmodi vorteilhaft sind, hängt von CPU und Bus ab: Auf langsameren CPUs ist Mode Y im Vorteil, während auf schnellen CPUs sowie in VLB/PCI-Umgebungen Mode 13h oder VESA direct besser sein können – allerdings bleiben Einschränkungen wie VESA 2.0
Sichtbare Performance-Unterschiede auf einem 486-DX2
- Führt man auf dem IBM PS/1 486-DX2 66 MHz „Mini-Tower“, Modell 2168, das originale DOOM mit
doom.exe -timedemo demo1aus, erhält man1710 gametics in 2783 realtics- DOOM gibt fps nicht direkt aus; sie müssen mit
1710/2783*35berechnet werden. Das Ergebnis sind 21,5 fps
- DOOM gibt fps nicht direkt aus; sie müssen mit
- Auf derselben Maschine liefert
fdoom.exe -timedemo demo1den Wert1710 gametics in 1988 realtics, also 30,1 fps - Auf schwereren Maps wie
demo1vondoom2steigt die Performance von 16,8 fps im Original auf 24,9 fps in fastDOOM – 48 % schneller - Allerdings wurden Joystick- und Network-Gameplay-Support entfernt; es ist also kein Port, der alle Funktionen unverändert beibehält
Die Code-Abstammung von fastDOOM
- DOOM wurde ursprünglich auf einer NeXT Workstation entwickelt und hatte eine leicht portierbare Struktur, aufgeteilt in den größten Teil des Core-Codes und ein kleines I/O-Subsystem
- Die kommerzielle DOS-Version nutzte von id Software geschriebenes DOS-I/O, konnte 1997 aber wegen der Abhängigkeit von der proprietären Soundbibliothek DMX nicht unverändert als Open Source veröffentlicht werden
- Der veröffentlichte Code war die Linux-Version, die Bernd Kreimeier im Rahmen eines Buchprojekts zur Erklärung der Engine aufbereitete
- Die DOS-Version PCDOOM v2 wurde aus folgender Kombination rekonstruiert
- dem Core von Linux DOOM
- dem I/O von Heretic
- APODMX zur Nachbildung von DMX
- aus der Disassemblierung von
DOOM.EXEreverse-engineertemi_ibm.c-Grafik-I/O
- fastDOOM nahm dieses PCDOOM v2 als Ausgangspunkt
Performance-Veränderungen anhand von Releases und Commits
- Victor „Viti95“ Nieto veröffentlichte fastDOOM häufig, taggte jedes Release und verwaltete die Historie so, dass ein Commit jeweils eine Aufgabe erledigt
- Die Git-Historie von fastDOOM umfasst 3.042 Commits, wodurch sich Performance-Veränderungen commitweise nachverfolgen ließen
- 52 fastDOOM-Releases, PCDOOM v2 und das originale
DOOM.EXEwurden heruntergeladen; ein Go-Programm erzeugte einRUN.BAT, das-timedemo demo1ausführt, und die Tests wurden über mTCPNETDRIVEgemountet- Bedingungen:
DOOM.WAD, Sound an, Screen Size 10 - Die komplette Suite wurde fünfmal ausgeführt, anschließend wurde der durchschnittliche fps-Wert als Graph geplottet
- Bedingungen:
- Obwohl PCDOOM v2 mit OpenWatcom 2 gebaut wurde, war der Zuwachs gegenüber dem originalen
DOOM.EXEnicht groß. Die Verbesserungen von fastDOOM lassen sich daher schwer allein durch den Einsatz eines modernen Compilers erklären - Der Dateigrößen-Graph zeigte, dass die frühe Arbeit darauf abzielte, den Code durch Aufräumen und Löschen leichter zu machen
Änderungen je Release, die die Performance steigerten
- Da ein Timedemo über alle 3.042 Builds hinweg etwa neun Tage dauern könnte, wurden commitweise Benchmarks vor allem für
v0.1,v0.6,v0.8,v0.9.2undv0.9.7durchgeführt, bei denen die Geschwindigkeitszuwächse groß waren -
fastDOOM v0.1
v0.1besteht aus 220 Commits- Der größte Patch ist e16bab8 in Build 36
- Die „Crispy optimization“ macht das Rendering der Statusleisten-Prozentanzeige zu einem No-op, wenn sich der Wert nicht geändert hat, und vermeidet dadurch Scrap-Buffer-Rendering und Screen-Blitting
- Allein diese Änderung brachte nachweislich 2 fps mehr
- a9359d5 in Build 167 inlinte
FixedDivals Makro - 9bd3f20 in Build 207 übernahm eine Optimierung aus PSX Doom und verbesserte die BSP-Traversierung
- dc0f48e in Build 212 inlinte die Renderfunktion für horizontale Flächen
R_MakeSpans - Von allen Commits waren 100 Lösch-Commits; etwa die Hälfte bestand also aus Code-Entfernung
-
fastDOOM v0.6
-
fastDOOM v0.8
v0.8besteht aus 282 Commits- Da das Sound-System instabil war, wurden Timedemos ohne Sound durchgeführt und die fps anschließend korrigiert
- Dieses Release konzentrierte sich auf den Text-Mode-Renderer; in Build 670 und Build 730 fiel die Crispy optimization heraus, wodurch Regressionen entstanden
- Die wichtigsten Verbesserungen waren:
-
fastDOOM v0.9.2 und v0.9.7
v0.9.2umfasst 110 Commits; wichtige Änderungen waren die Optimierung des skyflatnum-Vergleichs, die Optimierung vonR_DrawColumnfür Mode Y sowie Aufräumarbeiten anR_DrawSpanv0.9.7wurde als Release mit 293 Commits vorgestellt, die Befehlsausgabe zeigt jedoch 294- Bei diesem Release ließ sich das Rauschen auch durch mehrere Benchmarks nicht reduzieren
- Wichtige Änderungen waren Tests mit x86-ASM-Änderungen, CPU-Auswahl für 386SX und CR2-Optimierung, ESP-Optimierung für
R_DrawSpan386SX, Code auf Basis von ASM Fuzz Column Rendering sowie das Entfernen von CMP-Vergleichen pro Loop
Entscheidungskriterien für Mode 13h, Mode Y und VESA direct
- fastDOOM untersucht verschiedene Optimierungen für viele CPU- und Videobus-Kombinationen wie 386, 486, Pentium, Cyrix sowie ISA, VLB und PCI
- Auf dem IBM PS/1 486-DX2 66 MHz war die Optimierung mit Mode 13h statt Mode Y langsamer
-
Mode 13h
- Die Hardware übernimmt das Verteilen der Daten auf die vier VRAM-Bänke der VGA-Karte, sodass sie der CPU wie ein einzelner linearer 320x200-Framebuffer erscheinen
- Double Buffering im VRAM ist nicht möglich; daher muss im RAM gepuffert und anschließend zurück in den VRAM kopiert werden, wodurch Bytes zweimal geschrieben werden
- Die Engine muss bei VSYNC blockieren
-
Mode Y
- Die VGA-Bänke lassen sich einzeln ansprechen, wodurch VRAM Triple Buffering möglich ist und Bytes direkt nur einmal in den VRAM geschrieben werden müssen
- Für die Bankauswahl ist der langsame
OUT-Befehl nötig - Schreibt man über den Latch gleichzeitig in zwei VGA-Bänke, ist horizontale Pixelduplikation möglich, wodurch ein Low-Detail-Mode entsteht
- Das Rendering unsichtbarer Specters erfordert VRAM-Readback und ist dadurch deutlich langsamer
- Nach John Carmacks Erklärung nutzte DOOM im VGA-Modus 320×200×256 einen Mode-X-ähnlichen interleaved planar mode und rotierte zwischen drei Display Pages
- Direktes Texture Mapping in den Video Memory konnte auf vielen Videokarten 10 % bis 15 % zusätzliche Geschwindigkeit bringen
- Zudem war Page Flipping ohne Tearing möglich, anders als beim Buffering im Main Memory
- Heretic erschien 1994, und durch die damaligen Hardwareänderungen wurde Mode 13h zur attraktiveren Wahl; Raven modifizierte die DOOM-Engine in diese Richtung
- fastDOOM stellt den Nutzern mehrere Executables bereit
FDOOM.EXEFDOOM13H.EXEFDOOMVBD.EXE
-
Mode 13h und VESA direct in fastDOOM
- Der Mode 13h von fastDOOM rendert in einen einzelnen Framebuffer im RAM und kopiert ihn nach Abschluss der gesamten Szene in den VRAM
- VSYNC wird nicht erzwungen, wodurch Flickering entstehen kann
- Auf dem langsamen 8-bit-ISA-Bus wird Differential Copy genutzt, bei dem nur geänderte Pixel übertragen werden
- Auf schnelleren Bussen wie 16-bit ISA, VLB oder PCI wird der gesamte Backbuffer mit
REP MOVSkopiert - Nach Viti95s Tests ist der beste Modus für 486-CPUs der VESA direct mode für 320×200,
FDOOMVBD.EXE- Er kombiniert die Vorteile von Mode Y mit Heretics optimiertem Rendering-Code
- Abgesehen von einem
OUTpro Frame beim Buffer-Wechsel vermeidet erOUT-Befehle - Er benötigt eine VLB- oder PCI-Grafikkarte mit aktiviertem LFB und VESA-2.0-Support; in Low-Detail- und Potato-Detail-Modes ist er langsam
- Der IBM 2168 unterstützt kein VESA 2.0, daher treten beim Ausführen von
FDOOMVBP.EXEundFDOOMVBDFehler auf
Nicht erfolgreiche Versuche und Gesamteindruck
- Auch die prozessorspezifischen OpenWatcom-Flags
4r/4sund3r/3swurden ausprobiert, aber wieder aufgegeben- Sowohl die 386- als auch die 486-Flags von wcc386 wurden getestet; am Ende schien die 386-Version immer schneller zu sein
- Viti95 hat außerdem das Ziel, den Compiler von fastDOOM von OpenWatcom v2 auf DJGPP, also GCC, umzustellen
- Denn GCC erzeugte aus derselben Quelle offenbar schnelleren Code
- Alternativ bleibt es eine wünschenswerte Option, dass OpenWatcom v2 verbessert wird und den Performance-Abstand verkleinert
- Die Performance von fastDOOM ist das Ergebnis der Nutzung bestehender Verbesserungen aus Crispy, PSX, GBA und von Lee Killough sowie vieler neuer Optimierungen
- Auch Ideen und Teile des Codes von Ken Silverman flossen in Renderfunktionen für die UMC Green CPU ein und brachten auf dieser Hardware große Geschwindigkeitszuwächse
- fastDOOM ist kein Beispiel für eine einzelne magische Änderung, sondern dafür, wie Tausende kleiner Optimierungen zusammen einen DOS-Port ergeben, der schneller ist als das originale DOOM
1 Kommentare
Meinungen auf Hacker News
Ein gutes Beispiel dafür, dass Engpässe meist nicht dort liegen, wo man sie erwartet – deshalb braucht es Profiling und Messungen.
Dass ausgerechnet das Rendern der Prozentanzeige in der Statusleiste der Flaschenhals war, mag für Experten, die die Doom-Struktur gut kennen, relativ offensichtlich gewesen sein, aber vorher hätte ich das sicher nie als Engpass vermutet.
https://www.granola.ai/blog/dont-animate-height
Im schlimmsten Fall wurde fast ein Sechstel des gesamten Frames dafür verwendet, den Score in der Statusleiste anzuzeigen, wodurch die Schwelle für Verlangsamungen niedriger lag; der Patch änderte Speicherung und Anzeige des Scores auf nahezu konstante Zeit und machte es sogar etwas schneller als den bisherigen Bestfall.
https://www.smwcentral.net/?p=section&a=details&id=35746
UI-Rendering kann durch Transparenz, Layering, Neuzeichnen und vor allem durch ausgelöste Speicherallokationen fatal werden; ein Vergleich von altem und neuem Wert vor dem Neuzeichnen hilft enorm.
Auch bei CSS gab es ein Projekt, bei dem Layer und Transparenz der Flaschenhals waren; dort war die Reduzierung der Layer-Anzahl entscheidend.
Die Ladezeit von 6 Minuten wurde auf unter 2 Minuten reduziert.
https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times...
https://news.ycombinator.com/item?id=10974929
Vielleicht bin ich nicht die eigentliche Zielgruppe, aber NETDRIVE von mTCP fand ich interessant.
Ich hätte nicht gedacht, dass es schon so früh brauchbare Optionen für Netzwerkspeicher gab; beim Nachsehen fand ich https://www.brutman.com/mTCP/mTCP_NetDrive.html, was wirklich cool ist.
NetDrive soll ein Gerätetreiber sein, der es erlaubt, aus DOS auf ein von einer anderen Maschine gehostetes Remote-Disk-Image wie auf ein lokales Gerät mit Laufwerksbuchstaben zuzugreifen.
Es war extrem langsam, sodass Schüler zu Unterrichtsbeginn jeweils 5 bis 10 Minuten verloren, nur um die Textverarbeitung zu starten; auch der Xerox Alto nutzte Netzwerkmounts für Laufwerke.
Wenn es Networking gibt, will bald jemand Dateien kopieren, und die bequemste Art ist, es wie ein lokales Dateisystem aussehen zu lassen.
DOS hatte kein eingebautes Networking und hinkte in dieser Hinsicht hinterher; vieles musste man selbst erledigen.
Damit bekommt man Lese- und Schreibzugriff auf ein Netzwerk-Blockgerät, ohne DOS-seitige Treiber oder Konfiguration; wenn man es wie eine Freigabe benutzt, geht es schnell kaputt, es ist eher ein Blockgerät.
Es wirkt wie Magie, aber offenbar patcht iPXE das BIOS so, dass Plattenzugriffe an iSCSI geschickt werden.
FTP und telnet gab es natürlich, aber ich frage mich, ob Remote-Mounts tatsächlich genutzt wurden oder wegen der geringen Bandbreite nicht machbar waren.
Der GitHub-Thread mit Ken Silverman ist ein Schatz.
Es ist erstaunlich zu sehen, wie der FastDOOM-Autor und Ken sich in obskure 486-Register und Effizienz bei Taktzyklen vertiefen.
Es ist schön, dass es noch immer Leute gibt, die dafür sorgen, dass Doom Performance-Verbesserungen bekommt.
Dieses Scripting war buchstäblich mein erstes „Coden“, und in gewisser Weise verdanke ich KenS meine ganze Karriere und mein Vermögen – ziemlich großartig.
Besonders gut gefiel mir die Idee, auf dem 386SX mit sehr langsamen Speicherzugriffen und auf dem 386DX ohne Cache CR2 und CR3 wie Scratchpad-Register zu verwenden.
Auch die Technik, ESP als Loop-Counter zu verwenden, ohne Interrupts abzuschalten, ist genial: Sie stellt sicher, dass es immer auf eine gültige Stack-Position zeigt.
Eine Funktion von FastDOOM, die hier kaum behandelt wurde, sind die vielen seltsamen Videomodi
IBM-MDA-Textmodus: https://www.youtube.com/watch?v=Op2tr2lGK6Y
EGA & Plantronics ColorPlus: https://www.youtube.com/watch?v=gxx6lJvrITk
Klassisches blau-pinkes CGA: https://youtu.be/rD0UteHi2qM
CGA 320x200x16 mit dem „ANSI from Hell“-Hack: https://www.youtube.com/watch?v=ut0V1nGcTf8
Hercules: https://www.youtube.com/watch?v=EEumutuyBBo
Die meisten scheinen wegen Dingen wie Farb-Remapping langsamer zu laufen als VGA
Wenn ich es in CGA spielen müsste, fände ich das wohl nicht gut; und wenn er noch am Leben wäre, hätte es wohl einen 286-Build für den Tandy 1000 TL/2 gebraucht
Erinnert an die „moderne“ Clean Architecture bei Backend-Anwendungen
Die Stelle „IBM PS/1 486-DX2 66Mhz, ‚Mini-Tower‘, Modell 2168. Der Computer, den ich als Teenager immer haben wollte, mir aber nicht leisten konnte“ fand ich bemerkenswert
Um 1992 herum nutzte ich meinen vierten selbstgebauten PC, und die KCS-Computermesse in Marlborough, MA, war für Bastler eine enorme Ressource
Man kaufte Teile, baute einen PC, nutzte ihn eine Weile, verkaufte ihn und kaufte wieder Teile
Ende 1992 hatte ich einen 486-DX3 100 mit ULSI-487-Mathe-Coprozessor laufen, und eine Zeit lang war das der schnellste PC auf dem Campus, vielleicht sogar der schnellste Computer
Er war schneller als mehrere Pentium-Modelle und produzierte auch keine Rechenfehler
Den letzten Build rechtfertigte ich damit, dass die Neuberechnungszeiten zu lang wurden, weil ich für meine Honors Thesis ein Gas-/Diesel-Blockheizkraftwerk in einer 21-seitigen Excel-Tabelle simulierte
Mein Hauptfach war Umweltwissenschaften, aber meine Karriere bestand komplett aus Computern
Musste man das jemandem, der sich 1992 so einen Computer nicht leisten konnte, wirklich noch unter die Nase reiben?
Außerdem gab es keinen „DX3“, und der DX4, der erste 100-MHz-486, kam erst im März 1994 heraus; dass er Ende 1992 lief, scheint also nicht zu stimmen
Unser erster Computer, wenn man den damals schon völlig veralteten XT ausnimmt, den wir um 1992 bekamen, war ein 66MHz 486-DX2, gekauft Anfang 1995
Selbst Jahrzehnte später kränkt es mein Ego irgendwie, wenn jemand mit einem unmöglichen Computer prahlt, der trotz drei Jahren Vorsprung schneller gewesen sein soll als meiner
Um 1992 herum war ich ein armer Student und nahm bei der Credit Union etwa 2.000 Dollar Kredit auf, um einen 486 DX2-50 zu kaufen
In heutigem Geld waren das über 4.000 Dollar für einen ziemlich einfachen Computer, und darauf hatte ich DOS und Linux im Dual Boot
Nach kurzem Nachsehen war der Standard-487 offenbar eigentlich ein vollständiger 486DX, der den 486SX deaktivierte und ersetzte
War das vielleicht irgendein anderer, großartiger Coprozessor, von dem ich nichts wusste?
Das ist eine echte Demontage
Neben den häufigen Releases zeigte Viti95 auch hervorragende Git-Disziplin: Ein Commit erledigt eine Sache, und jedes Release wurde getaggt
https://fabiensanglard.net/fastdoom/#:~:text=one%20commit%20...
Bei „Bis ich fastDOOM entdeckte, hatte ich mich damit abgefunden, beim Spielen Ibuprofen nehmen zu müssen“ weiß ich nicht, was Ibuprofen heißen soll
Falls der Autor das sieht: Im gesamten Dokument ist John Carmacks Nachname als „Carnmack“ falsch geschrieben
Eine nicht zynische Erklärung dafür, warum moderne Software langsam ist und solche Optimierungen fehlen, ist die Standardisierungs-/Optimierungshypothese
Wenn etwas zum Standard wird, folgt Optimierung
Denn man will der Schnellste sein und zugleich alle Tests des Standards bestehen
Doom ist inzwischen ebenfalls ein Standardspiel geworden, das auf alles portiert wird, ob neue CPU oder Toaster; bei E-Mail-Protokollen oder Browser-Standards wie WebRTC, QUIC usw. ist es ähnlich
Der Grund, warum moderne Web-Apps oder Electron-Apps nicht schnell sind, ist, dass sie sich in der Explorationsphase befinden
Sie werden täglich für neue Nutzeranforderungen aktualisiert, und bei der Performance reicht es, wenn sie gerade schnell genug sind, um nicht im Weg zu stehen
Deshalb sind IRC-Apps sehr schnell, während Slack und Teams zwangsläufig immer langsam sein können
Beim Zurückgehen durch Versionen Verbesserungen und Regressionen zu prüfen, ist nicht trivial
Manche Optimierungen können Bugs erzeugen, die erst später entdeckt werden, und zwingend nötige Features können die Performance verschlechtern
Deshalb macht ein automatisch vor jedem Release laufender Performance-Test das Leben leichter; wenn ein Performance-Problem entdeckt wird, schreibt man wie üblich einen Regressionstest
Worauf ich hinauswill: Macht Performance-Tests