Esta página descreve workers multiplex, como escrever regras compatíveis com multiplex e soluções alternativas para determinadas limitações.
Os workers multiplex permitem que o Bazel processe várias solicitações com um único processo de worker. Para workers multithread, o Bazel pode usar menos recursos para alcançar o mesmo desempenho ou até mesmo um melhor. Por exemplo, em vez de ter um processo de worker por worker, o Bazel pode ter quatro workers multiplexados que se comunicam com o mesmo processo de worker, que pode processar solicitações em paralelo. Para linguagens como Java e Scala, isso economiza tempo de aquecimento da JVM e tempo de compilação JIT e, em geral, permite usar um cache compartilhado entre todos os workers do mesmo tipo.
Visão geral
Há duas camadas entre o servidor do Bazel e o processo do worker. Para algumas
mnemônicas que podem executar processos em paralelo, o Bazel recebe um WorkerProxy
do
pool de workers. O WorkerProxy
encaminha as solicitações para o processo do worker
sequencialmente com um request_id
. O processo do worker processa a solicitação
e envia respostas para o WorkerMultiplexer
. Quando o WorkerMultiplexer
recebe uma resposta, ele analisa o request_id
e encaminha as respostas
de volta para o WorkerProxy
correto. Assim como em workers não multiplexados, toda
a comunicação é feita por entrada/saída padrão, mas a ferramenta não pode usar
stderr
para saída visível ao usuário (consulte abaixo).
Cada worker tem uma chave. O Bazel usa o código hash da chave (composto de variáveis
de ambiente, raiz de execução e mnemônico) para determinar qual
WorkerMultiplexer
usar. Os WorkerProxy
s se comunicam com o mesmo
WorkerMultiplexer
se tiverem o mesmo código hash. Portanto, supondo
que as variáveis de ambiente e a raiz de execução sejam as mesmas em uma única invocação
do Bazel, cada mnemônico exclusivo só pode ter um WorkerMultiplexer
e um
processo de worker. O número total de workers, incluindo workers regulares e
WorkerProxy
s, ainda é limitado por --worker_max_instances
.
Como escrever regras compatíveis com multiplexação
O processo do worker da regra precisa ter vários threads para aproveitar
vários workers. O Protobuf permite que um conjunto de regras analise uma única solicitação, mesmo
que haja várias solicitações acumuladas no stream. Sempre que o
processo de worker analisar uma solicitação do stream, ele precisará processar a solicitação em
uma nova linha de execução. Como diferentes linhas de execução podem ser concluídas e gravadas no stream ao
mesmo tempo, o processo de worker precisa garantir que as respostas sejam gravadas
de forma atômica (as mensagens não se sobrepõem). As respostas precisam conter o
request_id
da solicitação que estão processando.
Como processar a saída multiplex
Os workers de multiplex precisam ter mais cuidado ao processar a saída do que
os workers de singleplex. Tudo o que for enviado para stderr
vai ser enviado para um único arquivo de registro
compartilhado entre todos os WorkerProxy
s do mesmo tipo,
intercalado aleatoriamente entre solicitações simultâneas. Embora redirecionar stdout
para stderr
seja uma boa ideia, não colete essa saída no campo output
de WorkResponse
, porque isso pode mostrar ao usuário partes danificadas da saída.
Se a ferramenta enviar apenas a saída orientada ao usuário para stdout
ou stderr
, será necessário mudar esse comportamento antes de ativar os workers multiplex.
Como ativar workers multiplex
Os workers de multiplex não são ativados por padrão. Uma regra pode ativar workers
multiplex usando a tag supports-multiplex-workers
no
execution_requirements
de uma ação, assim como a tag supports-workers
ativa workers regulares. Assim como no caso de workers normais, uma estratégia de worker precisa ser especificada no nível da regra (por exemplo, --strategy=[some_mnemonic]=worker
) ou geralmente no nível da estratégia (por exemplo, --dynamic_local_strategy=worker,standalone
). Nenhuma flag adicional é necessária, e supports-multiplex-workers
tem precedência sobre supports-workers
, se ambos estiverem definidos. É possível desativar os workers de multiplexação
globalmente transmitindo --noexperimental_worker_multiplex
.
Recomenda-se que uma regra de conjunto de regras use workers multiplex, se possível, para reduzir a pressão da memória e melhorar o desempenho. No entanto, no momento, os workers multiplex não são compatíveis com a execução dinâmica, a menos que implementem o sandboxing multiplex. A tentativa de executar workers multiplexados sem sandbox com execução dinâmica vai usar workers singleplex em sandbox em silêncio.
Sandbox de multiplex
Os workers multiplexados podem ser colocados em sandbox adicionando suporte explícito a eles nas implementações de workers. Embora o sandbox de worker singleplex possa ser feito executando cada processo de worker no próprio sandbox, os workers multiplex compartilham o diretório de trabalho do processo entre várias solicitações paralelas. Para permitir o sandbox de workers multiplex, o worker precisa oferecer suporte à leitura e gravação em um subdiretório especificado em cada solicitação, em vez de diretamente no diretório de trabalho.
Para oferecer suporte ao sandbox múltiplo, o worker precisa usar o campo sandbox_dir
do WorkRequest
e usá-lo como um prefixo para todas as leituras e gravações de arquivos.
Embora os campos arguments
e inputs
permaneçam inalterados em relação a uma solicitação
sem sandbox, as entradas reais são relativas ao sandbox_dir
. O worker precisa
traduzir os caminhos de arquivo encontrados em arguments
e inputs
para ler a partir desse
caminho modificado e também gravar todas as saídas relacionadas ao sandbox_dir
.
Isso inclui caminhos como '.', bem como caminhos encontrados em arquivos especificados
nos argumentos (como argumentos "argfile").
Quando um worker oferece suporte a sandboxes multiplex, a regra pode declarar esse
suporte adicionando supports-multiplex-sandboxing
ao
execution_requirements
de uma ação. O Bazel vai usar o sandbox múltiplo
se a flag --experimental_worker_multiplex_sandboxing
for transmitida ou se
o worker for usado com execução dinâmica.
Os arquivos de um worker multiplexado em sandbox ainda são relativos ao
diretório de trabalho do processo do worker. Portanto, se um arquivo for
usado para executar o worker e como entrada, ele precisará ser especificado como
uma entrada no argumento flagfile, bem como em tools
, executable
ou
runfiles
.