Pourquoi fastDOOM est plus rapide
(fabiensanglard.net)- Sur un IBM PS/1 486-DX2 66MHz, l’équivalent d’un PC haut de gamme en 1993, le DOOM original atteignait 21,5 fps sur
demo1, tandis que fastDOOM montait à 30,1 fps dans les mêmes conditions, illustrant l’écart d’optimisation du port DOS - fastDOOM est parti de PCDOOM v2, qui combinait le noyau de Linux DOOM, les E/S de Heretic, APODMX et des E/S graphiques en Mode Y fondées sur la rétro-ingénierie par désassemblage de
DOOM.EXE - Après avoir compilé et benchmarké 52 releases et 3 042 commits, il apparaît que le gain de performances ne vient pas d’un compilateur moderne à lui seul, mais de l’accumulation de petites optimisations
- Parmi les améliorations les plus marquantes figurent l’omission du rendu de la barre d’état, l’inlining de
FixedDiv, l’optimisation de la traversée BSP, la suppression de rendus visplane inutiles, l’élimination d’indirections de pointeurs et la séparation des exécutables par renderer - Le mode graphique le plus efficace dépend du CPU et du bus : sur les CPU lents, le Mode Y est avantageux, tandis que sur des CPU plus rapides avec VLB/PCI, le Mode 13h ou VESA direct peuvent être meilleurs, avec toutefois des contraintes comme VESA 2.0
L’écart de performances visible sur un 486-DX2
- Sur un IBM PS/1 486-DX2 66MHz « Mini-Tower » modèle 2168, exécuter le DOOM original avec
doom.exe -timedemo demo1donne1710 gametics in 2783 realtics- DOOM n’affiche pas directement les fps ; il faut donc calculer
1710/2783*35, ce qui donne 21,5 fps
- DOOM n’affiche pas directement les fps ; il faut donc calculer
- Sur la même machine,
fdoom.exe -timedemo demo1affiche1710 gametics in 1988 realtics, soit 30,1 fps - Sur des cartes plus lourdes comme
demo1dedoom2, on passe de 16,8 fps pour l’original à 24,9 fps pour fastDOOM, soit 48 % plus rapide - En revanche, la prise en charge du joystick et du jeu en réseau a été supprimée ; ce n’est donc pas un port qui conserve toutes les fonctionnalités à l’identique
La lignée du code derrière fastDOOM
- DOOM a été développé à l’origine sur NeXT Workstation, avec une structure facile à porter, séparant l’essentiel du code d’un petit sous-système d’E/S
- La version DOS commerciale utilisait des E/S DOS écrites par id Software, mais à cause de sa dépendance à la bibliothèque audio propriétaire DMX, elle n’a pas pu être open source telle quelle en 1997
- Le code publié correspond à la version Linux, préparée par Bernd Kreimeier dans le cadre d’un projet de livre expliquant le moteur
- La version DOS PCDOOM v2 a été reconstituée à partir de la combinaison suivante
- le noyau de Linux DOOM
- les E/S de Heretic
- APODMX pour imiter DMX
- les E/S graphiques de
i_ibm.crétroconçues à partir du désassemblage deDOOM.EXE
- fastDOOM prend ce PCDOOM v2 comme point de départ
L’évolution des performances suivie via les releases et les commits
- Victor « Viti95 » Nieto publiait souvent fastDOOM, taguait chaque release et organisait ses commits pour qu’un commit corresponde à une tâche
- L’historique Git de fastDOOM compte 3 042 commits, ce qui a permis de suivre l’évolution des performances commit par commit
- Les 52 releases de fastDOOM, PCDOOM v2 et le
DOOM.EXEoriginal ont été téléchargés, puis un programme Go a généré unRUN.BATexécutant-timedemo demo1, monté via mTCPNETDRIVEpour les tests- Les conditions étaient
DOOM.WAD, son activé et screen size 10 - La suite complète a été exécutée 5 fois afin de tracer un graphique de fps moyens
- Les conditions étaient
- Bien que PCDOOM v2 ait été compilé avec OpenWatcom 2, l’amélioration face au
DOOM.EXEoriginal reste modeste, ce qui montre que les gains de fastDOOM sont difficiles à expliquer par le seul usage d’un compilateur moderne - Le graphique de taille des fichiers montre qu’au départ, le travail consistait surtout à alléger le code par nettoyage et suppression
Les changements par release qui ont fait grimper les performances
- Exécuter un timedemo sur les 3 042 builds aurait pris environ 9 jours ; le benchmark au niveau du commit s’est donc concentré sur
v0.1,v0.6,v0.8,v0.9.2etv0.9.7, où les gains étaient les plus importants -
fastDOOM v0.1
v0.1comprend 220 commits- Le plus gros patch est e16bab8 du build 36
- La « Crispy optimization » transforme le rendu de la barre d’état en no-op tant que le pourcentage affiché ne change pas, évitant le rendu dans le scrap buffer et le blit vers l’écran
- Ce seul changement apporte 2 fps de plus
- a9359d5 du build 167 inline
FixedDivsous forme de macro - 9bd3f20 du build 207 reprend une optimisation de PSX Doom pour améliorer la traversée BSP
- dc0f48e du build 212 inline la fonction de rendu de surfaces horizontales
R_MakeSpans - Sur l’ensemble des commits, 100 étaient des suppressions, soit environ la moitié en suppression de code
-
fastDOOM v0.6
-
fastDOOM v0.8
v0.8comprend 282 commits- Le système audio étant instable, le timedemo a été effectué sans son puis les fps ont été corrigés
- Cette release se concentrait sur le renderer en mode texte, et les builds 670 et 730 ont subi des régressions avec la disparition de la Crispy optimization
- Principales améliorations
-
fastDOOM v0.9.2 et v0.9.7
v0.9.2compte 110 commits, avec notamment une optimisation de la comparaison skyflatnum, une optimisation deR_DrawColumnpour le Mode Y et un nettoyage du codeR_DrawSpanv0.9.7est présenté comme ayant 293 commits, mais la sortie de commande en affiche 294- Même après plusieurs benchmarks, le bruit n’a pas pu être réduit sur cette release
- Les principaux changements portent sur des tests de modifications ASM x86, la sélection CPU et l’optimisation CR2 pour 386SX, l’optimisation ESP pour
R_DrawSpan386SX, du code basé sur le rendu ASM fuzz column et la suppression d’une comparaison CMP par boucle
Comment choisir entre Mode 13h, Mode Y et VESA direct
- fastDOOM explore de nombreuses optimisations pour différentes combinaisons de CPU et de bus vidéo : 386, 486, Pentium, Cyrix, avec ISA, VLB ou PCI
- Sur l’IBM PS/1 486-DX2 66MHz, l’optimisation utilisant Mode 13h était plus lente que le Mode Y
-
Mode 13h
- Le matériel répartit les données entre les quatre banques de VRAM du VGA, ce qui donne au CPU l’illusion d’un framebuffer linéaire unique en 320x200
- Comme le double buffering n’est pas possible directement en VRAM, il faut bufferiser en RAM puis recopier vers la VRAM, ce qui revient à écrire les octets deux fois
- Le moteur doit se bloquer sur le VSYNC
-
Mode Y
- Les banques VGA étant accessibles individuellement, il permet le triple buffering en VRAM et n’écrit chaque octet qu’une seule fois directement en VRAM
- La sélection de banque nécessite cependant l’instruction lente
OUT - En écrivant simultanément sur deux banques VGA via les latchs, on peut dupliquer horizontalement les pixels et obtenir un mode low-detail
- Le rendu de l’invisible Specter exige une relecture de la VRAM, ce qui est beaucoup plus lent
- D’après l’explication de John Carmack, DOOM utilisait en mode VGA 320×200×256 un mode planaire entrelacé proche du Mode X, avec rotation entre trois pages d’affichage
- Le texture mapping direct en mémoire vidéo pouvait apporter 10 % à 15 % de vitesse supplémentaire sur beaucoup de cartes vidéo
- Cela permettait aussi un page flip sans tearing, contrairement au buffering en mémoire principale
- Heretic est sorti en 1994 et, avec l’évolution du matériel, le Mode 13h est devenu plus attrayant ; Raven a donc orienté le moteur de DOOM dans cette direction
- fastDOOM propose plusieurs exécutables à l’utilisateur
FDOOM.EXEFDOOM13H.EXEFDOOMVBD.EXE
-
Le Mode 13h et VESA direct dans fastDOOM
- En Mode 13h, fastDOOM rend dans un framebuffer linéaire unique en RAM, puis copie la scène entière en VRAM une fois l’image terminée
- Il ne force pas le VSYNC, ce qui peut provoquer du flickering
- Sur un bus ISA 8-bit lent, une copie différentielle n’envoie que les pixels modifiés
- Sur des bus plus rapides, comme ISA 16-bit, VLB ou PCI, le backbuffer complet est copié via
REP MOVS - D’après les tests de Viti95, le meilleur mode sur CPU 486 est le VESA direct mode 320×200 de
FDOOMVBD.EXE- Il combine les avantages du Mode Y avec le code de rendu optimisé de Heretic
- Il évite les instructions
OUT, sauf une fois par frame lors du changement de buffer - Il nécessite une carte graphique VLB ou PCI avec LFB activé et la prise en charge de VESA 2.0 ; il est lent en modes low-detail et potato-detail
- L’IBM 2168 ne prenant pas en charge VESA 2.0, l’exécution de
FDOOMVBP.EXEetFDOOMVBDprovoque une erreur
Les tentatives infructueuses et l’impression d’ensemble
- Les flags processeur spécifiques d’OpenWatcom,
4r/4set3r/3s, ont aussi été essayés avant d’être abandonnés- Les flags 386 et 486 de wcc386 ont tous deux été testés, et au final la version 386 semblait toujours plus rapide
- Viti95 vise aussi un changement de compilateur pour fastDOOM, d’OpenWatcom v2 vers DJGPP, donc GCC
- Il semble en effet que GCC génère un code plus rapide à partir de la même base source
- Une autre possibilité souhaitable serait qu’OpenWatcom v2 progresse pour réduire cet écart de performances
- Les performances de fastDOOM résultent de la réutilisation d’améliorations existantes issues de Crispy, PSX, GBA et Lee Killough, auxquelles s’ajoute une grande quantité de nouvelles optimisations
- Des idées de Ken Silverman et une partie de son code ont aussi été intégrées aux fonctions de rendu pour CPU UMC Green, avec des gains de vitesse importants sur ce matériel
- fastDOOM n’est pas né d’un changement magique unique, mais d’un empilement de milliers de petites optimisations qui ont fini par produire un port DOS plus rapide que le DOOM original
1 commentaires
Commentaires sur Hacker News
C’est un bon exemple qui montre que les goulots d’étranglement ne sont généralement pas là où on les attend, d’où la nécessité de profiler et mesurer
Un rendu en pourcentage dans la barre d’état : pour un expert qui connaît bien l’architecture de Doom, c’était peut-être relativement évident, mais j’aurais sans doute jamais deviné à l’avance que ce serait le goulot d’étranglement
https://www.granola.ai/blog/dont-animate-height
Dans le pire des cas, presque 1/6 de la frame entière servait à afficher le score dans la barre d’état, ce qui abaissait le seuil à partir duquel le jeu ralentissait ; le patch a modifié le stockage et l’affichage du score pour les rendre quasiment en temps constant, et c’était même un peu plus rapide que le meilleur cas précédent
https://www.smwcentral.net/?p=section&a=details&id=35746
Le rendu de l’UI peut être critique à cause de la transparence, du layering, des redraws, et surtout de ce qui déclenche des allocations mémoire ; comparer l’ancienne valeur à la nouvelle avant de redessiner aide beaucoup
J’ai aussi eu un projet en CSS où les couches et la transparence étaient le goulot d’étranglement, et la clé était alors de réduire le nombre de layers
Le chargement est passé de 6 minutes à moins de 2 minutes
https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times...
https://news.ycombinator.com/item?id=10974929
Je ne suis peut-être pas vraiment le public visé, mais le NETDRIVE de mTCP m’a intrigué
Je ne pensais pas qu’il existait déjà à l’époque des options de stockage réseau réellement utilisables, mais en cherchant je suis tombé sur https://www.brutman.com/mTCP/mTCP_NetDrive.html et c’est vraiment excellent
NetDrive est présenté comme un pilote qui permet, depuis DOS, d’accéder à une image disque distante hébergée par une autre machine comme à un périphérique local monté avec une lettre de lecteur
C’était terriblement lent : les élèves perdaient 5 à 10 minutes au début du cours juste pour lancer leur traitement de texte ; le Xerox Alto utilisait aussi des montages réseau pour ses lecteurs
Dès qu’il y a du réseau, quelqu’un veut rapidement copier des fichiers, et le moyen le plus pratique est de faire en sorte que cela ressemble à un système de fichiers local
DOS n’avait pas de réseau intégré, donc il était en retard sur ce point et demandait beaucoup plus de travail manuel
Ça donne un accès en lecture/écriture à un périphérique bloc réseau sans pilote ni configuration côté DOS, mais si on l’utilise comme un partage, ça se casse vite la figure : on est bien plus proche d’un périphérique bloc
Ça semble magique, mais il me semble qu’iPXE patche le BIOS pour rediriger les accès disque vers iSCSI
Il y avait évidemment des choses comme FTP et telnet, mais je me demande si les montages distants étaient réellement utilisés ou si la faible bande passante les rendait impraticables
Le fil GitHub auquel participe Ken Silverman est un vrai trésor
C’est fascinant de voir l’auteur de FastDOOM et Ken plonger dans les subtilités de l’efficacité des registres 486 et des cycles d’horloge
Ça fait plaisir de voir qu’il y a encore des gens pour continuer à améliorer les performances de Doom
Ce scripting a littéralement été ma première forme de « code », et d’une certaine manière je lui dois toute ma carrière et ma situation financière, ce qui est formidable
En particulier, l’idée d’utiliser CR2 et CR3 comme registres scratchpad sur les 386SX, où les accès mémoire sont très lents, et sur les 386DX sans cache, était excellente
La technique qui consiste à utiliser ESP comme compteur de boucle sans désactiver les interruptions est aussi géniale, car elle garantit qu’il pointe toujours vers une position de pile valide
Dans FastDOOM, une fonctionnalité dont on parle peu ici, ce sont toutes sortes de modes vidéo étranges
Mode texte IBM MDA : https://www.youtube.com/watch?v=Op2tr2lGK6Y
EGA & Plantronics ColorPlus : https://www.youtube.com/watch?v=gxx6lJvrITk
Le classique CGA bleu et rose : https://youtu.be/rD0UteHi2qM
CGA 320x200x16 avec le hack « ANSI from Hell » : https://www.youtube.com/watch?v=ut0V1nGcTf8
Hercules : https://www.youtube.com/watch?v=EEumutuyBBo
La plupart semblent tourner plus lentement que le VGA, à cause d'opérations comme le remappage des couleurs
Si je devais le faire tourner en CGA, ça ne m'emballerait pas, et s'il avait encore existé, il aurait probablement fallu un build 286 pour un Tandy 1000 TL/2
Ça me fait penser à la Clean Architecture « moderne » des applications backend
Le passage « IBM PS/1 486-DX2 66Mhz, “Mini-Tower”, model 2168. L'ordinateur dont j'ai toujours rêvé ado mais que je n'ai jamais pu m'offrir » m'a marqué
Vers 1992, j'utilisais déjà mon quatrième PC monté moi-même, et le salon informatique KCS de Marlborough, MA, était une ressource incroyable pour les bidouilleurs
J'achetais des composants, je montais un PC, je l'utilisais un moment, je le revendais, puis je rachetais des pièces
Fin 1992, je faisais tourner un 486-DX3 100 avec un coprocesseur mathématique ULSI 487, et pendant un temps c'était le PC le plus rapide du campus, peut-être même l'ordinateur le plus rapide
Il était plus rapide que plusieurs modèles de Pentium et ne faisait pas d'erreurs de calcul
J'avais justifié ce dernier build pour mon mémoire de fin d'études, parce que les temps de recalcul étaient trop longs pour simuler une centrale de cogénération gaz/diesel dans une feuille Excel de 21 pages
J'avais une spécialisation en sciences de l'environnement, mais toute ma carrière s'est finalement faite dans l'informatique
Est-ce qu'il fallait vraiment en remettre une couche à quelqu'un qui ne pouvait pas se payer un tel ordinateur en 1992 ?
En plus, il n'y a jamais eu de « DX3 », et le premier 486 à 100 MHz, le DX4, est sorti en mars 1994, donc dire qu'il l'utilisait fin 1992 ne semble pas crédible
Le premier ordinateur de notre foyer, si on exclut un XT déjà totalement dépassé qu'on nous a donné vers 1992, c'était un 486-DX2 66 MHz acheté début 1995
Même des décennies plus tard, ça me pique encore un peu l'ego de voir quelqu'un se vanter bizarrement d'un ordinateur impossible, plus rapide que le mien malgré trois ans de handicap
Vers 1992, j'étais un étudiant fauché et j'ai emprunté environ 2 000 dollars à la coopérative de crédit pour acheter un 486 DX2-50
En monnaie d'aujourd'hui, ça ferait plus de 4 000 dollars pour un ordinateur assez basique, et je faisais un dual boot DOS/Linux dessus
Après vérification, le 487 standard était en fait un 486DX complet qui désactivait et remplaçait le 486SX d'origine
C'était peut-être un autre coprocesseur fabuleux dont je n'avais jamais entendu parler
Il les avait complètement surclassés
Au-delà de la fréquence des releases, Viti95 a montré une excellente discipline Git : un commit ne fait qu'une seule chose et chaque release est taguée
https://fabiensanglard.net/fastdoom/#:~:text=one%20commit%20...
Dans « avant de connaître fastDOOM, je m'étais résigné à jouer sous Ibuprofen », je ne vois pas ce que veut dire Ibuprofen
Si l'auteur lit ceci, il y a une faute dans tout le document : le nom de famille de John Carmack est écrit « Carnmack »
Si on veut expliquer sans cynisme pourquoi les logiciels modernes sont lents et n'intègrent pas ce genre d'optimisations, il y a l'hypothèse standardisation/optimisation
Une fois qu'une chose devient un standard, l'optimisation suit
Parce qu'on veut être le plus rapide tout en passant tous les tests du standard
Doom est désormais lui aussi devenu un jeu standard à porter partout, que ce soit sur un nouveau CPU ou un grille-pain, et c'est un peu pareil pour les protocoles d'e-mail ou les standards de navigateur comme WebRTC et QUIC
Si les applis web modernes ou les applis Electron ne sont pas rapides, c'est parce qu'elles sont encore en phase d'exploration
Elles sont mises à jour chaque jour pour répondre à de nouvelles demandes des utilisateurs, et côté performances il suffit qu'elles soient assez rapides pour ne pas gêner
C'est pour ça que les applis IRC sont très rapides, alors que Slack et Teams sont condamnés à rester lents
Revenir en arrière sur les versions pour vérifier les améliorations et les régressions, ce n'est pas anodin
Certaines optimisations peuvent introduire des bugs découverts plus tard, et des fonctionnalités indispensables peuvent aussi faire baisser les performances
Avoir des tests de performance lancés automatiquement avant chaque release rend donc la vie plus simple, et si un problème de performance est détecté, on peut alors écrire un test de régression comme d'habitude
En gros, ce que je veux dire, c'est : faites des tests de performance