Nesta página, descrevemos os workers multiplex, como escrever arquivos regras e soluções alternativas para determinadas limitações.
Os workers multiplex permitem que o Bazel processe várias solicitações com um único worker de desenvolvimento de software. Para workers com várias linhas de execução, o Bazel pode usar menos recursos para com desempenho igual ou melhor. Por exemplo, em vez de ter um processo de worker por worker, o Bazel pode ter quatro workers multiplexados conversando do mesmo processo worker, que pode processar solicitações em paralelo. Para linguagens, como Java e Scala, isso economiza o tempo de aquecimento da JVM e a compilação do JIT tempo de atividade e, em geral, permite o uso de um cache compartilhado entre todos os workers da do mesmo tipo.
Visão geral
Há duas camadas entre o servidor do Bazel e o processo do worker. Para determinados
mnemônicas que podem executar processos em paralelo, o Bazel recebe uma WorkerProxy
do
no pool de workers. O WorkerProxy
encaminha solicitações para o processo do worker
sequencialmente com um request_id
, o processo do worker processa a solicitação
e envia respostas para a WorkerMultiplexer
. Quando a solicitação WorkerMultiplexer
recebe uma resposta, ele analisa o request_id
e encaminha as respostas
para o WorkerProxy
correto. Assim como nos workers não multiplexados,
a comunicação é feita na entrada/saída padrão, mas a ferramenta não pode simplesmente usar
stderr
para saída visível ao usuário (confira abaixo).
Cada worker tem uma chave. O Bazel usa o código hash da chave (composto do código
variáveis, a raiz de execução e a mnemônica) para determinar
WorkerMultiplexer
para usar. WorkerProxy
s se comunicam com a mesma
WorkerMultiplexer
se tiverem o mesmo código hash. Portanto, presumindo
as variáveis de ambiente e a raiz de execução são as mesmas em um único Bazel
invocação, cada mnemônico único só pode ter um WorkerMultiplexer
e um
processo do 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
workers multiplex. O protobuf permite que um conjunto de regras analise uma única solicitação, mesmo
embora possa haver várias solicitações se acumulando no stream. Sempre que o
processamento do worker analisa uma solicitação a partir do stream, deve lidar com a solicitação
uma nova conversa. Como um thread diferente pode concluir e gravar no stream em
ao mesmo tempo, o processo do worker precisa garantir que as respostas sejam gravadas
atomicamente (as mensagens não se sobrepõem). As respostas devem conter o
request_id
da solicitação que está processando.
Como gerenciar saídas multiplex
Os workers multiplex precisam ser mais cuidadosos ao lidar com a saída do que
workers singleplex. Tudo o que for enviado para stderr
será armazenado em um único arquivo de registros
compartilhados entre todos os WorkerProxy
s do mesmo tipo,
aleatoriamente entre solicitações simultâneas. Ao redirecionar stdout
em stderr
é uma boa ideia, não colete essa saída no output
de WorkResponse
, porque isso pode mostrar ao usuário partes da saída prejudicadas.
Caso sua ferramenta envie apenas saídas orientadas ao usuário para stdout
ou stderr
, você
é necessário mudar esse comportamento antes de ativar os workers multiplex.
Como ativar workers multiplex
Os workers multiplex não estão ativados por padrão. Um conjunto de regras pode ativar a multiplexação
workers usando a tag supports-multiplex-workers
no
execution_requirements
de uma ação, assim como a tag supports-workers
permite workers regulares). Como acontece com os workers regulares, um worker
estratégia precisa ser especificada, seja no nível do conjunto de regras (por exemplo,
--strategy=[some_mnemonic]=worker
) ou geralmente no nível da estratégia (para
exemplo, --dynamic_local_strategy=worker,standalone
.) Nenhuma sinalização adicional
necessário, e supports-multiplex-workers
tem precedência sobre
supports-workers
, se ambos estiverem definidos. É possível desativar os workers multiplex
globalmente transmitindo --noworker_multiplex
.
Um conjunto de regras é incentivado a usar workers multiplex, se possível, para reduzir a memória se pressionar e melhorar o desempenho. No entanto, os workers multiplex não estão são compatíveis com a execução dinâmica, a menos que implementar o sandbox multiplex. Tentativa de executar multiplex sem sandbox os workers com execução dinâmica usam o modo sandbox silenciosa workers singleplex.
Sandbox multiplex
Os workers multiplex podem ser colocados no sandbox com a adição de suporte explícito a eles no implementações de worker. O sandbox do worker singleplex pode ser feito que executam cada processo de worker em seu próprio sandbox, os workers multiplex compartilham o processar o diretório de trabalho entre várias solicitações paralelas. Para permitir sandbox de workers multiplex, o worker precisa oferecer suporte à leitura de gravar em um subdiretório especificado em cada solicitação, em vez de diretamente em o diretório de trabalho.
Para oferecer suporte ao sandbox multiplex, o worker precisa usar o campo sandbox_dir
do WorkRequest
e o use como prefixo para todas as leituras e gravações de arquivos.
Embora os campos arguments
e inputs
permaneçam inalterados em um ambiente sem sandbox
as entradas reais são relativas à sandbox_dir
. O worker precisa
traduzir caminhos de arquivos encontrados em arguments
e inputs
para ler a partir deste
caminho modificado e também precisa gravar todas as saídas relativas a sandbox_dir
.
Isso inclui caminhos como ".", bem como aqueles encontrados em arquivos especificados
nos argumentos (como argumentos "argfile").
Quando um worker oferece suporte ao sandbox multiplex, o conjunto de regras pode declarar essa
adicionando supports-multiplex-sandboxing
ao
execution_requirements
de uma ação. O Bazel vai usar o sandbox multiplex
se a sinalização --experimental_worker_multiplex_sandboxing
for passada ou se
o worker é usado com a execução dinâmica.
Os arquivos de um worker multiplex no sandbox ainda são relativos ao
de trabalho do processo do worker. Assim, se um arquivo for
usado tanto para executar o worker quanto como uma entrada, ele deve ser especificado tanto como
uma entrada no argumento flagfile, bem como em tools
, executable
ou
runfiles