O GitHub reconstruiu a interface de visualização de pull requests no aplicativo GitHub Copilot para lidar com um caso extremo: um pull request com 2.200 arquivos, mais de um milhão de linhas alteradas e mais de 400 comentários de revisão incorporados. O objetivo não era apenas acelerar a exibição de uma grande diferença, mas manter a rolagem e a revisão utilizáveis depois que a própria conversa adiciona dimensões variáveis ao documento.
A interface tradicional para grandes diferenças depende da renderização virtual, ou seja, mantém apenas os elementos visíveis próximos à janela de visualização, reutilizando elementos DOM durante a rolagem. Esse modelo funciona com relativa facilidade quando cada elemento é uma linha de código com altura conhecida. Os comentários, porém, não têm essa característica; sua altura varia de acordo com a quebra de Markdown, a abertura de seções <details>, a exibição do editor de resposta, as imagens, as alterações sugeridas e os diferentes estados de interação.
Duas engenharias em vez de uma única tabela de alturas
O GitHub manteve uma engenharia fixa para as linhas de código, usando cálculos prévios de posições e alturas e sem reconstruí-la quando um comentário muda. Em contrapartida, colocou comentários, editores de resposta e blocos dinâmicos em um índice independente. Cada bloco tem uma chave estável associada ao arquivo, à linha e ao lado, além de uma impressão digital do conteúdo, do estado das seções abertas e da última largura medida.
A altura medida é usada quando as medições são válidas, ou um valor armazenado em cache quando a impressão digital e a largura continuam compatíveis; caso contrário, a interface usa uma estimativa temporária. Assim, a expansão de um único comentário não provoca o recálculo da engenharia de milhões de linhas.
Medição fora do caminho da rolagem
O GitHub abandonou um design inicial que dependia de um ResizeObserver independente para cada bloco e gravava a medição diretamente no layout. Esse padrão pode criar um ciclo de realimentação, porque uma alteração no layout reinicia a observação, e seu custo também aumenta com o número de blocos montados.
O design lançado pela empresa usa um único ciclo de medição associado a períodos de inatividade e ao fim da rolagem. Normalmente, apenas os blocos localizados a cerca de 2.400 pixels da janela de visualização são medidos, enquanto os blocos distantes permanecem com suas estimativas até se aproximarem. As medições dos elementos visíveis são lidas em lote para evitar operações repetidas de reflow.
Os observadores continuam presentes para detectar mudanças como o carregamento de uma imagem ou a digitação no editor de resposta, mas marcam o bloco para que o ciclo de medição o leia novamente, em vez de alterar a altura diretamente. A exceção é uma mudança causada pelo usuário em um bloco visível, como abrir uma seção ou um editor de resposta; nesse caso, uma única correção síncrona pode ser aplicada no mesmo quadro, impedindo que apareça um salto visível entre a expansão do comentário e o movimento do código abaixo dele.
Correção do layout sem perder a posição de leitura
Quando a altura real difere da estimativa, a interface não corrige a posição com base apenas no número de pixels. Ela preserva a identidade do elemento que o usuário está lendo, seja uma linha ou um bloco de comentário, determina o deslocamento dentro dele, aplica as diferenças de altura e recalcula a posição do próprio elemento. Dessa forma, o elemento fixado permanece praticamente no mesmo lugar.
Normalmente, as correções não são realizadas durante a rolagem ou o impulso do usuário, e os ajustes resultantes de conteúdo abaixo da tela não são usados para mover a visualização. A equipe encontrou um erro quando a rolagem programática resultante de uma mudança na largura do painel foi considerada uma rolagem do usuário, o que causou a perda da correção e o deslocamento do arquivo em leitura. Isso foi resolvido separando a interação do usuário das mudanças causadas pela própria interface.
Pipeline de dados e testes automatizados
A responsividade não depende apenas da renderização virtual. A estrutura da diferença e os dados dos arquivos são enviados primeiro para que a árvore de arquivos e os metadados apareçam enquanto o restante do documento é carregado, enquanto tarefas como o realce de sintaxe e a construção detalhada do Markdown são adiadas até que os elementos se aproximem da janela de visualização. A interface também mantém temporariamente as últimas poucas diferenças usadas, liberando o que ultrapassa esse limite para reduzir o consumo de memória.
Para detectar defeitos que só aparecem durante uma rolagem profunda, o GitHub adicionou sinais permanentes de medição e testes automatizados que monitoram o número de linhas e blocos montados, o tempo do quadro, o tamanho das correções de rolagem, o vazamento de observadores e a existência de espaços não preenchidos. A equipe executou fluxos automatizados no aplicativo para desktop e no mecanismo de renderização real, com casos como abrir seções, iniciar editores de resposta, redimensionar a janela e navegar por uma lista grande de arquivos.
Por que esse design é importante?
O resultado anunciado é que um pull request com um milhão de linhas e centenas de comentários se comporta como um pull request comum: os comentários são exibidos por completo, em vez de serem cortados dentro de uma barra de rolagem aninhada; expandir uma seção move o código abaixo dela sem saltos aleatórios; e é possível retornar a um pull request mantendo a posição de leitura. O principal valor de engenharia é que o GitHub não tentou tornar todo o conteúdo de natureza única; em vez disso, manteve a parte determinística rápida e a separou do conteúdo cujo tamanho não pode ser conhecido antes da renderização.
Ainda assim, o material não afirma que todos os pull requests grandes se tornaram fáceis de revisar em termos de compreensão ou gerenciamento de riscos. O que foi tratado é o desempenho e o comportamento da interface durante a medição e as mudanças. Além disso, os resultados estão vinculados ao aplicativo GitHub Copilot e ao seu design interno, e não fornecem números independentes sobre o consumo de memória ou indicadores de desempenho em diferentes dispositivos e mecanismos.