Otimizar a velocidade de iteração

Nesta página, descrevemos como otimizar o desempenho de compilação do Bazel ao executá-lo repetidamente.

Estado do ambiente de execução do Bazel

Uma invocação do Bazel envolve várias partes que interagem.

  • A interface de linha de comando (CLI) bazel é a ferramenta de front-end voltada para o usuário e recebe comandos do usuário.

  • A ferramenta da CLI inicia um servidor do Bazel para cada base de saída distinta. O servidor do Bazel geralmente é permanente, mas será encerrado após algum tempo de inatividade para não desperdiçar recursos.

  • O servidor do Bazel executa as etapas de carregamento e análise para um determinado comando (build, run, cquery etc.), em que ele cria as partes necessárias do gráfico de build na memória. As estruturas de dados resultantes são retidas no servidor do Bazel como parte do cache de análise.

  • O servidor do Bazel também pode realizar a execução da ação ou enviar ações para execução remota, se estiver configurado para isso. Os resultados das execuções de ação também são armazenados em cache, ou seja, no cache de ações, ou cache de execução, que pode ser local ou remoto e pode ser compartilhado entre servidores do Bazel.

  • O resultado da invocação do Bazel é disponibilizado na árvore de saída.

Como executar o Bazel iterativamente

Em um fluxo de trabalho típico do desenvolvedor, é comum criar (ou executar) um trecho de código repetidamente, geralmente em uma frequência muito alta, por exemplo, para resolver algum erro de compilação ou investigar um teste com falha. Nessa situação, é importante que invocações repetidas de bazel tenham o mínimo possível de sobrecarga em relação à ação repetida e subjacente (por exemplo, invocar um compilador ou executar um teste).

Pensando nisso, vamos dar outra olhada no estado do ambiente de execução do Bazel:

O cache de análise é uma parte essencial dos dados. Uma quantidade significativa de tempo pode ser gasta apenas nas fases de carregamento e análise de uma execução a frio, ou seja, uma execução logo após o servidor Bazel ser iniciado ou quando o cache de análise foi descartado. Para um único build a frio bem-sucedido (por exemplo, para uma versão de produção), esse custo é suportável, mas para criar repetidamente o mesmo destino, é importante que ele seja amortizado e não repetido a cada invocação.

O cache de análise é bastante volátil. Em primeiro lugar, ele faz parte do estado de processo do servidor do Bazel, portanto, perder o servidor perde o cache. Mas o cache também é invalidado com muita facilidade: por exemplo, muitas sinalizações de linha de comando bazel fazem com que o cache seja descartado. Isso ocorre porque muitas flags afetam o gráfico de build, por exemplo, por causa de atributos configuráveis. Algumas mudanças de sinalização também podem fazer com que o servidor do Bazel seja reiniciado (por exemplo, mudando as opções de inicialização).

Um bom cache de execução também é valioso para o desempenho do build. Um cache de execução pode ser mantido localmente em disco ou remotamente. O cache pode ser compartilhado entre os servidores do Bazel e entre os desenvolvedores.

Evitar descartar o cache de análise

O Bazel vai imprimir um aviso se o cache de análise tiver sido descartado ou o servidor for reiniciado. Evite o seguinte durante o uso iterativo:

  • Lembre-se de mudar as flags bazel no meio de um fluxo de trabalho iterativo. Por exemplo, misturar um bazel build -c opt com um bazel cquery faz com que cada comando descarte o cache de análise do outro. Em geral, tente usar um conjunto fixo de sinalizações durante um fluxo de trabalho específico.

  • Se você perder o servidor do Bazel, o cache de análise será perdido. O servidor do Bazel tem um tempo de inatividade configurável. Após esse tempo, ele é encerrado. Você pode configurar esse tempo por meio do arquivo Bazel para atender às suas necessidades. O servidor também é reiniciado quando as sinalizações de inicialização são alteradas. Portanto, evite alterá-las, se possível.

  • Cuidado: o servidor do Bazel será eliminado se você pressionar Ctrl-C repetidamente enquanto o Bazel estiver em execução. É tentador tentar economizar tempo interrompendo um build em execução que não é mais necessário, mas pressione Ctrl-C apenas uma vez para solicitar o término sem dificuldades da invocação atual.

  • Se você quiser usar vários conjuntos de sinalizações do mesmo espaço de trabalho, poderá usar várias bases de saída distintas, alternadas com a sinalização --output_base. Cada base de saída recebe um servidor Bazel próprio.