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. No caso dos workers com várias linhas de execução, o Bazel pode usar menos recursos para alcançar um desempenho igual ou melhor. Por exemplo, em vez de ter um processo de worker por worker, o Bazel pode ter quatro workers multiplexados conversando com o mesmo processo de worker, que podem processar solicitações em paralelo. Para linguagens como Java e Scala, isso economiza o tempo de aquecimento da JVM e o tempo de compilação do JIT e, em geral, permite o uso de 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 determinadas
mnemônicas que podem executar processos em paralelo, o Bazel recebe um WorkerProxy
do
pool de workers. O WorkerProxy
encaminha as solicitações ao 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, em seguida, encaminha as respostas
de volta para o WorkerProxy
correto. Assim como nos workers não multiplexados, toda
a comunicação é feita por entrada/saída padrão, mas a ferramenta não pode usar
stderr
apenas para saídas visíveis ao usuário (confira abaixo).
Cada worker tem uma chave. O Bazel usa o código hash da chave (composto de variáveis
de ambiente, a raiz de execução e o mnemônico) para determinar qual
WorkerMultiplexer
usar. 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 único pode ter apenas 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 multiplex
O processo do worker da regra precisa ter várias linhas de execução para aproveitar
os workers multiplex. O Protobuf permite que um conjunto de regras analise uma única solicitação, mesmo que possa haver várias solicitações se acumulando no stream. Sempre que o
processo do worker analisa uma solicitação do stream, ele precisa processar a solicitação em
uma nova linha de execução. Como uma linha de execução diferente pode ser concluída e gravar no stream ao
mesmo tempo, o processo do worker precisa garantir que as respostas sejam gravadas
atomicamente (as mensagens não se sobrepõem). As respostas precisam conter o
request_id
da solicitação que estão processando.
Como gerenciar saídas multiplex
Os workers multiplex precisam ser mais cuidadosos ao lidar com a saída do que
os workers Singleplex. Qualquer coisa enviada para stderr
vai ficar em 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 partes de saída desorganizadas para o usuário.
Se a ferramenta só envia saídas orientadas ao usuário para stdout
ou stderr
, você
precisará alterar esse comportamento antes de ativar workers multiplex.
Como ativar workers multiplex
Os workers multiplex não estão ativados por padrão. Um conjunto de regras 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. Como acontece com workers regulares, é necessário especificar uma estratégia de worker, seja no nível do conjunto de regras (por exemplo, --strategy=[some_mnemonic]=worker
) ou geralmente no nível da estratégia (por exemplo, --dynamic_local_strategy=worker,standalone
). Nenhuma outra sinalização é necessária, e supports-multiplex-workers
tem precedência sobre supports-workers
se ambas estiverem definidas. É possível desativar os workers multiplex
globalmente transmitindo --noworker_multiplex
.
É recomendado que um conjunto de regras use workers multiplex, se possível, para reduzir a pressão da memória e melhorar o desempenho. No entanto, os workers multiplex atualmente não são compatíveis com a execução dinâmica, a menos que implementem o sandbox multiplex. A tentativa de executar workers multiplex fora do sandbox com a execução dinâmica usará silenciosamente os workers Singleplex no modo sandbox.
Sandbox multiplex
Os workers multiplex podem ser colocados no sandbox com a adição de suporte explícito a eles nas implementações do worker. Embora o sandbox de workers singleplex possa ser feito executando cada processo de worker em um sandbox próprio, 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, e não diretamente no diretório de trabalho.
Para oferecer suporte ao sandbox multiplex, o worker precisa usar o campo sandbox_dir
do WorkRequest
e usá-lo como prefixo de todas as leituras e gravações de arquivos.
Embora os campos arguments
e inputs
permaneçam inalterados de uma solicitação fora do sandbox, as entradas reais são relativas ao sandbox_dir
. O worker precisa
converter os caminhos de arquivo encontrados em arguments
e inputs
para ler esse
caminho modificado e também gravar todas as saídas relativas ao sandbox_dir
.
Isso inclui caminhos como ".", bem como caminhos encontrados em arquivos especificados
nos argumentos (como argumentos "argfile").
Quando um worker oferece suporte ao sandbox multiplex, o conjunto de regras pode declarar esse
suporte adicionando supports-multiplex-sandboxing
ao
execution_requirements
de uma ação. O Bazel usará o sandbox multiplex
se a sinalização --experimental_worker_multiplex_sandboxing
for transmitida ou se
o worker for usado com a execução dinâmica.
Os arquivos de um worker multiplex no sandbox ainda são relativos ao
diretório de trabalho do processo do worker. Assim, se um arquivo for
usado para executar o worker e como uma entrada, ele precisará ser especificado como
uma entrada no argumento flagfile e em tools
, executable
ou
runfiles
.