A execução dinâmica (link em inglês) é um recurso do Bazel em que a execução local e remota a mesma ação são iniciadas em paralelo, usando a saída da primeira ramificação que termina, cancelando a outra ramificação. Ele combina o poder de execução e/ou grande cache compartilhado de um sistema de compilação remota com baixa latência de execução, oferecendo o melhor dos dois mundos para builds limpos e incrementais parecidos.
Esta página descreve como ativar, ajustar e depurar a execução dinâmica. Se você com a execução local e remota configuradas e tentando ajustar o Bazel configurações para melhorar o desempenho, esta página é para você. Se você ainda não tiver configuração da execução remota, acesse a página de Execução remota do Bazel Visão geral.
Ativar a execução dinâmica?
O módulo de execução dinâmica faz parte do Bazel, mas para usar o você já deve ser capaz de compilar local e remotamente a mesma configuração do Bazel.
Para ativar o módulo de execução dinâmica, transmita o --internal_spawn_scheduler
para o Bazel. Isso adiciona uma nova estratégia de execução chamada dynamic
. Agora você pode
use isso como estratégia para as mnemônicas que você quer executar dinamicamente, como
--strategy=Javac=dynamic
: Confira a próxima seção para saber como escolher quais mnemônicas
ativar a execução dinâmica.
Para qualquer mnemônica que use a estratégia dinâmica, as estratégias de execução remota são
retirado da sinalização --dynamic_remote_strategy
e as estratégias locais do
sinalização --dynamic_local_strategy
. Em aprovação
--dynamic_local_strategy=worker,sandboxed
define o padrão para o
de execução dinâmica para testar com workers ou execução em sandbox
ordem. A transmissão de --dynamic_local_strategy=Javac=worker
substitui o padrão
somente mnemônico do Javac. A versão remota funciona da mesma maneira. As duas sinalizações podem
ser especificado várias vezes. Se uma ação não pode ser executada localmente, ela
executada remotamente como de costume e vice-versa.
Se o sistema remoto tiver um cache, a flag --dynamic_local_execution_delay
adiciona um atraso em milissegundos à execução local depois que o sistema remoto
indicou uma ocorrência em cache. Isso evita a execução local quando há mais ocorrências em cache
prováveis. O valor padrão é 1.000 ms, mas deve ser ajustado para ser um pouco menor
mais longa do que as ocorrências em cache costumam levar. O tempo real depende do controle remoto
e o tempo de ida e volta. Normalmente, o valor será o mesmo
para todos os usuários de um determinado sistema remoto, a menos que alguns deles estejam longe o suficiente
para aumentar a latência de ida e volta. É possível usar a criação de perfil do Bazel
atributos para analisar quanto tempo
o número de ocorrências em cache.
A execução dinâmica pode ser usada com a estratégia de sandbox local, bem como com
workers permanentes. Os workers persistentes vão automaticamente
são executados com sandbox quando usado com a execução dinâmica e não podem usar multiplex
workers. Nos sistemas Darwin e Windows, o modelo
estratégia pode ser lenta; é possível transmitir --reuse_sandbox_directories
para reduzir
sobrecarga da criação de sandboxes nesses sistemas.
A execução dinâmica também pode ser realizada com a estratégia standalone
, já que o
A estratégia standalone
precisa usar o bloqueio de saída quando começar a ser executada,
impede que a estratégia remota termine primeiro. O
A flag --experimental_local_lockfree_output
possibilita uma solução com esse problema:
permitindo que a execução local grave diretamente na saída, mas seja cancelada pelo
a execução remota, se isso terminar primeiro.
Se uma das ramificações da execução dinâmica terminar primeiro, mas falhar, o toda a ação falhar. Essa é uma escolha intencional para evitar diferenças entre a execução local e remota passe despercebida.
Para mais informações sobre como a execução dinâmica e o bloqueio funcionam, consulte Julio O excelente blog da Merino postagens
Quando devo usar a execução dinâmica?
A execução dinâmica requer alguma forma de sistema de execução remota. No momento, não é possível usar um sistema remoto somente cache, já que uma ausência no cache é considerada uma ação com falha.
Nem todos os tipos de ações são adequados para execução remota. Os melhores candidatos são aqueles que são naturalmente mais rápidos localmente, por exemplo, através o uso de workers permanentes ou aqueles com execução rápida o suficiente para que o overhead da execução remota domine o tempo de execução. Como cada ação executada localmente bloqueia alguns recursos de CPU e memória, as ações em execução que não se enquadram nessas categorias apenas atrasam a execução para aqueles que têm.
Na versão
5.0.0-pre.20210708.4,
A criação de perfil de desempenho contém dados
sobre a execução de workers, incluindo o tempo gasto para finalizar uma solicitação de trabalho após
perder uma corrida de execução dinâmica. Se as linhas de execução do worker de execução dinâmica forem exibidas
passar muito tempo adquirindo recursos ou muito tempo no
async-worker-finish
, algumas ações locais lentas podem atrasar o worker
fios
No perfil acima, que usa oito workers Javac, vemos muitos workers Javac
depois de perder as corridas e terminar o trabalho na async-worker-finish
fios Isso foi causado por uma mnemônica não relacionada ao trabalho consumindo recursos suficientes para
atrasam os workers.
Quando apenas Javac é executado com execução dinâmica, apenas cerca da metade do tempo iniciado trabalhadores acabam perdendo a corrida depois de iniciar o trabalho.
A sinalização --experimental_spawn_scheduler
recomendada anteriormente foi descontinuada.
Ela ativa a execução dinâmica e define dynamic
como a estratégia padrão para todas as
mnemônicas, o que geralmente levaria a esse tipo de problema.
Desempenho
A abordagem de execução dinâmica pressupõe que há recursos suficientes disponíveis local e remotamente que vale a pena gastar recursos extras para melhorar o desempenho geral. Mas o uso excessivo de recursos pode atrasar o Bazel ou na máquina em que é executado ou colocar uma pressão inesperada em um sistema remoto. Existem várias opções para alterar o comportamento da execução dinâmica:
--dynamic_local_execution_delay
atrasa o início de uma filial local em um número
de milissegundos após o início da ramificação remota, mas somente se houver
uma ocorrência em cache remoto durante a compilação atual. Assim, os builds que se beneficiam
do armazenamento em cache remoto para não desperdiçar recursos locais quando for provável que a maioria
as saídas podem ser encontradas no cache. Dependendo da qualidade do cache,
reduzir isso pode melhorar as velocidades de build, mas requer o uso de mais
do Google Cloud.
O --experimental_dynamic_local_load_factor
é um recurso experimental avançado
de gerenciamento de projetos. É preciso um valor de 0 a 1, 0 para desativar esse recurso.
Quando definido como um valor acima de 0, o Bazel ajusta o número de
as ações programadas localmente quando muitas ações aguardam
ser programados. Se ele for definido como 1, será possível programar quantas ações forem necessárias
são CPUs disponíveis, de acordo com --local_cpu_resources
. Valores mais baixos definem o número
de ações programadas para um número proporcionalmente menor à medida que mais ações são
disponíveis para execução. Isso pode parecer pouco intuitivo, mas com um bom controle remoto
a execução local não ajuda muito quando há muitas ações em execução, e
a CPU local é mais bem gasta gerenciando ações remotas.
--experimental_dynamic_slow_remote_time
prioriza o início de ramificações locais
quando a ramificação remota está em execução há pelo menos esse tempo. Normalmente, o
a ação agendada mais recentemente recebe prioridade, pois tem a maior chance de
vencer a corrida, mas se o sistema remoto às vezes travar ou demorar muito,
isso pode fazer um build avançar. Ele não é ativado por padrão,
pode ocultar problemas com o sistema remoto que devem ser corrigidos. Confirme se
para monitorar o desempenho do sistema remoto se você ativar essa opção.
--experimental_dynamic_ignore_local_signals
pode ser usado para permitir que o controle remoto
ramificação assume quando uma geração local é encerrada devido a um determinado sinal. Isso é
é útil principalmente com os limites de recursos do worker (consulte
--experimental_worker_memory_limit_mb
,
--experimental_worker_sandbox_hardening
,
e
--experimental_sandbox_memory_limit_mb
)),
em que os processos do worker podem ser eliminados quando usam muitos recursos.
O perfil de trace JSON contém um gráficos relacionados ao desempenho que podem ajudar a identificar maneiras de melhorar a do desempenho e do uso de recursos.
Solução de problemas
Problemas com a execução dinâmica podem ser sutis e difíceis de depurar, pois podem
apenas sob algumas combinações específicas de execução local e remota.
--debug_spawn_scheduler
adiciona outra saída da execução dinâmica.
que pode ajudar a depurar esses problemas. Também é possível ajustar
Sinalização --dynamic_local_execution_delay
e número de jobs remotos vs. locais para
facilitar a reprodução dos problemas.
Se você tiver problemas com a execução dinâmica usando o standalone
estratégia, tente executar sem --experimental_local_lockfree_output
ou execute
suas ações locais no sandbox. Isso pode deixar seu build um pouco mais lento. Confira acima
está usando um Mac ou Windows), mas remove algumas possíveis causas de falhas.