fastDOOM इतना तेज़ क्यों है
(fabiensanglard.net)- 1993 के high-performance PC-क्लास IBM PS/1 486-DX2 66MHz पर original DOOM
demo1के आधार पर 21.5fps था, जबकि fastDOOM समान शर्तों में 30.1fps तक पहुंचा, जो DOS port optimization का अंतर दिखाता है - fastDOOM की शुरुआत PCDOOM v2 से हुई, जिसमें Linux DOOM core, Heretic I/O, APODMX और
DOOM.EXEdisassembly पर आधारित Mode Y graphics I/O को जोड़ा गया था - 52 releases और 3,042 commits को build व benchmark करने पर पता चला कि performance gain किसी एक modern compiler से नहीं, बल्कि छोटे optimizations के accumulated effect से आया
- बड़े improvements में status bar rendering skip करना,
FixedDivको inline करना, BSP traversal optimization, visplane rendering skip करना, pointer indirect reference हटाना, और renderer-specific executables को अलग करना शामिल था - Graphics mode में फायदा/नुकसान CPU और bus पर निर्भर करता है; धीमे CPU में Mode Y बेहतर है, और तेज़ CPU व VLB/PCI environment में Mode 13h या VESA direct बेहतर हो सकते हैं, लेकिन VESA 2.0 जैसी constraints बची रहती हैं
486-DX2 पर दिखा performance gap
- IBM PS/1 486-DX2 66MHz “Mini-Tower” model 2168 पर original DOOM को
doom.exe -timedemo demo1से चलाने पर1710 gametics in 2783 realticsमिलता है- DOOM सीधे fps output नहीं करता, इसलिए
1710/2783*35से calculate करना पड़ता है; result 21.5fps है
- DOOM सीधे fps output नहीं करता, इसलिए
- उसी machine पर
fdoom.exe -timedemo demo1चलाने पर1710 gametics in 1988 realtics, यानी 30.1fps confirm होता है doom2केdemo1जैसे ज्यादा heavy map में original 16.8fps से fastDOOM 24.9fps तक पहुंचता है, यानी 48% तेज़- हालांकि joystick और network gameplay support हटा दिया गया है, इसलिए यह ऐसा port नहीं है जो सभी features को ज्यों का त्यों preserve करता हो
fastDOOM की code lineage
- DOOM मूल रूप से NeXT Workstation पर develop किया गया था, और यह ज्यादातर core code व छोटे I/O subsystem में बंटा था, जिससे इसकी porting-friendly structure बनी
- Commercial DOS version ने id Software द्वारा लिखा गया DOS I/O इस्तेमाल किया, लेकिन proprietary sound library DMX dependency के कारण 1997 में उसे वैसा का वैसा open source नहीं किया जा सका
- Public किया गया code Bernd Kreimeier द्वारा engine explanation book project के दौरान整理 किया गया Linux version था
- DOS version PCDOOM v2 को इस combination से reconstruct किया गया
- Linux DOOM का core
- Heretic का I/O
- DMX की नकल करने के लिए APODMX
DOOM.EXEdisassembly से reverse-engineeredi_ibm.cgraphics I/O
- fastDOOM ने इसी PCDOOM v2 को starting point बनाया
Releases और commits से track किया गया performance change
- Victor “Viti95” Nieto ने fastDOOM को frequent releases दिए और हर release को tag किया, साथ ही एक commit को एक काम तक सीमित रखने का discipline रखा
- fastDOOM का Git history 3,042 commits से बना है, जिससे commit-by-commit performance changes track किए जा सके
- 52 fastDOOM releases, PCDOOM v2 और original
DOOM.EXEdownload करके-timedemo demo1चलाने वालाRUN.BATGo program से generate किया गया, और mTCPNETDRIVEसे mount करके test किया गया- Conditions थीं
DOOM.WAD, sound on, screen size 10 - पूरी suite को 5 बार run करके average fps को graph में plot किया गया
- Conditions थीं
- PCDOOM v2 OpenWatcom 2 से build होने के बावजूद original
DOOM.EXEकी तुलना में बड़ा improvement नहीं दिखाता, इसलिए fastDOOM का gain सिर्फ modern compiler usage से समझाना मुश्किल है - File size graph में शुरुआती काम code cleanup और deletion के जरिए उसे हल्का बनाने की दिशा में था
Performance बढ़ाने वाले release-wise changes
- सभी 3,042 builds को timedemo करने में करीब 9 दिन लग सकते थे, इसलिए जिनमें speed gains बड़े थे, उन
v0.1,v0.6,v0.8,v0.9.2,v0.9.7पर focused commit-level benchmarking की गई -
fastDOOM v0.1
v0.1220 commits से बना है- सबसे बड़ा patch build 36 का e16bab8 है
- “Crispy optimization” status bar percentage नहीं बदलने पर rendering को no-op बना देता है, जिससे scrap buffer rendering और screen blit बचते हैं
- सिर्फ इस change से 2fps की बढ़ोतरी confirm हुई
- build 167 के a9359d5 ने
FixedDivको macro के रूप में inline किया - build 207 के 9bd3f20 ने PSX Doom optimization लाकर BSP traversal method सुधारा
- build 212 के dc0f48e ने horizontal surface rendering function
R_MakeSpansको inline किया - कुल commits में deletion commits 100 थे, यानी करीब आधे code deletion थे
-
fastDOOM v0.6
-
fastDOOM v0.8
v0.8282 commits से बना है- sound system unstable था, इसलिए timedemo बिना sound के चलाकर fps adjust किया गया
- यह release text-mode renderer पर focused था, और build 670 व build 730 में Crispy optimization हटने से regression आया
- मुख्य improvements इस प्रकार हैं
-
fastDOOM v0.9.2 और v0.9.7
v0.9.2110 commits वाला है; skyflatnum comparison optimization, Mode Y के लिएR_DrawColumnoptimization, औरR_DrawSpancode cleanup इसके मुख्य changes हैंv0.9.7को 293 commits के रूप में introduce किया गया, लेकिन command output 294 दिखाता है- इस release में कई बार benchmark करने पर भी noise कम नहीं हो सका
- मुख्य changes में x86 ASM change tests, 386SX के लिए CPU selection और CR2 optimization,
R_DrawSpan386SXके लिए ESP optimization, ASM fuzz column rendering-based code, और per-loop CMP comparison हटाना शामिल हैं
Mode 13h, Mode Y, VESA direct चुनने के criteria
- fastDOOM 386, 486, Pentium, Cyrix और ISA, VLB, PCI जैसी अलग-अलग CPU-video bus combinations के लिए कई optimizations explore करता है
- IBM PS/1 486-DX2 66MHz पर Mode Y के बजाय Mode 13h इस्तेमाल करने वाला optimization धीमा था
-
Mode 13h
- VGA के चार VRAM banks में data distribute करने का काम hardware करता है, इसलिए CPU को यह single linear 320x200 framebuffer जैसा दिखता है
- VRAM में double buffering नहीं की जा सकती, इसलिए RAM में buffering करने के बाद उसे फिर VRAM में copy करना पड़ता है, यानी bytes दो बार लिखे जाते हैं
- Engine को VSYNC पर block होना पड़ता है
-
Mode Y
- VGA banks को individually access किया जा सकता है, जिससे VRAM triple buffering संभव है, और bytes सीधे VRAM में सिर्फ एक बार लिखे जा सकते हैं
- Bank selection के लिए धीमा
OUTcommand चाहिए - latch के जरिए दो VGA banks में simultaneously लिखने पर horizontal pixel replication संभव है, जिससे low-detail mode मिलता है
- invisible Specter rendering को VRAM readback चाहिए, इसलिए यह काफी धीमा है
- John Carmack के explanation के अनुसार DOOM ने 320×200×256 VGA mode में Mode X जैसा interleaved planar mode इस्तेमाल किया और तीन display pages को rotate किया
- video memory में directly texture mapping करने से कई video cards पर 10%~15% extra speed मिल सकती थी
- main memory buffering की तुलना में tearing-free page flip भी संभव था
- Heretic 1994 में release हुआ, और उस समय hardware changes के कारण Mode 13h ज्यादा attractive choice बन गया, इसलिए Raven ने DOOM engine को इसी दिशा में modify किया
- fastDOOM users को कई executables देता है
FDOOM.EXEFDOOM13H.EXEFDOOMVBD.EXE
-
fastDOOM का Mode 13h और VESA direct
- fastDOOM का Mode 13h RAM के single framebuffer में render करता है और पूरा scene खत्म होने पर उसे VRAM में copy करता है
- VSYNC force नहीं करता, जिससे flickering हो सकती है
- धीमे 8-bit ISA bus पर सिर्फ बदले हुए pixels भेजने वाली differential copy इस्तेमाल होती है
- 16-bit ISA, VLB, PCI जैसे तेज़ bus पर
REP MOVSसे पूरा backbuffer copy किया जाता है - Viti95 के tests के अनुसार 486 CPU के लिए सबसे अच्छा mode 320×200 के लिए VESA direct mode
FDOOMVBD.EXEहै- यह Mode Y के advantages और Heretic के optimized rendering code को combine करता है
- Buffer switch करते समय प्रति frame एक
OUTको छोड़करOUTcommands से बचता है - LFB enabled VLB या PCI graphics card और VESA 2.0 support चाहिए, और low-detail व potato-detail mode में धीमा है
- IBM 2168 VESA 2.0 support नहीं करता, इसलिए
FDOOMVBP.EXEऔरFDOOMVBDचलाने पर error आता है
जो कोशिशें काम नहीं आईं और overall impression
- OpenWatcom के processor-specific flags
4r/4sऔर3r/3sभी try किए गए, लेकिन बंद कर दिए गए- wcc386 के 386 flags और 486 flags दोनों try किए गए, और नतीजे में 386 version हमेशा तेज़ दिखा
- Viti95 का लक्ष्य fastDOOM के compiler को OpenWatcom v2 से DJGPP, यानी GCC, में बदलना भी है
- क्योंकि उसी source से GCC तेज़ code generate करता दिखा
- या OpenWatcom v2 का performance gap घटाने के लिए improve होना भी एक desirable option बना हुआ है
- fastDOOM की performance Crispy, PSX, GBA, Lee Killough के existing improvements का उपयोग करने और बड़ी मात्रा में नए optimizations जोड़ने का result है
- Ken Silverman के ideas और code के कुछ हिस्से भी UMC Green CPU के rendering functions में गए, जिससे उस hardware पर बड़ा speed gain मिला
- fastDOOM कोई एक जादुई बदलाव नहीं, बल्कि हजारों छोटे optimizations के जमा होने से original DOOM से तेज़ बना DOS port है
1 टिप्पणियां
Hacker News टिप्पणियां
यह इस बात का अच्छा उदाहरण है कि bottleneck आम तौर पर वहां नहीं होता जहां आप उम्मीद करते हैं, इसलिए profiling और measurement ज़रूरी हैं
status bar में percentage rendering—Doom की संरचना को अच्छी तरह जानने वाले विशेषज्ञ के लिए शायद यह अपेक्षाकृत स्पष्ट रहा हो, लेकिन पहले से इसे bottleneck मानना बिल्कुल मुश्किल लगता
https://www.granola.ai/blog/dont-animate-height
सबसे खराब स्थिति में status bar पर score दिखाने में पूरे frame का लगभग 1/6 लग जाता था, जिससे slow होने की threshold कम हो गई थी; patch ने score को store और display करने का तरीका लगभग constant time जैसा बना दिया, और इसे पुराने best case से भी थोड़ा तेज़ कर दिया
https://www.smwcentral.net/?p=section&a=details&id=35746
transparency, layering, redraw, खासकर memory allocation trigger होने की वजह से UI rendering घातक हो सकती है, और redraw से पहले पुराने और नए value की तुलना करना काफी मदद करता है
CSS में भी एक project में layers और transparency bottleneck थे, और तब मुख्य बात layer count कम करना था
6 मिनट की loading को 2 मिनट से कम कर दिया गया
https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times...
https://news.ycombinator.com/item?id=10974929
शायद मैं इसका वास्तविक target audience नहीं हूं, लेकिन mTCP का NETDRIVE दिलचस्प लगा
मुझे नहीं पता था कि इतने पुराने समय में भी इस्तेमाल लायक network storage options रहे होंगे, लेकिन खोजने पर https://www.brutman.com/mTCP/mTCP_NetDrive.html मिला, जो सच में शानदार है
कहा जाता है कि NetDrive एक device driver है जो किसी दूसरी machine द्वारा host की गई remote disk image को DOS में drive letter से जुड़े local device की तरह access करने देता है
यह बेहद धीमा था, इसलिए students class की शुरुआत में word processor खोलने में 5–10 मिनट गंवा देते थे, और Xerox Alto भी drives के लिए network mounts इस्तेमाल करता था
अगर networking है तो कोई न कोई जल्द ही files copy करना चाहेगा, और सबसे आसान तरीका है उसे local filesystem जैसा दिखाना
DOS में built-in networking नहीं थी, इसलिए वह इस मामले में पीछे था और काफी कुछ खुद करना पड़ता था
DOS-side driver या configuration के बिना network block device पर read/write access मिल जाता है, लेकिन इसे share की तरह इस्तेमाल करें तो यह जल्दी टूट जाता है और block device के ज्यादा करीब है
यह जादू जैसा लगता है, लेकिन शायद iPXE BIOS को patch करके disk access को iSCSI पर भेजता है
FTP और telnet जैसी चीजें तो जाहिर है रही होंगी, लेकिन remote mount सच में इस्तेमाल होते थे या कम bandwidth की वजह से असंभव थे—यह जानने की जिज्ञासा है
Ken Silverman वाला GitHub thread किसी खजाने जैसा है
FastDOOM के author और Ken को मुश्किल 486 registers और clock cycle efficiency में गहराई तक जाते देखना कमाल है
अच्छा लगता है कि कोई अब भी Doom की performance improvements का ध्यान रख रहा है
वह scripting सचमुच मेरी पहली “coding” थी, और एक तरह से मैं अपना career और पूरी संपत्ति KenS का ऋणी मानता हूं—यह शानदार है
खासकर memory access बहुत धीमा होने वाले 386SX और cache-less 386DX पर CR2 और CR3 को scratchpad registers की तरह इस्तेमाल करने का idea अच्छा लगा
interrupts बंद किए बिना ESP को loop counter की तरह इस्तेमाल करने की technique भी genius है, जिसमें यह सुनिश्चित किया जाता है कि वह हमेशा valid stack location की ओर ही point करे
FastDOOM में यहाँ जिस feature पर ज़्यादा बात नहीं हुई, वह है हर तरह के अजीब video modes
IBM MDA text mode: https://www.youtube.com/watch?v=Op2tr2lGK6Y
EGA & Plantronics ColorPlus: https://www.youtube.com/watch?v=gxx6lJvrITk
क्लासिक नीला-गुलाबी CGA: https://youtu.be/rD0UteHi2qM
‘ANSI from Hell’ hack इस्तेमाल करने वाला CGA 320x200x16: https://www.youtube.com/watch?v=ut0V1nGcTf8
Hercules: https://www.youtube.com/watch?v=EEumutuyBBo
लगता है ज़्यादातर VGA से भी धीमे चलते हैं, शायद color remapping जैसे कामों की वजह से
अगर CGA पर चलाना पड़े तो मुझे पसंद नहीं आएगा, और अगर वह अभी भी ज़िंदा होता तो शायद Tandy 1000 TL/2 के लिए 286 build चाहिए होता
backend applications की “modern” Clean Architecture याद आती है
“IBM PS/1 486-DX2 66Mhz, ‘Mini-Tower’, model 2168. किशोर उम्र में जिस computer को मैं हमेशा चाहता था, लेकिन खरीद नहीं सकता था” वाला हिस्सा प्रभावशाली लगा
1992 के आसपास मैं अपना खुद assembled चौथा PC इस्तेमाल कर रहा था, और Marlborough MA का KCS computer show tinkerers के लिए जबरदस्त resource था
parts खरीदकर PC बनाता, कुछ समय इस्तेमाल करता, फिर बेच देता, और फिर parts खरीदता था
1992 के अंत तक मैं ULSI 487 math coprocessor लगे 486-DX3 100 पर चल रहा था, और कुछ समय तक वह campus का सबसे तेज़ PC, शायद सबसे तेज़ computer भी कहा जा सकता था
वह कई Pentium models से तेज़ था और math errors भी नहीं देता था
आख़िरी build को मैंने अपनी honours thesis के लिए justify किया था, क्योंकि gas/diesel cogeneration plant को 21-page Excel spreadsheet में simulate करने पर recalculation time बहुत लंबा हो रहा था
major Environmental Science था, लेकिन career पूरी तरह computers में चला गया
क्या 1992 में ऐसा computer afford न कर पाने वाले व्यक्ति को यूँ चुभाना ज़रूरी था
ऊपर से “DX3” नाम की कोई चीज़ नहीं थी, और पहला 100MHz 486 यानी DX4 मार्च 1994 में आया, इसलिए 1992 के अंत में इसे चलाने की बात सही नहीं लगती
हमारे घर का पहला computer, 1992 के आसपास मिले पहले से ही बहुत पुराने XT को छोड़ दें, तो 1995 की शुरुआत में खरीदा गया 66MHz 486-DX2 था
दशकों बाद भी, 3 साल का handicap होने के बावजूद मेरे computer से तेज़ बताई जा रही उस असंभव machine की अजीब शेख़ी देखकर बेवजह अहं को ठेस लगती है
1992 के आसपास मैं गरीब college student था और credit union से करीब 2,000 dollars loan लेकर 486 DX2-50 खरीदा था
आज के पैसों में देखें तो एक काफ़ी basic computer पर 4,000 dollars से ज़्यादा खर्च किए थे, और उस पर DOS और Linux dual boot करता था
खोजने पर पता चला कि standard 487 असल में पूरा 486DX था, जो मूल 486SX को disable करके replace करता था
क्या यह कोई और शानदार coprocessor था जिसके बारे में मुझे पता नहीं था
उसने ठीक से धूल चटा दी थी
बार-बार releases करने के अलावा, Viti95 ने बेहतरीन Git discipline दिखाया: एक commit एक काम करता है और हर release को tag किया गया था
https://fabiensanglard.net/fastdoom/#:~:text=one%20commit%20...
“fastDOOM जानने से पहले मैंने मान लिया था कि खेलते समय Ibuprofen लेना पड़ेगा” में Ibuprofen का क्या मतलब है, समझ नहीं आया
अगर लेखक यह देखे, तो पूरे document में John Carmack के surname की spelling “Carnmack” गलत लिखी है
अगर cynicism के बिना देखें कि modern software धीमा क्यों है और ऐसी optimizations क्यों नहीं लगतीं, तो इसे standardization/optimization hypothesis से समझाया जा सकता है
कोई चीज़ standard बन जाती है तो optimization उसके पीछे आती है
क्योंकि सभी standard tests pass करते हुए सबसे तेज़ होना चाहेंगे
Doom भी अब ऐसा standard game बन गया है जिसे नए CPU से लेकर toaster तक हर जगह port किया जाता है, और email protocols या browser standards जैसे WebRTC, QUIC आदि भी ऐसे ही हैं
modern web apps या Electron apps तेज़ इसलिए नहीं हैं क्योंकि वे exploration phase में हैं
वे हर दिन नई user requirements के हिसाब से update होते हैं, और performance के मामले में इतना तेज़ होना ही काफ़ी है कि बाधा न बने
इसलिए IRC apps बहुत तेज़ हैं, लेकिन Slack और Teams हमेशा धीमे ही रहने वाले हैं
versions में पीछे जाकर improvements और regressions देखना मामूली काम नहीं है
कुछ optimizations बाद में मिलने वाले bugs बना सकती हैं, और कोई ज़रूरी feature performance गिरा सकता है
इसलिए हर release से पहले अपने-आप चलने वाले performance tests हों तो ज़िंदगी आसान हो जाती है, और performance problem मिलने पर हमेशा की तरह regression test लिख सकते हैं
कहना यही है कि performance testing कीजिए