← Wszystkie wpisy

Filozofia inżynierii: John Carmack, wydajność jako moralne rzemiosło

John Carmack, programista i współzałożyciel id Software

Najważniejsze wnioski

  • Carmack traktuje wydajność jako kwestię moralną, a nie jako etap optymalizacji. Przepaść między kodem a fizyczną granicą sprzętu to marnotrawstwo, a marnotrawstwo jest wyborem.
  • Jego metoda jest odejmowaniem: zrozumieć problem do fundamentów, sprowadzić go do szybkiego i prostego rdzenia oraz odrzucić każdą funkcję, która ten rdzeń spowalnia.
  • Gdy zmienia się problem leżący u podstaw, Carmack pisze wszystko od nowa. Quake porzucił silnik, który rozsławił id, ponieważ prawdziwe 3D było zupełnie innym problemem niż jego udawanie.
  • Pracował w sposób jawny — najpierw codzienne dzienniki .plan, później silniki udostępnione jako open source — kierując się jednym przekonaniem: kod, który zamierza się opublikować, pisze się uczciwiej.

Zasada

„Prędkość światła jest do niczego.” — John Carmack1

To żart, a zarazem cała filozofia. Carmack powiedział to o opóźnieniach sieciowych — twardej, fizycznej granicy tego, jak szybko pakiet może przebyć kontynent — ale ta myśl przewija się przez każdą napisaną przez niego linijkę. Maszyną rządzi fizyka, a zadaniem inżyniera jest zbliżyć się do fizycznej granicy na tyle, na ile pozwala problem. Nie dostatecznie blisko. Tak blisko, jak pozwala fizyka. Wszystko, co znajduje się między użytkownikiem a prędkością światła, to marnotrawstwo, a marnotrawstwo to wybór, którego się dokonało.

Carmack traktuje wydajność jako kwestię moralną, a nie jako etap optymalizacji. Większość oprogramowania gromadzi powolność tak, jak dom gromadzi bałagan — po jednej rozsądnej decyzji naraz, każda do obrony, a suma nie do obrony. Dyscyplina Carmacka polega na odmowie tego gromadzenia: zrozumieć problem do fundamentów, sprowadzić go do szybkiego i prostego rdzenia, i właśnie to dostarczyć. To samo przekonanie leży u podstaw tezy, że wydajność nie jest funkcją, którą się dodaje, lecz właściwością, którą się traci — nie optymalizuje się powolnego systemu, by uczynić go szybkim; buduje się szybki i go broni.

I pokazywał swoją pracę. Przez ponad dekadę Carmack publikował swój codzienny dziennik inżynierski — plik .plan — w otwartym internecie, dostępny dla każdego, kto miał klienta finger.2 Najtrudniejsze problemy renderowania 3D lat 90. rozwiązywano publicznie, niemal w czasie rzeczywistym. Praca w sposób jawny nie była marketingiem. Był to ten sam instynkt, co w samym kodzie: żadnego ukrytego stanu, niczego, czego nie dałoby się skontrolować.

Kontekst

John D. Carmack urodził się 21 sierpnia 1970 roku w Shawnee Mission w stanie Kansas.3 Przez dwa semestry studiował na University of Missouri–Kansas City, po czym odszedł, by zawodowo pisać oprogramowanie. Nie było żadnego formalnego terminowania ani dyplomu. Programowania grafiki nauczył się tak, jak robiła to scena demo — czytając instrukcje sprzętowe, mierząc to, co układ faktycznie robił, i pisząc w asemblerze, dopóki liczby się nie zgadzały.

Trafił do Softdisku, firmy wydającej oprogramowanie i magazyn na dyskietkach, w Shreveport w Luizjanie, gdzie pracował nad subskrypcją gier o nazwie Gamer’s Edge. Tam poznał Johna Romero, Toma Halla i Adriana Carmacka (niespokrewnionego). We wrześniu 1990 roku Carmack zbudował demonstrację, która nie powinna być możliwa na pececie: płynne, konsolowej jakości przewijanie boczne na sprzęcie EGA. IBM PC z 1990 roku przerysowywał cały ekran w każdej klatce — zbyt wolno jak na grę z przewijaniem. Technika Carmacka, adaptacyjne odświeżanie kafelków, wykorzystywała mało znane funkcje sprzętowe EGA, by przesunąć już narysowany ekran i odmalować jedynie nowo odsłonięte krawędzie.4 Zespół odtworzył pierwszy poziom Super Mario Bros. 3 Nintendo jako demo na peceta, by to udowodnić. Nintendo odmówiło. Zespół zatrzymał silnik.

W lutym 1991 roku odeszli z Softdisku, by założyć id Software. Wzorzec był już ustalony: znaleźć problem, którego nikt nie rozwiązał, rozwiązać go na poziomie sprzętu, a na tym rozwiązaniu zbudować produkt. Carmack zrobi to ponownie z teksturowanym 3D, potem znów z prawdziwym 3D wielokątowym, a potem jeszcze raz z rzeczywistością wirtualną. Środowisko wokół niego — Graphics Programming Black Book Michaela Abrasha, kultura liczenia cykli ze sceny demo — traktowało procesor jako coś, co należy zrozumieć dokładnie, a nie przybliżać. To Carmack rozsławił tę kulturę.

John Romero (po lewej) i John Carmack ze swoimi ferrari przed siedzibą id Software na początku lat 90., w tym samochód wyścigowy w barwach DOOM-a

Dzieło

Commander Keen i Doom: szybki rdzeń (1990–1993)

Okładka DOOM-a (1993), namalowana przez Dona Ivana Punchatza — marine na szczycie hordy demonów

Commander Keen in Invasion of the Vorticons (grudzień 1990) był pierwszą komercyjną grą zbudowaną na adaptacyjnym odświeżaniu kafelków. Liczył się mniej jako gra niż jako dowód: że uważne odczytanie sprzętu może zlikwidować przepaść między uniwersalnym pecetem a dedykowaną konsolą. Płynne przewijanie nie było grafiką nałożoną na wierzch. Było silnikiem.

Doom (1993) to kanoniczny przykład metody Carmacka. Aby renderować swoje otoczenia dostatecznie szybko na pececie z 1993 roku, sięgnął po binarny podział przestrzeni — drzewa BSP, sformalizowane w akademickim artykule z 1980 roku, który Carmack wyśledził i zaadaptował — by z góry wyliczyć kolejność, w jakiej należy rysować ściany, tak aby silnik nigdy nie przerysowywał piksela, który i tak później zostanie zakryty.5 Doom nie jest prawdziwym 3D; to dwuwymiarowa mapa renderowana z taką dozą pomysłowości, że sprawia wrażenie przestrzennej. I właśnie o to rozróżnienie chodzi. Carmack nie budował najbardziej uniwersalnego systemu. Zbudował system, który działał szybko na sprzęcie, który istniał, i odrzucił każdą funkcję, która spowolniłaby główną pętlę. Szybki, prosty rdzeń — dostarczony.

Quake: prawdziwe 3D w oprogramowaniu (1996)

Okładka Quake'a (1996) — zardzewiałe Q z gwoździa na ciemnym kamieniu, które zapowiedziało skok id do prawdziwego 3D

Quake (1996) był przebudową od zera. Tam, gdzie Doom udawał głębię, Quake renderował autentyczne trójwymiarowe światy wielokątowe — pochyłe powierzchnie, spoglądanie w górę i w dół, prawdziwą geometrię — programowo, zanim konsumenckie akceleratory 3D stały się powszechne.6 Silnik łączył wstępnie wyliczoną widoczność BSP z mapami oświetlenia generowanymi offline oraz ręcznie dostrojonym asemblerem, by dokonać tego, co według utartych przekonań procesor tamtej epoki zrobić nie mógł. id wydało później GLQuake, renderer oparty na OpenGL, który pomógł ugruntować pozycję konsumenckiej karty graficznej 3D.

Quake to dzieło, w którym cała postawa Carmacka jest widoczna naraz: porzucił silnik, który rozsławił firmę, zrozumiał nowy problem (prawdziwe 3D) do fundamentów i przebudował. Żadnego ponownego wykorzystania dla niego samego. Poprzednie rozwiązanie nie było święte; święty był problem.

Otwarte silniki id i pliki .plan (1997–2011)

Carmack zrobił dwie nietypowe rzeczy z kodem, który go wzbogacił. Publikował swój codzienny dziennik pracy — pliki .plan — tak by praca inżynierska była czytelna w miarę jej powstawania.2 A potem rozdał silniki. id udostępniło jako open source silnik Dooma w 1997 roku, Quake’a w 1999 roku i kontynuowało udostępnianie kodu źródłowego każdej generacji id Tech w miarę pojawiania się następnej, aż po Doom 3 i dalej.7 Jego argument był prosty: udostępnianie starego kodu pozwala młodszym programistom nauczyć się, jak coś naprawdę zostało zbudowane, a „darmowe oprogramowanie, które ludzie cenią, dodaje światu bogactwa”.8

Ta gotowość to ta część, do której większość zafiksowanych na wydajności inżynierów nigdy nie dochodzi. Rzemiosło Carmacka było prywatną dyscypliną wyniesioną na widok publiczny. Gotowość, by dać się czytać — by pozwolić każdemu skontrolować codzienny dziennik, a ostatecznie i kod źródłowy — sama w sobie jest umową o jakość. Kod, który zamierza się opublikować, pisze się uczciwiej.

Oculus VR: granica opóźnienia (2013–2019)

Gogle wirtualnej rzeczywistości Oculus Rift CV1, konsumenckie urządzenie, do którego celowała praca Carmacka nad opóźnieniem

W Oculusie odwieczny wróg Carmacka — opóźnienie — stał się całym problemem. Pisał, że „opóźnienie między fizycznym ruchem głowy użytkownika a docierającymi do jego oczu zaktualizowanymi fotonami z wyświetlacza montowanego na głowie to jeden z najbardziej krytycznych czynników zapewnienia wysokiej jakości doświadczenia” oraz że dostrzegalne opóźnienie śledzenia ruchu głowy „jest również jedną z głównych przyczyn choroby symulatorowej”.9 Wyznaczył budżet — celem było rzędu 20 milisekund od ruchu do fotonu — i każdy etap potoku traktował jako miejsce, w którym można odzyskać mikrosekundy. Jego technika timewarp dokonuje reprojekcji już wyrenderowanej klatki w ostatniej chwili przed wyświetleniem, by wchłonąć ruch głowy, który nastąpił w trakcie renderowania.9 To znów adaptacyjne odświeżanie kafelków, dwadzieścia trzy lata później: nie rysować ponownie tego, co da się wykorzystać ponownie, i mierzyć wynik względem fizycznej granicy.

Metoda

Metoda jest spójna na przestrzeni trzydziestu lat i czterech dziedzin problemowych.

Zrozumieć problem do fundamentów. Carmack czyta instrukcję sprzętową, mierzy faktyczne zachowanie i pracuje od pierwszych zasad, a nie od konwencji. Drzewa BSP, mapy oświetlenia i timewarp nie były zapisane w żadnym podręczniku; zostały wyprowadzone z tego, czego problem faktycznie wymagał.

Sprowadzić do szybkiego, prostego rdzenia. Doom nie jest 3D, ponieważ 3D nie było potrzebne, by sprawiać wrażenie 3D na sprzęcie z 1993 roku. Dyscyplina polega na odejmowaniu: zidentyfikować wewnętrzną pętlę, uczynić ją szybką i odrzucić funkcje, które by ją spowolniły.

Pisać od nowa, gdy zmienia się problem. Quake nie rozszerzał silnika Dooma. Carmack traktuje działający system jako jednorazowy w chwili, gdy problem leżący u podstaw się przesunął. Koszt utopiony nie jest argumentem.

Głębokie, nieprzerwane skupienie. Maratońskie sesje kodowania Carmacka nigdy nie chodziły o wytrzymałość dla niej samej. Utrzymanie całego silnika w pamięci roboczej — układu danych, wewnętrznej pętli, wszystkich przypadków brzegowych naraz — ładuje się godzinami i rozpada w jednej chwili, gdy następuje przełączenie kontekstu. Carmack chronił ten stan tak, jak chronił cykle w pętli renderującej: jako zasób deficytowy, na którym praca rzeczywiście się odbywała.

Później: styl funkcyjny w C. W okresie Doom 3 i po nim Carmack zaczął preferować funkcje czyste i minimalizować zmienny stan nawet w C i C++ — nie z mody, lecz dlatego, że kod bez ukrytego stanu to kod, którego zachowanie da się przewidzieć, co oznacza mniej błędów.10 To ten sam instynkt, co przy plikach .plan: niczego, czego nie dałoby się skontrolować.

Łańcuch wpływów

Kto go ukształtował

Michael Abrash jest najbliższy roli mentora w tej linii. Pisma Abrasha o grafice x86 — później zebrane jako Graphics Programming Black Book — skodyfikowały kulturę liczenia cykli i mierzenia wszystkiego, którą Carmack praktykował. Obaj współpracowali później w id, a znacznie później w Oculusie, gdzie Abrash został głównym naukowcem. (Wpływ bezpośredni)

Scena demo i kultura optymalizacji w asemblerze schyłku lat 80. nauczyły fundamentalnego przekonania: procesor da się poznać dokładnie, a przepaść między kodem a sprzętowym sufitem to odpowiedzialność programisty. (Wpływ formacyjny)

John Romero, jego wspólnik w id, był raczej dopełnieniem niż nauczycielem. Projektowanie i praca nad poziomami autorstwa Romero dawały silnikom Carmacka coś, co warto było uruchomić. To partnerstwo przypomina, że szybki rdzeń jest konieczny, lecz niewystarczający — silnik istnieje po to, by w niego grać.

Kogo on ukształtował

Cała branża silników do gier. Widoczność BSP, mapy oświetlenia i udostępnianie dojrzałych silników jako open source stały się standardową praktyką. Pokolenie programistów silników nauczyło się renderowania 3D, czytając kod źródłowy id Tech, który Carmack postanowił udostępnić.

Konsumencki sprzęt graficzny 3D. Ścieżka OpenGL w Quake’u była wczesnym komercyjnym argumentem za kartą-akceleratorem 3D, pomagając wprowadzić GPU do głównego nurtu peceta.

Współczesna rzeczywistość wirtualna. Timewarp i bezlitosny budżet opóźnień to dziś standardowe słownictwo w każdym potoku VR. Cel 20 milisekund, do którego dążył Carmack, jest powodem, dla którego dzisiejsze gogle nie przyprawiają ludzi o mdłości.

Nić przewodnia

Andrej Karpathy odbudowuje sieci neuronowe od zera, ponieważ zrozumienia nie da się przekazać — trzeba wyprowadzić je samodzielnie. Carmack wyprowadza swoje renderery tak samo: nie z frameworka, lecz ze sprzętu i z problemu. A tam, gdzie Linus Torvalds ceni „dobry gust” — przypadek szczególny, który rozpływa się w przypadku ogólnym — Carmack ceni wewnętrzną pętlę, która wykonuje najmniej pracy, na ile pozwala fizyka. Oba to to samo przekonanie w innym ubraniu: właściwa struktura nie jest dekoracją nałożoną na problem; jest problemem, widzianym poprawnie. (Pomost serii)

Co z tego biorę

Lekcja, którą zachowuję, brzmi: wydajność to uczciwość. Powolny system to zwykle taki, którego autor nigdy nie zrozumiał problemu dostatecznie dobrze, by odnaleźć jego szybki rdzeń — składał abstrakcje, dopóki nie zadziałało, a na „zadziałało” się zatrzymał. Carmack zatrzymuje się dopiero na fizycznej granicy. To ten sam standard, co w tezie, że jakość jest jedyną zmienną: pytaniem nigdy nie jest „czy to dostatecznie szybkie, by dostarczyć?”, lecz „czy naprawdę rozumiem, dlaczego jest aż tak wolne?”.

W świecie, w którym teraz buduję — agenci, pętle narzędziowe, systemy AI — pokusa jest przeciwieństwem dyscypliny Carmacka: piętrzyć frameworki, zaklejać opóźnienia kolejnymi wywołaniami modelu, nigdy nie czytać, co system faktycznie robi. Ruch w stylu Carmacka to sprofilować pętlę, znaleźć część, która dominuje, zrozumieć ją do fundamentów i odrzucić resztę. To przekonanie — że gust jest systemem technicznym, który da się zmierzyć, a nie wrażeniem, które się głosi — jest nicią przewodnią od sztuczki z przewijaniem EGA z 1990 roku po ramy agenta z 2026 roku.

FAQ

Na czym polega filozofia inżynierska Johna Carmacka?

Carmack traktuje wydajność jako kwestię moralną, a nie jako sprawę uboczną. Dyscyplina polega na tym, by zrozumieć problem do fundamentów, sprowadzić go do szybkiego i prostego rdzenia, odrzucić funkcje, które ten rdzeń spowalniają, i napisać wszystko od nowa, gdy zmienia się problem leżący u podstaw. Łączy to z pracą w sposób jawny — publikowaniem codziennego dziennika inżynierskiego i udostępnianiem dojrzałych silników jako open source — w przekonaniu, że kod, który da się skontrolować, jest pisany uczciwiej.28

Co zbudował John Carmack?

Carmack współzałożył id Software w 1991 roku i był głównym programistą gier Commander Keen (1990, adaptacyjne odświeżanie kafelków), Wolfenstein 3D (1992), Doom (1993, renderowanie oparte na BSP) oraz Quake (1996, programowe renderowanie prawdziwego 3D). Udostępnił silniki id Tech jako open source na przestrzeni dwóch dekad, pełnił funkcję CTO w Oculus VR, gdzie kierował pracami nad opóźnieniem od ruchu do fotonu, a później założył firmę zajmującą się AI — Keen Technologies.5679

Czym jest adaptacyjne odświeżanie kafelków?

To technika, którą Carmack opracował w 1990 roku, by osiągnąć płynne przewijanie boczne na sprzęcie EGA komputera IBM PC, który w przeciwnym razie był zbyt wolny, ponieważ przerysowywał cały ekran w każdej klatce. Adaptacyjne odświeżanie kafelków przesuwa już narysowany ekran z użyciem funkcji sprzętowych EGA i odmalowuje wyłącznie nowo odsłonięte kafelki na krawędziach, drastycznie zmniejszając pracę przypadającą na klatkę. To ono umożliwiło powstanie Commander Keena i ustanowiło charakterystyczny ruch Carmacka: rozwiązać wąskie gardło na poziomie sprzętu.4

Dlaczego Carmack publikował swoje pliki .plan i udostępniał silniki jako open source?

Pliki .plan były codziennym dziennikiem inżynierskim, pierwotnie czytelnym przez protokół finger, który dokumentował rozwój id niemal w czasie rzeczywistym.2 Carmack udostępnił później jako open source każdą generację id Tech, gdy tylko jej następczyni trafiła na rynek, argumentując, że udostępnianie starego kodu pomaga nowszym programistom nauczyć się, jak gry naprawdę się buduje, oraz że wartościowe darmowe oprogramowanie „dodaje światu bogactwa”.8 Obie praktyki odzwierciedlają tę samą zasadę, co jego kod: żadnego ukrytego stanu, niczego, czego nie dałoby się skontrolować.


Źródła


  1. John D. Carmack, „The speed of light sucks.” Wikiquote, o opóźnieniach sieciowych. Szeroko cytowane z jego prac nad siecią z czasów QuakeWorld; zob. także dyskusję w Data Center Knowledge. 

  2. Robbie, „The Carmack Plan,” Garbage Collected, październik 2017 — o plikach .plan, protokole finger i pracy w sposób jawny. Zarchiwizowane dzienniki w oliverbenns/john-carmack-plan obejmują okres od 1996 roku po lata 2000., dokumentując wieloletni przebieg tej praktyki. 

  3. „John Carmack.” DoomWiki. Urodzony 21 sierpnia 1970 roku, Shawnee Mission, Kansas; University of Missouri–Kansas City; Softdisk; założenie id Software. 

  4. David Kushner, Masters of Doom: How Two Guys Created an Empire and Transformed Pop Culture (Random House, 2003), rozdz. 3 — datuje przełom Carmacka z płynnym przewijaniem oraz nocne odtworzenie Super Mario Bros. 3 na wrzesień 1990 roku w Softdisku. Potwierdzone przez współpracownika Romero, Johna Andersona, „The Saga of Dangerous Dave,” który datuje „Dangerous Dave in Copyright Infringement” na wrzesień 1990 roku. Szczegóły techniczne: „Adaptive tile refresh,” Wikipedia, oraz Fabien Sanglard, „Commander Keen’s Adaptive Tile Refresh.” 

  5. „Doom rendering engine,” DoomWiki — drzewa BSP przyjęte między alfą z maja 1993 roku a betą z października 1993 roku; eliminacja przerysowywania poprzez przycinanie segmentów. O pochodzeniu techniki: Sinclair Target, „How Much of a Genius-Level Move Was Using Binary Space Partitioning in Doom?,” Two-Bit History (2019) — śledzi drzewo BSP aż do artykułu z 1980 roku autorstwa Henry’ego Fuchsa, Zviego Kedema i Bruce’a Naylora, „On Visible Surface Generation by A Priori Tree Structures” (oraz jego poprzednika z 1969 roku — symulatora lotu Sił Powietrznych USA) i dokumentuje, że Carmack zaadaptował je na potrzeby Dooma. 

  6. „Quake engine.” Wikipedia. Programowe renderowanie prawdziwego 3D wielokątowego (1996), wstępnie wyliczona widoczność, mapy oświetlenia, napisane w C i asemblerze, później ścieżka OpenGL. 

  7. „id Tech,” Wikipedia — dokumentuje udostępnienia kodu źródłowego: silnik Dooma w 1997 roku (zmiana licencji na GPL w 1999 roku), silnik Quake’a w 1999 roku, Quake II w 2001 roku, Quake III w 2005 roku oraz silnik Doom 3 (id Tech 4) w 2011 roku — ostatnie wydanie na licencji GPL. Przegląd: „A graphical history of id Tech,” PC Gamer. 

  8. Brad Cook, wywiad z Johnem Carmackiem, Apple.com (zarchiwizowane), cytowane za Wikiquote. „Dzielenie się kodem po prostu wydaje się słuszną rzeczą… Darmowe oprogramowanie, które ludzie cenią, dodaje światu bogactwa.” Zob. także: TechRadar, „id’s John Carmack sings praises of open source.” 

  9. John Carmack, „Latency Mitigation Strategies” (zarchiwizowane; pierwotnie opublikowane w lutym 2013 roku). Dosłownie: „Opóźnienie między fizycznym ruchem głowy użytkownika a docierającymi do jego oczu zaktualizowanymi fotonami z wyświetlacza montowanego na głowie to jeden z najbardziej krytycznych czynników zapewnienia wysokiej jakości doświadczenia” oraz „Dostrzeganie opóźnienia w reakcji na ruch głowy jest również jedną z głównych przyczyn choroby symulatorowej”. Tekst opisuje technikę reprojekcji time-warp. Kontekst docelowego opóźnienia VR: PCGamesN, „John Carmack’s battle for 20 millisecond latency.” 

  10. John Carmack, „In-Depth: Functional Programming in C++,” Gamasutra/Game Developer, 30 kwietnia 2012: „Duża część wad w tworzeniu oprogramowania wynika z tego, że programiści nie rozumieją w pełni wszystkich możliwych stanów, w jakich ich kod może się wykonywać. Programowanie w stylu funkcyjnym sprawia, że stan przedstawiany kodowi staje się jawny.” O preferowaniu funkcji czystych i minimalizowaniu zmiennego stanu w celu redukcji błędów. 

Powiązane artykuły

Filozofia inżynierii: Thompson i Ritchie, rób jedną rzecz dobrze

Thompson i Ritchie zbudowali Uniksa i język C z małych, ostrych narzędzi łączonych przez jeden uniwersalny interfejs: st…

15 min czytania

Filozofia inżynierska: Leslie Lamport, myśl, zanim zaczniesz kodować

Leslie Lamport uczynił z systemów rozproszonych naukę: czas nie jest globalny, prawdziwa jest przyczynowość, a projekt o…

15 min czytania

The Shader Gallery That Lied: Debugging 216 WebGL Presets

A user said the shader playground looked broken. Pixel-readback testing found 30 dead presets, 11 that never compiled, a…

11 min czytania