La ejecución dinámica es una función en Bazel con la que la ejecución local y remota de la misma acción se inician en paralelo, con el resultado de la primera rama que finalice, cancelando la otra rama. Combina la potencia de ejecución o una gran caché compartida de un sistema de compilación remoto con la baja latencia de para la ejecución, lo que ofrece lo mejor de ambos mundos para compilaciones limpias e incrementales. por igual.
En esta página, se describe cómo habilitar, ajustar y depurar la ejecución dinámica. Si tienen configurada la ejecución local y remota e intentan ajustar Bazel para lograr un mejor rendimiento, esta página es para ti. Si aún no tienes configuración de la ejecución remota, ve a Remote Execution de Bazel Overview.
¿Quieres habilitar la ejecución dinámica?
El módulo de ejecución dinámica es parte de Bazel, pero para usar ya debes poder compilar de forma local y remota con la misma configuración de Bazel.
Para habilitar el módulo de ejecución dinámica, pasa --internal_spawn_scheduler
.
a Bazel. Esto agrega una nueva estrategia de ejecución llamada dynamic
. Ahora puedes
use esto como su estrategia para los mnemónicos que desea ejecutar dinámicamente, como
--strategy=Javac=dynamic
Consulta la siguiente sección para saber cómo elegir los mnemónicos
para habilitar la ejecución dinámica.
Para cualquier mnemotécnico que usa la estrategia dinámica, las estrategias de ejecución remota
tomado de la marca --dynamic_remote_strategy
, y las estrategias locales de la
--dynamic_local_strategy
. Aprobación
--dynamic_local_strategy=worker,sandboxed
establece el valor predeterminado de la configuración
de ejecución dinámica para probar con trabajadores o la ejecución de zona de pruebas
en el orden personalizado. Pasar --dynamic_local_strategy=Javac=worker
anula el valor predeterminado para
solo el nombre nemotécnico Javac. La versión remota funciona de la misma manera. Ambas marcas pueden
especificar varias veces. Si una acción no se puede ejecutar localmente, es
se ejecuten de forma remota como de costumbre, y viceversa.
Si tu sistema remoto tiene una caché, la marca --dynamic_local_execution_delay
agrega un retraso en milisegundos a la ejecución local después de que el sistema remoto
indicó un acierto de caché. Esto evita que se ejecute la ejecución local cuando más aciertos de caché
más probables. El valor predeterminado es 1,000 ms, pero debería ajustarse para ser solo un poco
más tiempo del que suelen tardar los aciertos de caché. La hora real depende tanto del control remoto
y el tiempo que demora un recorrido de ida y vuelta. Por lo general, el valor será el mismo
para todos los usuarios de un sistema remoto determinado, a menos que algunos estén lo suficientemente lejos
para agregar latencia de ida y vuelta. Puedes usar la generación de perfiles de Bazel
atributos para ver cuánto tiempo
que toman los aciertos de caché.
La ejecución dinámica se puede usar con la estrategia de zona de pruebas local y con
trabajadores persistentes. Los trabajadores persistentes
ejecutarse con zona de pruebas cuando se usa con ejecución dinámica y no puede usar multiplex
trabajadores. En los sistemas Darwin y Windows, la zona de pruebas
la estrategia puede ser lenta; puedes pasar --reuse_sandbox_directories
para reducir
la sobrecarga de crear zonas de pruebas en estos sistemas.
La ejecución dinámica también puede ejecutarse con la estrategia standalone
, aunque, como
La estrategia standalone
debe tomar el bloqueo de salida cuando comienza a ejecutarse.
bloquea eficazmente la estrategia remota para que no finalice primero. El
La marca --experimental_local_lockfree_output
permite evitar este problema
lo que permite que la ejecución local escriba directamente en la salida, pero que la anule
y la ejecución remota, si esto debería terminar primero.
Si una de las ramas de la ejecución dinámica termina primero, pero es una falla, el falla toda la acción. Esta es una elección deliberada para evitar diferencias entre la ejecución local y remota.
Para obtener más información sobre cómo funciona la ejecución dinámica y su bloqueo, consulta Julio. El excelente blog de Merino publicaciones
¿Cuándo debo usar la ejecución dinámica?
La ejecución dinámica requiere algún tipo de sistema de ejecución remota. En este momento, no es posible utilizar un sistema remoto que solo incluya caché, como un error de caché se consideraría una acción fallida.
No todos los tipos de acciones son adecuados para la ejecución remota. Los mejores candidatos son los que son inherentemente más rápidos a nivel local, por ejemplo, a través de el uso de trabajadores persistentes o aquellos que se ejecutan rápido para que la sobrecarga de la ejecución remota domine el tiempo de ejecución. Desde cada acción ejecutada localmente bloquea una cantidad de recursos de CPU y memoria ejecutar acciones que no pertenecen a esas categorías simplemente retrasa la ejecución para aquellos que sí lo hacen.
Desde el lanzamiento
5.0.0-pre.20210708.4,
la generación de perfiles de rendimiento contiene datos
sobre la ejecución del trabajador, incluido el tiempo dedicado a finalizar una solicitud de trabajo después de
perder una carrera de ejecución dinámica. Si ves subprocesos de trabajador de ejecución dinámica
dedican mucho tiempo a adquirir recursos o a invertir
async-worker-finish
, es posible que tengas algunas acciones locales lentas que retrasan al trabajador
conversaciones.
En el perfil anterior, que usa 8 trabajadores Javac, vemos muchos trabajadores Javac.
perdieron las carreras y terminaron su trabajo en el async-worker-finish
conversaciones. Esto se debe a que un mnemotécnico no trabajador
que tomó suficientes recursos para
retrasar a los trabajadores.
Cuando solo se ejecuta Javac con ejecución dinámica, solo cerca de la mitad de terminan perdiendo la carrera después de comenzar su trabajo.
La marca --experimental_spawn_scheduler
recomendada anteriormente dejó de estar disponible.
Se activa la ejecución dinámica y se establece dynamic
como la estrategia predeterminada para todos.
mnemotécnicas que a menudo
daría lugar a este tipo de problemas.
Rendimiento
El enfoque de ejecución dinámica supone que hay suficientes recursos disponibles de forma local y remota, que vale la pena invertir recursos adicionales para mejorar el rendimiento general. Sin embargo, el uso excesivo de recursos puede ralentizar a Bazel o la máquina en la que se ejecuta o aplicar una presión inesperada a un sistema remoto. Existen varias opciones para cambiar el comportamiento de la ejecución dinámica:
--dynamic_local_execution_delay
retrasa el inicio de una sucursal local en un número
de milisegundos después del inicio de la rama remota, pero solo si
un acierto de caché remota durante la compilación actual. Esto hace que las compilaciones que se beneficien
del almacenamiento en caché remoto no desperdician recursos locales cuando es probable que la mayoría
los resultados de búsqueda
en la caché. Según la calidad de la caché,
Esto podría mejorar las velocidades de compilación, a costa de usar modelos de
de Google Cloud.
--experimental_dynamic_local_load_factor
es un recurso avanzado y experimental
de administración de versiones. Para desactivar esta función, debe tener un valor de 0 a 1.
Cuando se establece en un valor superior a 0, Bazel ajusta la cantidad de
acciones programadas localmente cuando muchas acciones en espera
pueden programarse. Si se establece en 1, se podrán programar tantas acciones como haya
hay CPU disponibles (según --local_cpu_resources
). Los valores más bajos establecen la cantidad
de acciones programadas a un número menor de acciones a medida que aumenta la cantidad de acciones.
que están disponibles para ejecutarse. Esto puede sonar contraintuitivo, pero con un buen control remoto
de procesamiento, la ejecución local no es de mucha ayuda cuando se ejecutan muchas acciones y
usar la CPU local para administrar
acciones remotas.
--experimental_dynamic_slow_remote_time
prioriza el inicio de las sucursales locales
cuando la rama remota se ejecutó
durante al menos este tiempo. Por lo general, el
se le da prioridad a la acción programada más reciente, ya que tiene más probabilidades de
pero si el sistema remoto
a veces se bloquea o tarda más
esto puede hacer que una compilación avance. Esta opción no está habilitada de forma predeterminada
podría ocultar problemas con el sistema remoto que deberían solucionarse. Asegúrate de que
para supervisar el rendimiento del sistema remoto si habilitas esta opción.
Se puede usar --experimental_dynamic_ignore_local_signals
para permitir que el control remoto
que una rama toma el control cuando un engendro local sale debido a una señal determinada. Este es
es útil principalmente junto con los límites de recursos de los trabajadores (consulta
--experimental_worker_memory_limit_mb
,
--experimental_worker_sandbox_hardening
,
y
--experimental_sandbox_memory_limit_mb
)),
en las que los procesos de los trabajadores podrían finalizarse cuando usan demasiados recursos.
El perfil de seguimiento de JSON contiene un de gráficos relacionados con el rendimiento que pueden ayudar a identificar formas de mejorar el la compensación entre el rendimiento y el uso de recursos.
Soluciona problemas
Los problemas con la ejecución dinámica pueden ser sutiles y difíciles de depurar, ya que pueden
el manifiesto solo con algunas combinaciones específicas de ejecución local y remota.
El elemento --debug_spawn_scheduler
agrega resultados adicionales de la ejecución dinámica.
que ayuda a depurar esos problemas. También puedes ajustar el
Marca de --dynamic_local_execution_delay
y cantidad de trabajos remotos y locales para
facilitan la reproducción de los problemas.
Si tienes problemas con la ejecución dinámica con standalone
prueba correr sin --experimental_local_lockfree_output
o ejecuta
tu zona de pruebas de acciones locales. Esto puede ralentizar un poco la compilación (consulta la sección anterior si
está en Mac o Windows), pero quita algunas de las posibles causas de errores.