Por que o fastDOOM é mais rápido
(fabiensanglard.net)- Em um IBM PS/1 486-DX2 66MHz, que era um PC de alto desempenho em 1993, o DOOM original rodava
demo1a 21,5 fps, enquanto o fastDOOM chegava a 30,1 fps nas mesmas condições, mostrando a diferença trazida pela otimização do port para DOS - O fastDOOM partiu do PCDOOM v2, que combinava o núcleo do Linux DOOM, I/O do Heretic, APODMX e I/O gráfico em Mode Y baseado em desassemblagem reversa de
DOOM.EXE - Após compilar e testar 52 releases e 3.042 commits, concluiu-se que o ganho de desempenho não veio de um compilador moderno sozinho, mas do acúmulo de pequenas otimizações
- Entre as grandes melhorias estão omitir a renderização da barra de status, inline de
FixedDiv, otimização da travessia de BSP, omissão da renderização de visplane, remoção de indireção por ponteiros e separação de executáveis por renderizador - Os modos gráficos têm vantagens e desvantagens dependendo da CPU e do barramento: em CPUs lentas, o Mode Y leva vantagem; em CPUs rápidas e ambientes VLB/PCI, Mode 13h ou VESA direct podem ser melhores, embora ainda existam restrições como VESA 2.0
Diferença de desempenho exposta no 486-DX2
- No IBM PS/1 486-DX2 66MHz “Mini-Tower” modelo 2168, ao executar o DOOM original com
doom.exe -timedemo demo1, o resultado é1710 gametics in 2783 realtics- Como o DOOM não mostra fps diretamente, é preciso calcular
1710/2783*35, o que resulta em 21,5 fps
- Como o DOOM não mostra fps diretamente, é preciso calcular
- Na mesma máquina, ao executar
fdoom.exe -timedemo demo1, aparece1710 gametics in 1988 realtics, confirmando 30,1 fps - Em mapas mais pesados, como
demo1dedoom2, o desempenho sobe de 16,8 fps no original para 24,9 fps no fastDOOM, ficando 48% mais rápido - Porém, o suporte a joystick e network gameplay foi removido, então não é um port que preserva todos os recursos originais
A linhagem de código de onde veio o fastDOOM
- O DOOM foi desenvolvido originalmente em uma NeXT Workstation e tinha uma estrutura fácil de portar, dividida entre a maior parte do código principal e um pequeno subsistema de I/O
- A versão comercial para DOS usava o I/O para DOS escrito pela id Software, mas por depender da biblioteca de som proprietária DMX, ela não pôde ser aberta como open source em 1997 do mesmo jeito
- O código publicado foi a versão Linux organizada por Bernd Kreimeier enquanto ele trabalhava em um projeto de livro para explicar o engine
- A versão DOS PCDOOM v2 foi reconstruída com a seguinte combinação
- o núcleo do Linux DOOM
- o I/O do Heretic
- o APODMX para imitar o DMX
- o I/O gráfico de
i_ibm.c, obtido por engenharia reversa a partir da desassemblagem deDOOM.EXE
- O fastDOOM adotou esse PCDOOM v2 como ponto de partida
Mudanças de desempenho rastreadas por releases e commits
- Victor “Viti95” Nieto lançava o fastDOOM com frequência, marcava cada release com tags e mantinha a regra de um commit para cada tarefa
- O histórico Git do fastDOOM é composto por 3.042 commits, o que permitiu rastrear a variação de desempenho commit a commit
- Foram baixados 52 releases do fastDOOM, o PCDOOM v2 e o
DOOM.EXEoriginal, e um programa em Go gerou umRUN.BATpara executar-timedemo demo1, com os testes montados via mTCPNETDRIVE- As condições eram
DOOM.WAD, som ligado e screen size 10 - A suíte inteira foi executada 5 vezes e a média de fps foi plotada em gráfico
- As condições eram
- O PCDOOM v2 foi compilado com OpenWatcom 2, mas ainda assim melhorou pouco em relação ao
DOOM.EXEoriginal, então o avanço do fastDOOM é difícil de explicar apenas pelo uso de compilador moderno - No gráfico de tamanho dos arquivos, o trabalho inicial seguia a direção de deixá-los mais leves por meio de limpeza e remoção de código
Mudanças por release que aumentaram o desempenho
- Fazer timedemo de todas as 3.042 builds levaria cerca de 9 dias, então o benchmark no nível de commit se concentrou em
v0.1,v0.6,v0.8,v0.9.2ev0.9.7, onde os ganhos de velocidade foram maiores -
fastDOOM v0.1
v0.1é composto por 220 commits- O maior patch é o e16bab8 da build 36
- A “Crispy optimization” transforma a renderização em no-op quando a porcentagem da barra de status não mudou, evitando a renderização do scrap buffer e o blit para a tela
- Só essa mudança trouxe um ganho de 2 fps
- O a9359d5 da build 167 faz inline de
FixedDivcomo macro - O 9bd3f20 da build 207 incorpora uma otimização do PSX Doom e melhora a forma de percorrer o BSP
- O dc0f48e da build 212 faz inline da função de renderização de superfícies horizontais
R_MakeSpans - Entre todos os commits, 100 eram commits de remoção, ou seja, cerca de metade foi exclusão de código
-
fastDOOM v0.6
-
fastDOOM v0.8
v0.8é composto por 282 commits- Como o sistema de som estava instável, o timedemo foi feito sem som e depois o fps foi corrigido
- Essa release tinha foco no renderizador em modo texto, e houve regressão nas builds 670 e 730 quando a Crispy optimization saiu
- As principais melhorias foram as seguintes
-
fastDOOM v0.9.2 e v0.9.7
v0.9.2tem 110 commits, com destaque para a otimização da comparação de skyflatnum, otimização deR_DrawColumnpara Mode Y e limpeza de código emR_DrawSpanv0.9.7foi apresentado como tendo 293 commits, mas a saída do comando mostra 294- Mesmo com vários benchmarks, essa release não conseguiu reduzir o ruído dos resultados
- As principais mudanças incluem testes de alterações em ASM x86, seleção de CPU para 386SX e otimização de CR2, otimização de ESP para
R_DrawSpan386SX, código baseado em renderização ASM fuzz column e remoção de comparações CMP por loop
Como escolher entre Mode 13h, Mode Y e VESA direct
- O fastDOOM explora várias otimizações para combinações diversas de CPU e barramento de vídeo, incluindo 386, 486, Pentium, Cyrix e ISA, VLB, PCI
- No IBM PS/1 486-DX2 66MHz, a otimização usando Mode 13h foi mais lenta do que o Mode Y
-
Mode 13h
- O hardware distribui os dados entre os quatro bancos de VRAM da VGA, então para a CPU ele parece um framebuffer linear único de 320x200
- Não é possível fazer double buffering na VRAM, então é preciso renderizar em RAM e depois copiar de novo para a VRAM, escrevendo os bytes duas vezes
- O engine precisa ficar bloqueado no VSYNC
-
Mode Y
- Permite acessar individualmente os bancos da VGA, tornando possível triple buffering em VRAM e escrita direta dos bytes na VRAM uma única vez
- A seleção de banco exige a instrução lenta
OUT - Escrevendo simultaneamente em dois bancos de VGA via latch, é possível replicar pixels horizontais e obter low-detail mode
- A renderização do Specter invisível exige readback da VRAM, ficando muito mais lenta
- Segundo a explicação de John Carmack, o DOOM usava no modo VGA 320×200×256 um modo planar intercalado semelhante ao Mode X e alternava entre três display pages
- Fazer texture mapping diretamente na video memory podia render 10% a 15% mais velocidade em muitas placas de vídeo
- Também permitia page flip sem tearing, algo que o buffering em main memory não conseguia
- Heretic saiu em 1994, e com a mudança do hardware na época o Mode 13h se tornou uma opção mais atraente, levando a Raven a adaptar o engine nessa direção
- O fastDOOM oferece vários executáveis ao usuário
FDOOM.EXEFDOOM13H.EXEFDOOMVBD.EXE
-
Mode 13h e VESA direct no fastDOOM
- No Mode 13h do fastDOOM, a renderização é feita em um framebuffer linear único na RAM e, quando a cena inteira termina, ela é copiada para a VRAM
- Como o VSYNC não é forçado, pode haver flickering
- Em barramentos ISA 8-bit lentos, usa-se cópia diferencial, enviando apenas os pixels alterados
- Em barramentos mais rápidos, como ISA 16-bit, VLB e PCI, o backbuffer inteiro é copiado com
REP MOVS - Nos testes de Viti95, o melhor modo para CPUs 486 é o VESA direct mode de 320×200,
FDOOMVBD.EXE- Ele combina as vantagens do Mode Y com o código de renderização otimizado do Heretic
- Evita a instrução
OUT, exceto por uma vez por frame na troca de buffer - Exige placa gráfica VLB ou PCI com LFB ativado e suporte a VESA 2.0, além de ficar lento nos modos low-detail e potato-detail
- O IBM 2168 não suporta VESA 2.0, então
FDOOMVBP.EXEeFDOOMVBDgeram erro ao executar
Tentativas que não funcionaram e impressão geral
- Também foram testadas as flags específicas de processador do OpenWatcom,
4r/4se3r/3s, mas a tentativa foi abandonada- Foram testadas as flags para 386 e 486 do wcc386, e no fim a versão para 386 sempre parecia mais rápida
- Viti95 também quer trocar o compilador do fastDOOM de OpenWatcom v2 para DJGPP, ou seja, GCC
- Isso porque o GCC parece gerar código mais rápido a partir do mesmo source
- Outra alternativa desejável seria melhorar o OpenWatcom v2 para reduzir essa diferença de desempenho
- O desempenho do fastDOOM é resultado do reaproveitamento de melhorias já existentes de Crispy, PSX, GBA e Lee Killough, junto com uma grande quantidade de novas otimizações
- Ideias e parte do código de Ken Silverman também entraram nas funções de renderização para CPU UMC Green, trazendo um grande ganho de velocidade nesse hardware
- O fastDOOM é um caso em que não houve uma mudança mágica única, mas sim milhares de pequenas otimizações acumuladas até virar um port para DOS mais rápido que o DOOM original
1 comentários
Comentários do Hacker News
Este é um bom exemplo de como gargalos normalmente não estão onde se espera, então profiling e medição são necessários
Renderização de porcentagem na barra de status — para um especialista que conhece bem a estrutura do Doom isso talvez fosse relativamente óbvio, mas antes disso eu jamais teria imaginado que fosse o gargalo
https://www.granola.ai/blog/dont-animate-height
No pior caso, quase 1/6 do frame inteiro era gasto mostrando a pontuação na barra de status, o que reduzia o limite antes de o jogo ficar lento; o patch mudou o armazenamento e a exibição da pontuação para algo próximo de tempo constante, ficando até um pouco mais rápido que o melhor caso anterior
https://www.smwcentral.net/?p=section&a=details&id=35746
Renderização de UI pode ser crítica por causa de transparência, camadas, redesenho e especialmente por provocar alocação de memória; comparar o valor anterior com o novo antes de redesenhar ajuda bastante
Também já houve projeto em CSS em que camadas e transparência eram o gargalo, e ali o principal foi reduzir a quantidade de camadas
O carregamento de 6 minutos caiu para menos de 2 minutos
https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times...
https://news.ycombinator.com/item?id=10974929
Talvez eu não seja exatamente o público-alvo, mas o NETDRIVE do mTCP foi interessante
Eu não sabia que existiam opções utilizáveis de armazenamento em rede já naquela época; fui procurar e encontrei https://www.brutman.com/mTCP/mTCP_NetDrive.html, o que é realmente muito legal
Dizem que o NetDrive é um driver de dispositivo que permite ao DOS acessar uma imagem de disco remota hospedada em outra máquina como se fosse um dispositivo local anexado a uma letra de unidade
Era extremamente lento, então os alunos perdiam de 5 a 10 minutos no começo da aula só para abrir o processador de texto; o Xerox Alto também usava montagens de rede em drives
Quando existe rede, alguém logo quer copiar arquivos, e a forma mais conveniente é fazer isso parecer um sistema de arquivos local
O DOS ficava para trás nisso por não ter rede embutida, então havia muito mais coisa a fazer manualmente
Sem drivers nem configuração no lado do DOS, isso permite acesso de leitura e escrita a um dispositivo de bloco em rede; se usar como compartilhamento, quebra rapidamente, e se parece mais com um dispositivo de bloco
Parece mágica, mas imagino que o iPXE faça patch no BIOS para enviar o acesso a disco via iSCSI
FTP e telnet obviamente existiam, mas fico pensando se montagens remotas eram realmente usadas ou se eram inviáveis por causa da baixa largura de banda
A thread no GitHub com participação de Ken Silverman é um tesouro
É impressionante ver o autor do FastDOOM e o Ken mergulhando nas complexidades de eficiência de registradores de 486 e ciclos de clock
É bom saber que ainda existe gente cuidando para que o Doom continue recebendo melhorias de desempenho
Aquele scripting foi literalmente minha primeira “programação” e, de certo modo, devo minha carreira e meu patrimônio inteiros ao KenS, o que é incrível
Gostei especialmente da ideia de usar CR2 e CR3 como registradores scratchpad no 386SX, em que acesso à memória é muito lento, e no 386DX sem cache
A técnica de usar o ESP como contador de loop sem desabilitar interrupções também é genial, porque garante que ele sempre aponte para uma posição válida da pilha
Um recurso do FastDOOM que não foi muito abordado aqui são os vários modos de vídeo esquisitos
Modo texto IBM MDA: https://www.youtube.com/watch?v=Op2tr2lGK6Y
EGA & Plantronics ColorPlus: https://www.youtube.com/watch?v=gxx6lJvrITk
CGA clássico azul e rosa: https://youtu.be/rD0UteHi2qM
CGA 320x200x16 usando o hack “ANSI from Hell”: https://www.youtube.com/watch?v=ut0V1nGcTf8
Hercules: https://www.youtube.com/watch?v=EEumutuyBBo
A maioria parece rodar mais devagar que VGA, provavelmente por causa de tarefas como remapeamento de cores
Se tivesse de rodar em CGA, eu não ia gostar, e se ainda estivesse vivo, provavelmente precisaria de uma build 286 para um Tandy 1000 TL/2
Lembra a Clean Architecture “moderna” de aplicações de backend
A parte “IBM PS/1 486-DX2 66Mhz, ‘Mini-Tower’, model 2168. Um computador que eu sempre quis quando era adolescente, mas nunca pude comprar” chama atenção
Por volta de 1992, eu já estava usando o quarto PC que montei, e a feira de computadores da KCS em Marlborough, MA, era um recurso enorme para quem gostava de fuçar
Eu comprava peças, montava um PC, usava por um tempo, vendia e depois comprava peças de novo
No fim de 1992, eu estava rodando um 486-DX3 100 com um coprocessador matemático ULSI 487 e, por um tempo, dava para dizer que era o PC mais rápido do campus, talvez até o computador mais rápido
Era mais rápido que vários modelos de Pentium e não cometia erros matemáticos
A última montagem se justificou porque eu estava simulando uma usina de cogeração a gás/diesel numa planilha Excel de 21 páginas para minha monografia de conclusão, e o tempo de recálculo era longo demais
Minha formação era em ciências ambientais, mas minha carreira acabou sendo toda em computadores
Será que precisava fazer alguém que não pôde comprar um computador desses em 1992 se sentir mal desse jeito
Além disso, não existia “DX3”, e o DX4, o primeiro 486 de 100MHz, saiu em março de 1994, então não parece bater essa história de estar rodando isso no fim de 1992
O primeiro computador da minha família, desconsiderando um XT já muito ultrapassado que recebemos por volta de 1992, foi um 66MHz 486-DX2 comprado no começo de 1995
Mesmo depois de décadas, ver alguém se gabando estranhamente de um computador impossível, que teria sido mais rápido que o meu apesar de um atraso de três anos, ainda mexe com meu orgulho sem motivo
Eu era um estudante universitário pobre por volta de 1992 e peguei um empréstimo de cerca de 2.000 dólares na cooperativa de crédito para comprar um 486 DX2-50
Em dinheiro de hoje, isso dá mais de 4.000 dólares por um computador bem básico, e eu fazia dual boot de DOS e Linux naquela máquina
Fui pesquisar e o 487 padrão era na verdade um 486DX completo que desativava e substituía o 486SX original
Será que era algum outro coprocessador incrível que eu desconhecia
Deu um baile mesmo
Além de lançar com frequência, Viti95 mostrou uma excelente disciplina de Git, com cada commit fazendo uma única coisa e cada release recebendo uma tag
https://fabiensanglard.net/fastdoom/#:~:text=one%20commit%20...
Em “antes de conhecer fastDOOM, eu tinha me resignado a jogar tomando Ibuprofen”, não entendo o que Ibuprofen quer dizer
Se o autor vir isso, ao longo do documento o sobrenome de John Carmack está escrito errado como “Carnmack”
Uma forma não cínica de ver por que softwares modernos são lentos e não recebem esse tipo de otimização é a hipótese da padronização/otimização
Quando algo vira padrão, a otimização vem em seguida
Porque você passa a querer ser o mais rápido possível enquanto ainda passa em todos os testes do padrão
Doom agora também virou um jogo padrão para portar para qualquer coisa, seja uma CPU nova ou uma torradeira, e protocolos de e-mail ou padrões de navegador como WebRTC e QUIC são parecidos
Apps web modernos ou apps em Electron não são rápidos porque ainda estão na fase de exploração
Eles são atualizados todos os dias para atender a novas demandas dos usuários e, em termos de desempenho, basta que sejam rápidos o suficiente para não atrapalhar
É por isso que um app de IRC pode ser muito rápido, enquanto Slack e Teams inevitavelmente estão sempre lentos
Voltar pelas versões para verificar melhorias e regressões não é algo trivial
Algumas otimizações podem introduzir bugs descobertos só depois, e recursos realmente necessários também podem piorar o desempenho
Por isso, ter testes de desempenho rodando automaticamente antes de cada release facilita a vida, e se um problema de desempenho for encontrado, basta escrever um teste de regressão como de costume
No fim, o que eu quero dizer é: façam testes de desempenho