En esta página, se describen los trabajadores de multiplexación, cómo escribir reglas compatibles con la multiplexación y las soluciones alternativas para ciertas limitaciones.
Los trabajadores de multiplexación permiten que Bazel controle varias solicitudes con un solo proceso de trabajador. En el caso de los trabajadores de subprocesos múltiples, Bazel puede usar menos recursos para lograr el mismo rendimiento o uno mejor. Por ejemplo, en lugar de tener un proceso de trabajador por trabajador, Bazel puede tener cuatro trabajadores multiplexados que se comuniquen con el mismo proceso de trabajador, que luego puede controlar las solicitudes en paralelo. En lenguajes como Java y Scala, esto ahorra tiempo de inicio de la JVM y de compilación JIT, y, en general, permite usar una caché compartida entre todos los trabajadores del mismo tipo.
Descripción general
Hay dos capas entre el servidor de Bazel y el proceso de trabajador. Para ciertas mnemónicas que pueden ejecutar procesos en paralelo, Bazel obtiene un WorkerProxy
del grupo de trabajadores. El WorkerProxy
reenvía las solicitudes al proceso de trabajador de forma secuencial junto con un request_id
. El proceso de trabajador procesa la solicitud y envía respuestas al WorkerMultiplexer
. Cuando el WorkerMultiplexer
recibe una respuesta, analiza el request_id
y, luego, reenvía las respuestas al WorkerProxy
correcto. Al igual que con los trabajadores no multiplexados, toda la comunicación se realiza a través de la entrada y salida estándar, pero la herramienta no puede usar stderr
para la salida visible para el usuario (consulta a continuación).
Cada trabajador tiene una llave. Bazel usa el código hash de la clave (compuesto por variables de entorno, la raíz de ejecución y la mnemónica) para determinar qué WorkerMultiplexer
usar. Los WorkerProxy
se comunican con el mismo WorkerMultiplexer
si tienen el mismo código hash. Por lo tanto, si se supone que las variables de entorno y la raíz de ejecución son las mismas en una sola invocación de Bazel, cada mnemónico único solo puede tener un proceso de WorkerMultiplexer
y un proceso de trabajador. La cantidad total de trabajadores, incluidos los trabajadores habituales y los WorkerProxy
, sigue limitada por --worker_max_instances
.
Cómo escribir reglas compatibles con el multiplexado
El proceso de trabajador de la regla debe ser de varios subprocesos para aprovechar los trabajadores de multiplexación. Protobuf permite que un conjunto de reglas analice una sola solicitud, aunque haya varias solicitudes acumulándose en el flujo. Cada vez que el proceso de trabajador analiza una solicitud de la transmisión, debe controlar la solicitud en un nuevo subproceso. Debido a que diferentes subprocesos podrían completar y escribir en el flujo al mismo tiempo, el proceso de trabajador debe asegurarse de que las respuestas se escriban de forma atómica (los mensajes no se superpongan). Las respuestas deben contener el request_id
de la solicitud que están controlando.
Cómo controlar la salida de multiplex
Los trabajadores de multiplexación deben tener más cuidado al manipular su producción que los trabajadores de simplex. Todo lo que se envíe a stderr
se registrará en un solo archivo de registro compartido entre todos los objetos WorkerProxy
del mismo tipo, intercalado de forma aleatoria entre las solicitudes simultáneas. Si bien es una buena idea redireccionar stdout
a stderr
, no recopiles ese resultado en el campo output
de WorkResponse
, ya que eso podría mostrarle al usuario fragmentos de resultados dañados.
Si tu herramienta solo envía resultados orientados al usuario a stdout
o stderr
, deberás cambiar ese comportamiento antes de habilitar los trabajadores de multiplexación.
Cómo habilitar trabajadores de multiplexación
Los trabajadores de multiplexación no están habilitados de forma predeterminada. Un conjunto de reglas puede activar trabajadores de multiplexación con la etiqueta supports-multiplex-workers
en el execution_requirements
de una acción (al igual que la etiqueta supports-workers
habilita a los trabajadores normales). Al igual que cuando se usan trabajadores normales, se debe especificar una estrategia de trabajador, ya sea a nivel del conjunto de reglas (por ejemplo, --strategy=[some_mnemonic]=worker
) o, en general, a nivel de la estrategia (por ejemplo, --dynamic_local_strategy=worker,standalone
). No se necesitan marcas adicionales, y supports-multiplex-workers
tiene prioridad sobre supports-workers
si se configuran ambos. Puedes desactivar los trabajadores de multiplexación de forma global pasando --noworker_multiplex
.
Se recomienda que un conjunto de reglas use trabajadores de multiplexación si es posible, para reducir la presión de la memoria y mejorar el rendimiento. Sin embargo, los trabajadores de multiplexación no son compatibles con la ejecución dinámica, a menos que implementen el aislamiento de multiplexación. Si intentas ejecutar trabajadores de multiplexación sin zona de pruebas con ejecución dinámica, se usarán de forma silenciosa trabajadores de multiplexación única con zona de pruebas.
Zona de pruebas de multiplex
Los trabajadores de multiplexación se pueden ejecutar en un entorno de pruebas agregando compatibilidad explícita para ellos en las implementaciones de trabajadores. Si bien el aislamiento de procesos de trabajo de un solo plex puede realizarse ejecutando cada proceso de trabajo en su propio aislamiento, los procesos de trabajo de multiplex comparten el directorio de trabajo del proceso entre varias solicitudes paralelas. Para permitir el aislamiento de los trabajadores de multiplexación, el trabajador debe admitir la lectura y escritura en un subdirectorio especificado en cada solicitud, en lugar de hacerlo directamente en su directorio de trabajo.
Para admitir el aislamiento de zona de pruebas múltiple, el trabajador debe usar el campo sandbox_dir
de WorkRequest
y usarlo como prefijo para todas las lecturas y escrituras de archivos.
Si bien los campos arguments
y inputs
no cambian con respecto a una solicitud que no se encuentra en el entorno de pruebas, las entradas reales son relativas a sandbox_dir
. El trabajador debe traducir las rutas de acceso de archivos que se encuentran en arguments
y inputs
para leer desde esta ruta de acceso modificada, y también debe escribir todas las salidas en relación con sandbox_dir
.
Esto incluye rutas de acceso como ".", así como las que se encuentran en los archivos especificados en los argumentos (como los argumentos "argfile").
Una vez que un trabajador admite el aislamiento de múltiples procesos, el conjunto de reglas puede declarar esta compatibilidad agregando supports-multiplex-sandboxing
al execution_requirements
de una acción. Luego, Bazel usará el aislamiento de zona de pruebas múltiplex si se pasa la marca --experimental_worker_multiplex_sandboxing
o si se usa el trabajador con la ejecución dinámica.
Los archivos de trabajo de un trabajador de multiplexación en zona de pruebas siguen siendo relativos al directorio de trabajo del proceso de trabajador. Por lo tanto, si un archivo se usa para ejecutar el trabajador y como entrada, se debe especificar como entrada en el argumento flagfile y en tools
, executable
o runfiles
.