Vì sao fastDOOM chạy nhanh
(fabiensanglard.net)- Trên IBM PS/1 486-DX2 66MHz, một PC hiệu năng cao năm 1993, DOOM gốc đạt 21,5fps với
demo1, còn fastDOOM đạt 30,1fps trong cùng điều kiện, cho thấy khác biệt trong tối ưu hóa bản port DOS - fastDOOM bắt đầu từ PCDOOM v2, kết hợp lõi Linux DOOM, I/O của Heretic, APODMX và I/O đồ họa Mode Y dựa trên dịch ngược assembly của
DOOM.EXE - Kết quả build và benchmark 52 bản phát hành cùng 3.042 commit cho thấy mức tăng hiệu năng không đến từ một compiler hiện đại duy nhất, mà từ sự tích lũy của các tối ưu hóa nhỏ
- Các cải thiện lớn gồm bỏ qua render thanh trạng thái, inline
FixedDiv, tối ưu duyệt BSP, bỏ qua render visplane, loại bỏ tham chiếu gián tiếp qua pointer, và tách file thực thi theo từng renderer - Chế độ đồ họa có lợi hay bất lợi tùy CPU và bus; với CPU chậm thì Mode Y có lợi, còn trong môi trường CPU nhanh và VLB/PCI thì Mode 13h hoặc VESA direct có thể tốt hơn, nhưng vẫn còn các ràng buộc như VESA 2.0
Khác biệt hiệu năng lộ rõ trên 486-DX2
- Khi chạy DOOM gốc bằng
doom.exe -timedemo demo1trên mẫu IBM PS/1 486-DX2 66MHz “Mini-Tower” 2168, kết quả là1710 gametics in 2783 realtics- DOOM không xuất fps trực tiếp, nên phải tính bằng
1710/2783*35; kết quả là 21,5fps
- DOOM không xuất fps trực tiếp, nên phải tính bằng
- Trên cùng máy đó, chạy
fdoom.exe -timedemo demo1cho kết quả1710 gametics in 1988 realtics, xác nhận 30,1fps - Với các map nặng hơn như
demo1củadoom2, tốc độ tăng từ 16,8fps của bản gốc lên 24,9fps của fastDOOM, nhanh hơn 48% - Tuy nhiên, hỗ trợ joystick và network gameplay đã bị loại bỏ, nên đây không phải là bản port giữ nguyên toàn bộ chức năng
Dòng phả hệ mã nguồn tạo ra fastDOOM
- DOOM ban đầu được phát triển trên NeXT Workstation, và có cấu trúc dễ port khi phần lớn mã lõi được tách khỏi một hệ thống con I/O nhỏ
- Bản DOS thương mại dùng DOS I/O do id Software viết, nhưng do phụ thuộc vào DMX, một proprietary sound library, nên không thể được open-source nguyên trạng vào năm 1997
- Mã được công bố là phiên bản Linux do Bernd Kreimeier chỉnh lý trong lúc thực hiện dự án sách giải thích engine
- Phiên bản DOS PCDOOM v2 được tái cấu trúc từ tổ hợp sau
- Lõi của Linux DOOM
- I/O của Heretic
- APODMX để mô phỏng DMX
- I/O đồ họa
i_ibm.cđược reverse-engineer từ bản dịch ngược assembly củaDOOM.EXE
- fastDOOM lấy chính PCDOOM v2 này làm điểm xuất phát
Theo dõi thay đổi hiệu năng qua release và commit
- Victor “Viti95” Nieto phát hành fastDOOM thường xuyên, gắn tag cho từng release, và quản lý sao cho một commit làm một việc
- Lịch sử Git của fastDOOM gồm 3.042 commit, nhờ đó có thể theo dõi thay đổi hiệu năng theo từng commit
- 52 bản phát hành fastDOOM, PCDOOM v2 và
DOOM.EXEgốc được tải về; một chương trình Go tạoRUN.BATđể chạy-timedemo demo1, rồi mount bằng mTCPNETDRIVEđể kiểm thử- Điều kiện là
DOOM.WAD, bật sound, screen size 10 - Toàn bộ bộ test được chạy 5 lần và fps trung bình được vẽ thành biểu đồ
- Điều kiện là
- Dù PCDOOM v2 được build bằng OpenWatcom 2, mức cải thiện so với
DOOM.EXEgốc không lớn, nên khó giải thích mức tăng của fastDOOM chỉ bằng việc dùng compiler hiện đại - Biểu đồ kích thước file cho thấy công việc ban đầu hướng tới làm nhẹ hơn bằng cách dọn dẹp và xóa mã
Các thay đổi theo release đã kéo hiệu năng lên
- Nếu timedemo toàn bộ 3.042 build, có thể mất khoảng 9 ngày, nên benchmark theo từng commit được thực hiện chủ yếu quanh các bản có mức tăng tốc lớn:
v0.1,v0.6,v0.8,v0.9.2,v0.9.7 -
fastDOOM v0.1
v0.1gồm 220 commit- Patch lớn nhất là e16bab8 ở build 36
- “Crispy optimization” biến việc render thành no-op khi phần trăm trên thanh trạng thái không đổi, tránh render scrap buffer và blit lên màn hình
- Chỉ riêng thay đổi này đã được xác nhận làm tăng 2fps
- a9359d5 ở build 167 inline
FixedDivthành macro - 9bd3f20 ở build 207 đưa tối ưu từ PSX Doom vào để cải thiện cách duyệt BSP
- dc0f48e ở build 212 inline hàm render bề mặt ngang
R_MakeSpans - Trong toàn bộ commit, có 100 commit xóa mã, tức khoảng một nửa là xóa code
-
fastDOOM v0.6
-
fastDOOM v0.8
v0.8gồm 282 commit- Do sound system không ổn định, timedemo được chạy không có sound rồi hiệu chỉnh fps
- Release này tập trung vào text-mode renderer, và đã xảy ra hồi quy khi Crispy optimization bị bỏ ở build 670 và build 730
- Các cải thiện chính như sau
-
fastDOOM v0.9.2 và v0.9.7
v0.9.2có 110 commit; các thay đổi chính là tối ưu so sánh skyflatnum, tối ưuR_DrawColumncho Mode Y, và dọn dẹp mãR_DrawSpanv0.9.7được giới thiệu là có 293 commit, nhưng output lệnh cho thấy 294 commit- Dù benchmark release này nhiều lần, vẫn không thể giảm nhiễu
- Các thay đổi chính gồm thử nghiệm thay đổi x86 ASM, lựa chọn CPU cho 386SX và tối ưu CR2, tối ưu ESP cho
R_DrawSpan386SX, mã dựa trên ASM fuzz column rendering, loại bỏ phép so sánh CMP trong mỗi vòng lặp, v.v.
Tiêu chí chọn Mode 13h, Mode Y và VESA direct
- fastDOOM khám phá nhiều tối ưu hóa cho các tổ hợp CPU và video bus đa dạng như 386, 486, Pentium, Cyrix cùng ISA, VLB, PCI
- Trên IBM PS/1 486-DX2 66MHz, tối ưu dùng Mode 13h thay cho Mode Y lại chậm hơn
-
Mode 13h
- Phần cứng xử lý việc phân phối dữ liệu vào bốn VRAM bank của VGA, nên với CPU nó trông như một framebuffer tuyến tính 320x200 duy nhất
- Không thể double buffering trong VRAM, nên phải buffer trong RAM rồi chép lại sang VRAM, tức ghi byte hai lần
- Engine phải bị block ở VSYNC
-
Mode Y
- Có thể truy cập riêng từng VGA bank, cho phép VRAM triple buffering, và có thể ghi byte trực tiếp vào VRAM chỉ một lần
- Việc chọn bank cần lệnh
OUTchậm - Nếu ghi đồng thời vào hai VGA bank thông qua latch, có thể sao chép pixel theo chiều ngang để có low-detail mode
- Render Specter vô hình cần readback từ VRAM nên chậm hơn nhiều
- Theo giải thích của John Carmack, DOOM dùng một interleaved planar mode tương tự Mode X trong chế độ VGA 320×200×256, và luân phiên ba display page
- Texture mapping trực tiếp vào video memory có thể mang lại thêm 10%~15% tốc độ trên nhiều video card
- Page flip không bị tearing cũng khả thi hơn so với buffering trong main memory
- Heretic ra mắt năm 1994, và do thay đổi phần cứng thời đó khiến Mode 13h trở thành lựa chọn hấp dẫn hơn, Raven đã sửa DOOM engine theo hướng này
- fastDOOM cung cấp cho người dùng nhiều file thực thi
FDOOM.EXEFDOOM13H.EXEFDOOMVBD.EXE
-
Mode 13h và VESA direct của fastDOOM
- Mode 13h của fastDOOM render vào một framebuffer duy nhất trong RAM, rồi sao chép sang VRAM sau khi toàn bộ cảnh hoàn tất
- Không ép VSYNC, nên có thể xuất hiện flickering
- Trên bus ISA 8-bit chậm, differential copy chỉ truyền các pixel đã thay đổi được dùng
- Trên các bus nhanh hơn như ISA 16-bit, VLB, PCI, toàn bộ backbuffer được sao chép bằng
REP MOVS - Theo các thử nghiệm của Viti95, chế độ tốt nhất cho CPU 486 là
FDOOMVBD.EXE, tức VESA direct mode cho 320×200- Kết hợp ưu điểm của Mode Y với mã render đã tối ưu của Heretic
- Tránh lệnh
OUT, ngoại trừ một lầnOUTmỗi frame khi chuyển buffer - Cần card đồ họa VLB hoặc PCI có LFB được bật và hỗ trợ VESA 2.0; chậm trong low-detail và potato-detail mode
- IBM 2168 không hỗ trợ VESA 2.0, nên sẽ phát sinh lỗi khi chạy
FDOOMVBP.EXEvàFDOOMVBD
Những thử nghiệm không hiệu quả và ấn tượng tổng thể
- Các flag theo từng bộ xử lý của OpenWatcom là
4r/4svà3r/3scũng đã được thử, nhưng bị dừng lại- Cả flag 386 và flag 486 của wcc386 đều được thử, và kết quả là phiên bản 386 luôn có vẻ nhanh hơn
- Viti95 cũng có mục tiêu đổi compiler của fastDOOM từ OpenWatcom v2 sang DJGPP, tức GCC
- Lý do là trên cùng source, GCC cho thấy tạo ra mã nhanh hơn
- Hoặc việc OpenWatcom v2 được cải thiện để thu hẹp khoảng cách hiệu năng cũng vẫn là một lựa chọn đáng mong muốn
- Hiệu năng của fastDOOM là kết quả của việc tận dụng các cải tiến có sẵn từ Crispy, PSX, GBA, Lee Killough và bổ sung hàng loạt tối ưu hóa mới
- Ý tưởng và một phần mã của Ken Silverman cũng được đưa vào các hàm render cho UMC Green CPU, tạo ra mức tăng tốc lớn trên phần cứng đó
- fastDOOM không phải là kết quả của một thay đổi ma thuật duy nhất, mà là ví dụ về một bản port DOS nhanh hơn DOOM gốc nhờ hàng nghìn tối ưu hóa nhỏ tích lũy
1 bình luận
Ý kiến trên Hacker News
Đây là một ví dụ hay cho thấy nút thắt thường không nằm ở nơi ta dự đoán, nên cần profiling và đo đạc
Việc render phần trăm trên thanh trạng thái nghe có vẻ khá hiển nhiên với một chuyên gia hiểu rõ cấu trúc của Doom, nhưng trước đó chắc hẳn không ai đoán nó là nút thắt
https://www.granola.ai/blog/dont-animate-height
Trong trường hợp tệ nhất, việc hiển thị điểm trên thanh trạng thái dùng gần 1/6 toàn bộ frame, khiến ngưỡng bắt đầu bị chậm thấp hơn; bản vá đã đổi cách lưu và hiển thị điểm thành gần như thời gian hằng số, thậm chí còn nhanh hơn một chút so với trường hợp tốt nhất trước đây
https://www.smwcentral.net/?p=section&a=details&id=35746
Render UI có thể gây chết người vì độ trong suốt, layering, vẽ lại, đặc biệt là do kích hoạt cấp phát bộ nhớ; cách so sánh giá trị cũ và mới trước khi vẽ lại giúp ích rất nhiều
Trong CSS cũng từng có dự án mà layer và độ trong suốt là nút thắt, khi đó điểm mấu chốt là giảm số lượng layer
Họ đã giảm thời gian tải 6 phút xuống dưới 2 phút
https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times...
https://news.ycombinator.com/item?id=10974929
Có lẽ tôi không phải độc giả mục tiêu thật sự, nhưng NETDRIVE của mTCP khá thú vị
Tôi không ngờ từ thời xa xưa như vậy đã có lựa chọn network storage dùng được; tìm thử thì thấy https://www.brutman.com/mTCP/mTCP_NetDrive.html, thật sự rất hay
NetDrive được nói là một device driver cho phép DOS truy cập image đĩa từ xa do máy khác host như một thiết bị cục bộ gắn với drive letter
Nó chậm khủng khiếp, khiến học sinh mất 5–10 phút đầu giờ chỉ để mở trình xử lý văn bản; Xerox Alto cũng dùng network mount cho drive
Khi đã có networking, chẳng mấy chốc sẽ có người muốn sao chép file, và cách tiện nhất là làm cho nó trông như filesystem cục bộ
DOS không có networking tích hợp nên tụt hậu ở mảng này, và phải tự làm rất nhiều thứ
Nó cho phép truy cập đọc/ghi vào thiết bị block qua mạng mà không cần driver hay cấu hình phía DOS, nhưng nếu dùng như share thì sẽ hỏng rất nhanh, vì nó gần với block device hơn
Nghe như phép thuật, nhưng có vẻ iPXE patch BIOS để chuyển truy cập đĩa sang iSCSI
Những thứ như FTP và telnet thì chắc chắn có, nhưng tôi muốn biết remote mount có thực sự được dùng không, hay là bất khả thi vì băng thông thấp
Thread GitHub có Ken Silverman tham gia đúng là một kho báu
Thật đáng kinh ngạc khi thấy tác giả FastDOOM và Ken đào sâu vào các thanh ghi 486 khó hiểu và hiệu quả chu kỳ clock
Thật vui khi vẫn có người chăm chút để Doom tiếp tục được cải thiện hiệu năng
Phần scripting đó đúng nghĩa là lần “lập trình” đầu tiên của tôi, và theo một nghĩa nào đó, tôi nợ KenS toàn bộ sự nghiệp và tài sản của mình, thật tuyệt
Tôi đặc biệt thích ý tưởng dùng CR2 và CR3 như các thanh ghi scratchpad trên 386SX, nơi truy cập bộ nhớ rất chậm, và 386DX không có cache
Kỹ thuật dùng ESP làm bộ đếm vòng lặp mà không tắt interrupt cũng thiên tài: nó đảm bảo ESP luôn trỏ tới một vị trí stack hợp lệ
Một tính năng không được bàn nhiều ở đây trong FastDOOM là đủ loại chế độ video kỳ quặc
Chế độ văn bản IBM MDA: https://www.youtube.com/watch?v=Op2tr2lGK6Y
EGA & Plantronics ColorPlus: https://www.youtube.com/watch?v=gxx6lJvrITk
CGA xanh dương-hồng cổ điển: https://youtu.be/rD0UteHi2qM
CGA 320x200x16 dùng hack ‘ANSI from Hell’: https://www.youtube.com/watch?v=ut0V1nGcTf8
Hercules: https://www.youtube.com/watch?v=EEumutuyBBo
Hầu hết có vẻ chạy chậm hơn VGA vì các việc như remap màu
Nếu phải chạy bằng CGA thì chắc tôi không thích, và nếu chiếc Tandy 1000 TL/2 của tôi vẫn còn sống thì có lẽ cần một bản build 286 cho nó
Nó làm tôi nhớ đến Clean Architecture “hiện đại” trong các ứng dụng backend
Tôi ấn tượng với đoạn “IBM PS/1 486-DX2 66Mhz, ‘Mini-Tower’, model 2168. Chiếc máy tính tôi luôn muốn có khi còn tuổi teen nhưng không thể mua được”
Khoảng năm 1992, tôi đang dùng chiếc PC thứ tư tự lắp, và các hội chợ máy tính KCS ở Marlborough MA là một nguồn tài nguyên khổng lồ cho dân mày mò
Tôi mua linh kiện để dựng PC, dùng một thời gian rồi bán đi, rồi lại mua linh kiện tiếp
Đến cuối năm 1992, tôi đang chạy 486-DX3 100 gắn đồng xử lý toán học ULSI 487, và trong một thời gian có thể nói đó là chiếc PC nhanh nhất trong khuôn viên trường, thậm chí có lẽ là máy tính nhanh nhất
Nó nhanh hơn nhiều mẫu Pentium và không mắc lỗi toán học
Bản build cuối cùng được biện minh vì tôi phải mô phỏng một nhà máy đồng phát điện khí/diesel trong bảng tính Excel 21 trang cho luận văn danh dự, khiến thời gian tính lại quá lâu
Chuyên ngành của tôi là khoa học môi trường, nhưng toàn bộ sự nghiệp lại đi vào máy tính
Có nhất thiết phải làm khó một người không thể mua nổi chiếc máy tính như vậy vào năm 1992 không
Hơn nữa không có thứ gọi là “DX3”, và DX4, chiếc 486 đầu tiên 100MHz, ra mắt vào tháng 3/1994, nên chuyện đã chạy nó vào cuối năm 1992 có vẻ không đúng
Chiếc máy tính đầu tiên của nhà tôi, nếu bỏ qua một chiếc XT đã quá lỗi thời nhận được khoảng năm 1992, là 66MHz 486-DX2 mua đầu năm 1995
Ngay cả mấy chục năm sau, thấy ai đó khoe một chiếc máy tính bất khả thi nhanh hơn máy của tôi dù có lợi thế đi trước 3 năm vẫn làm tôi thấy hơi tự ái một cách kỳ lạ
Khoảng năm 1992 tôi là sinh viên nghèo, vay khoảng 2.000 đô la từ credit union để mua một chiếc 486 DX2-50
Tính theo tiền ngày nay thì tôi đã chi hơn 4.000 đô la cho một chiếc máy khá cơ bản, và tôi dual boot DOS với Linux trên nó
Tìm thử thì thấy 487 tiêu chuẩn vốn là một 486DX hoàn chỉnh, vô hiệu hóa và thay thế 486SX
Hay đó là một loại đồng xử lý tuyệt vời nào khác mà tôi không biết?
Đó là thắng áp đảo thật sự
Không chỉ phát hành thường xuyên, Viti95 còn thể hiện kỷ luật Git xuất sắc: mỗi commit làm một việc và mỗi release đều được gắn tag
https://fabiensanglard.net/fastdoom/#:~:text=one%20commit%20...
Tôi không hiểu Ibuprofen trong câu “trước khi biết fastDOOM, tôi đã cam chịu rằng phải uống Ibuprofen khi chơi” nghĩa là gì
Nếu tác giả có đọc được, trong toàn bộ tài liệu họ của John Carmack bị gõ nhầm thành “Carnmack”
Nếu nhìn một cách không cay độc về lý do phần mềm hiện đại chậm và không có các tối ưu kiểu này, có thể giải thích bằng giả thuyết chuẩn hóa/tối ưu hóa
Khi một thứ trở thành chuẩn, tối ưu hóa sẽ theo sau
Vì người ta sẽ muốn nhanh nhất trong khi vẫn vượt qua mọi bài kiểm thử của chuẩn
Doom giờ cũng đã trở thành một game chuẩn được port lên mọi nơi, từ CPU mới đến lò nướng bánh, và các giao thức email hay các chuẩn trình duyệt như WebRTC, QUIC cũng tương tự
Lý do các web app hiện đại hay ứng dụng Electron không nhanh là vì chúng đang ở giai đoạn khám phá
Chúng được cập nhật mỗi ngày theo nhu cầu người dùng mới, và về hiệu năng thì chỉ cần đủ nhanh để không gây cản trở là được
Vì vậy ứng dụng IRC rất nhanh, còn Slack và Teams thì gần như chắc chắn luôn chậm
Việc quay lại từng phiên bản để kiểm tra cải tiến và hồi quy không hề đơn giản
Một số tối ưu hóa có thể tạo ra bug chỉ được phát hiện về sau, và những tính năng cần thiết cũng có thể làm giảm hiệu năng
Vì vậy nếu có kiểm thử hiệu năng chạy tự động trước mỗi release thì cuộc sống sẽ dễ thở hơn, và khi phát hiện vấn đề hiệu năng, chỉ cần viết regression test như thường lệ
Điều muốn nói cuối cùng vẫn là: hãy kiểm thử hiệu năng