Optimiser les temps de build avec Bazel et Buildfarm
Introduction
L'optimisation des temps de build est cruciale pour maintenir une cadence de développement rapide et efficace dans les pipelines d'intégration continue.
Sur un projet client, nous avons créés un mono-repository qui contient désormais ~40 micro-services, principalement en Go comme des APIs, des consumers Kafka, des workers Temporal et également 4 projets front en React et TypeScript.
Bazel s'occupe des construire jusqu'aux images de conteneurs, de les pousser sur une registry et de créer les manifests de déploiement Kubernetes. Nous suivons la philosophie GitOps à 100%.
Pour construire ces projets et les déployer dans notre CI/CD, nous utilisons Bazel, un outil de build open-source développé par Google.
Il offre des fonctionnalités puissantes pour accélérer ce processus.
Lorsqu'il est combiné avec Buildfarm, une solution de build et de cache distribué, les gains de performance peuvent être significatifs.
Dans cet article, je vais vous partager quelques options de configuration que nous avons ajoutés à notre fichier .bazelrc
afin d'obtenir des builds plus rapides.
Comment fonctionne Bazel ?
Sans m'étoffer sur le sujet, Bazel est un système de build et de gestion de dépendances qui prend en charge plusieurs langages de programmation.
Il est conçu pour être rapide, fiable et capable de gérer des projets variés et de grande envergure.
Voici quelques-unes de ses principales fonctionnalités :
- Builds Incrémentaux : Bazel ne reconstruit que les parties du projet qui ont changées, le reste est en cache,
- Parallélisation : Il exécute les actions de build en parallèle pour accélérer le processus,
- Reproductibilité : Les builds sont reproductibles, ce qui garantit que le même code produit les mêmes résultats à chaque fois.
Qu'est-ce que Buildfarm ?
Buildfarm est une solution de cache et de build distribué qui permet d'exécuter des builds Bazel sur plusieurs machines.
En distribuant les tâches de build, Buildfarm peut réduire considérablement le temps nécessaire pour compiler de grands projets.
Il s'intègre avec plusieurs outils et particulièrement parfaitement avec Bazel.
Optimisation du Fichier .bazelrc
Passons au vif du sujet, voici quelques options que j'ai pu identifier parmis les options disponibles afin d'accélérer les temps de build.
Dans le cadre de notre projet, lorsqu'un changement minime est fait, notre job de CI/CD ne prend que 3 minutes à être relancé, pour construire l'ensemble des 40 services.
Le fichier .bazelrc
est essentiel pour configurer les options de build dans Bazel. Voici quelques options clés à inclure pour améliorer les temps de build :
Mode de compilation rapide
build --compilation_mode=fastbuild
Utilisez le mode de compilation fastbuild pour accélérer le processus de build en sacrifiant certaines optimisations.
Réutilisation des répertoires sandbox
build --reuse_sandbox_directories
Réutilisez les répertoires sandbox pour éviter de recréer des environnements d'exécution à chaque build.
Désactivation de la vérification des fichiers de dépôt externes
build --noexperimental_check_external_repository_files
Désactivez la vérification expérimentale des fichiers de dépôt externes pour accélérer le processus de build.
Désactivation du stockage des métadonnées de cache d'action
build --noexperimental_action_cache_store_output_metadata
Désactivez le stockage expérimental des métadonnées de cache d'action pour réduire le temps de build.
Exécution parallèle des analyses Skyframe
build --experimental_merged_skyframe_analysis_execution
Activez l'exécution parallèle des analyses Skyframe pour accélérer l'analyse des dépendances.
Utilisation d'un cache Merkle distribué
build --experimental_remote_merkle_tree_cache
Utilisez un cache Merkle distribué pour stocker et récupérer les artefacts de build de manière efficace.
Utilisation de hardlinks pour le cache de dépôt
build --experimental_repository_cache_hardlinks
Utilisez des hardlinks pour le cache de dépôt afin de réduire l'espace disque utilisé et d'accélérer l'accès aux fichiers.
Protection contre les changements concurrents
build --experimental_guard_against_concurrent_changes
Protégez-vous contre les changements concurrents qui peuvent interférer avec le processus de build.
Réduction des téléchargements depuis le cache distant
build --remote_download_outputs=minimal
Réduisez le nombre de fichiers téléchargés depuis le cache distant pour accélérer les builds.
Pour les tests
test --build_tests_only
Construisez uniquement ce qui est nécessaire pour les tests, ce qui accélère grandement lorsque vous targettez tout le projet.
Environnement d'action strict et sortie complète des tests
test --incompatible_strict_action_env --test_output=all
Utilisez un environnement d'action strict et générez une sortie complète des tests pour une meilleure traçabilité et des performances accrues.
Bonnes pratiques générales
Ces options viennent améliorer les builds mais il faut bien garder en tête ces quelques règles afin de garder des builds rapides :
- Réduction des Dépendances : Simplifiez vos fichiers
BUILD
etWORKSPACE
pour minimiser les dépendances, - Machines puissantes : Exécutez les builds sur des machines avec du CPU et de RAM, Bazel utilise beaucoup de ressources,
- Profilage : Utilisez les outils de profilage (
--profile
) de Bazel pour identifier et résoudre les goulots d'étranglement.
Conclusion
En configurant correctement Bazel et Buildfarm, et en optimisant votre fichier .bazelrc
, vous pouvez réduire considérablement les temps de build.
Ces optimisations permettent de maintenir une cadence de développement rapide et efficace, même pour les projets de grande envergure.
N'hésitez pas à expérimenter et à adapter ces configurations en fonction des besoins spécifiques de votre projet.