Bazel es complejo y realiza muchas acciones diferentes durante una compilación, algunas de las cuales pueden tener un impacto en el rendimiento de la compilación. En esta página, se intenta asignar algunos de estos conceptos de Bazel a sus implicaciones en el rendimiento de la compilación. Si bien no es exhaustivo, incluimos algunos ejemplos de cómo detectar problemas de rendimiento de la compilación mediante la extracción de métricas y qué puedes hacer para solucionarlos. Con esto, esperamos que puedas aplicar estos conceptos cuando investigues las regresiones del rendimiento de la compilación.
Compilaciones limpias en comparación con compilaciones incrementales
Una compilación limpia es aquella que compila todo desde cero, mientras que una compilación incremental reutiliza parte del trabajo ya completado.
Te sugerimos que observes las compilaciones limpias e incrementales por separado, en especial cuando recopilas o agregas métricas que dependen del estado de las memorias caché de Bazel (por ejemplo, las métricas de tamaño de solicitud de compilación). También representan dos experiencias de usuario diferentes. También representan dos experiencias de usuario diferentes.
Puede usar el campo CumulativeMetrics.num_analyses en el BEP para clasificar
compilaciones. Si num_analyses <= 1, es una compilación limpia; de lo contrario, podemos
categorizarla ampliamente como una compilación incremental; el usuario podría haber cambiado
a diferentes indicadores o diferentes objetivos, lo que provocaría una compilación efectivamente limpia. Cualquier
definición más rigurosa de incrementalidad probablemente tendrá que presentarse en forma
de heurística, por ejemplo, observando el número de paquetes cargados
(PackageMetrics.packages_loaded).
Es probable que cualquier definición más rigurosa de incrementalidad deba presentarse en forma de heurística, por ejemplo, observar la cantidad de paquetes cargados (`PackageMetrics.packages_loaded`).
Métricas de compilación deterministas como proxy para el rendimiento de la compilación Medir el rendimiento de la compilación puede ser difícil debido a la naturaleza no determinista de ciertas métricas (por ejemplo, el tiempo de CPU de Bazel o los tiempos de cola en un clúster remoto).
Por lo tanto, puede ser útil usar métricas deterministas como proxy para la cantidad de trabajo que realiza Bazel, lo que, a su vez, afecta su rendimiento. El tamaño de una solicitud de compilación puede tener una implicación significativa en el rendimiento de la compilación. Una compilación más grande podría representar más trabajo en el análisis y la construcción de los gráficos de compilación.
El crecimiento orgánico de las compilaciones se produce de forma natural con el desarrollo, ya que se agregan o crean más dependencias y, por lo tanto, aumentan en complejidad y se vuelven más costosas de compilar.
PackageMetrics.packages_loaded: el número de paquetes cargados correctamente. `PackageMetrics.packages_loaded`: Es la cantidad de paquetes cargados correctamente. Una regresión aquí representa más trabajo que debe hacerse para leer y analizar cada archivo BUILD adicional en la fase de carga.- Una regresión aquí representa más trabajo que se debe realizar para leer y analizar cada archivo BUILD adicional en la fase de carga.
- Esto suele deberse a la adición de dependencias y a la necesidad de cargar su cierre transitivo.
TargetMetrics.targets_configured: que representa la cantidad de objetivos y aspectos configurados en la compilación. `TargetMetrics.targets_configured`: Representa la cantidad de destinos y aspectos configurados en la compilación.- Una regresión representa más trabajo en la construcción y el recorrido del gráfico de destino configurado.
- Utiliza cquery para encontrar dónde se podrían haber añadido nuevas dependencias.
ActionSummary.actions_created: representa las acciones creadas en la compilación, y una regresión representa más trabajo en la construcción del gráfico de acciones. `ActionSummary.actions_created`: Representa las acciones creadas en la compilación, y una regresión representa más trabajo en la construcción del gráfico de acciones. Tenga en cuenta que esto también incluye acciones no utilizadas que podrían no haber sido ejecutadas.- Usa aquery para depurar regresiones; te
sugerimos empezar con
--output=summaryantes de profundizar con--skyframe_state.
- Usa aquery para depurar regresiones; te
sugerimos empezar con
ActionSummary.actions_executed: el número de acciones ejecutadas, una regresión representa directamente más trabajo en la ejecución de estas acciones.- `ActionSummary.actions_executed`: Es la cantidad de acciones ejecutadas. Una regresión representa directamente más trabajo en la ejecución de estas acciones.
ActionDataEl BEP escribe las estadísticas de acción `ActionData` que muestran los tipos de acción más ejecutados.--experimental_record_metrics_for_all_mnemonics - Esto debería ayudarte a averiguar qué tipo de acciones se ejecutaron (adicionalmente).
- `ActionSummary.actions_executed`: Es la cantidad de acciones ejecutadas. Una regresión representa directamente más trabajo en la ejecución de estas acciones.
BuildGraphSummary.outputArtifactCount: el número de artefactos creados por las acciones ejecutadas.- `BuildGraphSummary.outputArtifactCount`: Es la cantidad de artefactos creados por las acciones ejecutadas.
Estas métricas se ven afectadas por el estado de la caché local, por lo que querrá asegurarse de que las compilaciones de las que extrae estas métricas sean compilaciones limpias.
Todas estas métricas se ven afectadas por el estado de la caché local, por lo que deberás asegurarte de que las compilaciones de las que extraes estas métricas sean **compilaciones limpias**.
Observamos que una regresión en cualquiera de estas métricas puede ir acompañada de regresiones en el tiempo real, el tiempo de CPU y el uso de memoria.
Uso de recursos locales
Bazel consume una variedad de recursos en tu máquina local (tanto para analizar el gráfico de compilación y controlar la ejecución como para ejecutar acciones locales), lo que puede afectar el rendimiento o la disponibilidad de tu máquina para realizar la compilación y otras tareas.
Tiempo transcurrido Puedes
usar bazel-bench para obtener un benchmark
de estas métricas, y con un número suficiente de --runs, puedes aumentar
la significación estadística de tu medición.
El tiempo real es el tiempo transcurrido en el mundo real.
- Si solo el tiempo real se degrada, sugerimos recopilar un perfil de seguimiento JSON y buscar diferencias. De lo contrario, probablemente sería más eficiente investigar otras métricas regresadas, ya que podrían haber afectado el tiempo real.
El tiempo de CPU es el tiempo que la CPU dedica a ejecutar código de usuario.
- Si el tiempo de CPU retrocede entre dos confirmaciones de proyecto, sugerimos
recopilar un perfil de CPU de Starlark. Probablemente también deberías usar
--nobuildpara restringir la compilación a la fase de análisis, ya que es donde se realiza la mayor parte del trabajo pesado de la CPU.
- Si el tiempo de CPU retrocede entre dos confirmaciones de proyecto, sugerimos
recopilar un perfil de CPU de Starlark. Probablemente también deberías usar
Probablemente también deberías usar `--nobuild` para restringir la compilación a la fase de análisis, ya que es donde se realiza la mayor parte del trabajo pesado de la CPU.
- El tiempo del sistema es el tiempo que la CPU dedica al kernel.
Si el tiempo del sistema regresa, se correlaciona principalmente con la E/S cuando Bazel lee archivos de tu sistema de archivos.
Generación de perfiles de carga en todo el sistema--experimental_collect_load_average_in_profiler

Figura 1. **Figura 1:**
Perfil que incluye el promedio de carga del sistema Es posible que quieras considerar
ajustar
--local_cpu_resources
y
--local_ram_resources,
especialmente en entornos de contenedores (al menos hasta que se combine
#16512).
Es posible que desees ajustar `--local_cpu_resources` y `--local_ram_resources`, en especial en entornos de contenedores (al menos hasta que se combine #16512).
Supervisión del uso de memoria de Bazelinfo
bazel info used-heap-size-after-gc: La cantidad de memoria utilizada en bytes después de una llamada aSystem.gc().- `bazel info used-heap-size-after-gc`: Es la cantidad de memoria usada en bytes después de una llamada a `System.gc()`.Bazel bench provides benchmarks for this metric as well.
- Además, hay
peak-heap-size,max-heap-size,used-heap-sizeycommitted-heap-size(consulte la documentación), pero son menos relevantes.
BEP's
MemoryMetrics.peak_post_gc_heap_size: Tamaño del tamaño máximo del montón de la JVM en bytes después de la GC (requiere establecer--memory_profileque intenta forzar una GC completa).
Para analizar la huella de memoria de Bazel en un nivel más detallado, te recomendamos que uses el generador de perfiles de memoria integrado para las reglas.
Generación de perfiles de memoria de trabajadores persistentes Bazel recopila métricas sobre sus trabajadores, en
particular, el campo WorkerMetrics.WorkerStats.worker_memory_in_kb indica cuánta
memoria usan los trabajadores (por mnemotécnico).
El generador de perfiles de seguimiento JSON también recopila el uso de memoria persistente del trabajador durante la invocación al pasar la marca --experimental_collect_system_network_usage (nuevo en Bazel 6.0).

Figura 2. **Figura 2:**
Reducir el valor de
--worker_max_instances
(predeterminado 4) podría ayudar a reducir la cantidad de memoria utilizada por los trabajadores persistentes. Estamos trabajando activamente para que el administrador de recursos y el
planificador de Bazel sean más inteligentes, de modo que este ajuste fino sea necesario con menos frecuencia en el
futuro.
Trabajamos de forma activa para que el administrador de recursos y el programador de Bazel sean más inteligentes, de modo que este ajuste preciso sea menos frecuente en el futuro.
Supervisión del tráfico de red para compilaciones remotas En la ejecución remota, Bazel descarga los artefactos que se compilaron como resultado de la ejecución de acciones.
Si usas la ejecución remota para tus compilaciones, es posible que quieras considerar
supervisar el tráfico de red durante la invocación con el proto
NetworkMetrics.SystemNetworkStats de
BEP (requiere pasar
--experimental_collect_system_network_usage).
Además, los perfiles de seguimiento JSON te permiten
ver el uso de red en todo el sistema durante la compilación si pasas la
--experimental_collect_system_network_usage marca (nueva en Bazel
6.0).

Figura 3. **Figura 3:**
Un uso de red alto pero bastante plano al usar la ejecución remota podría indicar
que la red es el cuello de botella en tu compilación; si aún no la estás usando,
considera activar la compilación sin los bytes pasando
--remote_download_minimal.
Esto acelerará tus compilaciones al evitar la descarga de artefactos intermedios innecesarios.
Otra opción es configurar una caché de disco local para ahorrar ancho de banda de descarga.