Green Coding 3/7: Les images natives pour réduire notre impact environnemental

Thierno Diallo
Just-Tech-IT
Published in
8 min readFeb 29, 2024
springboot native image build

Après avoir introduit les bases fondamentales du green coding et l’aspect gestion durable des données dans les deux premiers articles dont voici les liens

- Green Coding ou comment construire des logiciels durables | by Thierno Diallo | Just-Tech-IT | Medium

- Green Coding 2/8: Principe de la gestion durable des données | by Thierno Diallo | Just-Tech-IT | Medium

Il est temps de commencer à explorer les sujets/outils et pratiques qui permettent de construire des livrables plus efficients, prenant moins place en mémoire, et nécessitant moins de cpu et ram pour s’exécuter.

Dans ce troisième volet de notre série en sept parties, nous aborderons le concept compilation en image native, ainsi que ses apports sur la réduction de notre impact environnemental à travers des stratégies d’optimisation et de réduction des besoins en ressources (énergie, cpu, ram, mémoire). Nous définirons rapidement la compilation native, ensuite nous parlerons de comment elle pourrait aider dans la réduction d’impact environnemental, et enfin nous parlerons de ses limites.

1. Définition

La compilation en image native, ou “native image build”, consiste à compiler le code source d’une application pour le transformer en un binaire exécutable autonome, destiné à une plateforme cible. Cette approche a pour but de créer un exécutable léger, optimisé, autonome et indépendant qui va contenir tout ce qui lui est nécessaire pour son exécution.

Plusieurs outils et Framework sont disponibles pour nous aider à construire des images natives, notamment GraalVM pour Java et Kotlin, PyInstaller et Nuitka pour Python. Ces outils permettent de construire pour plusieurs cibles différentes.

processus de création d’un exécutable natif

2. Gains de la compilation en image native

La compilation de nos applications en image contribue à la réduction de notre empreinte environnementale principalement grâce à son efficience, sa faible empreinte mémoire (Stockage et RAM) dû à la petite taille de l’exécutable, son optimisation pendant le déploiement/démarrage et l’exécution de l’application (CPU).

Ci-après 7 exemples des différentes façons dont l’adoption des images natives peuvent contribuer à réduire notre empreinte environnementale.

1. Utilisation efficiente et optimisé des ressources

La compilation à l’avance, ou “Ahead of time compilation (AOT)”, est l’une des techniques qui apporte le plus de gain à la compilation native. Il intervient après la production du bytecode (jvm) pour produire un exécutable natif.

Impact RAM et CPU

La construction des images natives utilise la technique de compilation à l’avance « Ahead of time (AOT) ». Cette technique permet d’avoir le code source compilé en langage machine, plutôt que de l’interpréter au moment de l’exécution « Just-In-Time (JIT) ».

Ce processus conduit à une utilisation plus efficace des ressources CPU et RAM lors de l’exécution de l’application.

Impact Mémoire

L’une des conséquences de la compilation native est la taille réduite de l’exécutable obtenu et sa petite empreinte mémoire, comparé à des exécutables basés sur JVM.
Si nous prenons un environnement cloud où les ressources sont allouées dynamiquement en fonction de la demande, cette efficience qui réduit la demande en stockage, en consommation de cpu, ram et énergie, tout en accélérant le traitement n’est pas négligeable.

Impact consommation d’Energie

La construction des images natives optimise la consommation des ressources pendant l’exécution, ce qui entraine une réduction de la consommation d’énergie de nos applications et par extension, cela réduit également la consommation des infrastructures sur lesquelles tournent nos applications.

Afin de réduire la consommation d’énergie de nos applications, nous optimisons notre image construite.

Pour optimiser, nous pouvons utiliser l’optimisation guidée par le profilage (PGO) dont voici un exemple :

optimisation

2. Démarrage Rapide

Nous constatons une nette amélioration des temps de démarrage sur les applications construites en image native, contrairement aux applications traditionnelles.

Cette amélioration du temps de démarrage réduit le besoin en énergie et l’impact environnemental global.

A titre d’exemple, je mets ici un benchmark d’une application minimaliste « helloWorld ». Nous avons à la dernière colonne une compilation native, où nous constatons un passage de 136 MB (traditionnel) à 12 MB (native), nous passons de 4 secondes en traditionnel à 12 millisecondes en native pour up.

Pour en savoir plus sur ce sujet, je vous invite à lire cet article que j’avais rédigé en novembre 2021 Efficience des apps java dans le cloud | by Thierno Diallo | Just-Tech-IT | Medium

3. Conteneurisation optimisée

La construction native produit des exécutables légers et autonomes, ce qui les rend parfaitement adapté à la conteneurisation.

Les images de conteneurs plus petites nécessitent moins d’espace disque et de bande passante pour la distribution, réduisant ainsi l’impact environnemental global associé au déploiement à l’exécution et à l’hébergement de nos applications.

4. Reduction du besoin en refroidissement

L’optimisation et la réduction du besoin de ressources occasionne automatiquement une réduction du besoin de refroidissement et donc de la consommation électrique.

5. Reduction des couts d’infrastructure

En optimisant l’utilisation des ressources et en améliorant les performances des applications, la construction d’image native peut aider à réduire les coûts d’infrastructure, notamment :

  • La consommation d’énergie ;
  • Les coûts de stockage, l’utilisation de ram et cpu ;
  • Les besoins en refroidissement ;
  • Les frais de maintenance.

Ces économies de coûts peuvent se traduire par un impact environnemental moindre tout au long du cycle de vie de l’application.

6. Améliorée l’efficience et la scalabilité

Les applications construites avec une technologie d’image native ont une scalabilité plus efficiente, ce qui nous permet de gérer potentiellement plus de charge, sans forcément augmenter de manière considérable l’impact environnemental. Cette scalabilité permet une meilleure utilisation des ressources et réduit le besoin d’une infrastructure matérielle supplémentaire pour répondre à la demande croissante.

7. Encrer le numérique durable et responsable dans nos pratiques

L’adoption de la construction d’images natives, comme pratique incontournable dans le développement de nos applications, favorise une culture d’efficacité et écoresponsable au sein de nos équipes de développement et plus largement dans nos métiers et entreprises. En donnant la priorité à l’optimisation des ressources et à la responsabilité environnementale tout en conservant l’efficacité du service rendu.

Nous pouvons par conséquent minimiser l’empreinte carbone, ainsi que contribuer à la durabilité et l’écoresponsabilité de notre secteurs et des applications que nous produisons et exploitons.

3. Limites de la compilation en image native

Les avantages de la compilation en image native sont indéniables, néanmoins il y a également quelques limites.

Néanmoins, en fonction du besoin final, la compilation native n’est pas automatiquement la bonne solution, il faut bien prendre en compte la volumétrie de l’app pour choisir le mode de compilation.

Si on a besoin d’un throughput (débit) conséquent, il vaut mieux garder une JVM classique qui s’en sortira bien mieux cf. l’image au début de l’article Pedal to the metal: High-performance Java with GraalVM Native Image (oracle.com)

Connaitre et comprendre ces limites est nécessaire pour savoir quand et comment utiliser la compilation native. Je vous propose alors une liste, non exhaustive, de quelques limites :

Fort lien avec l’OS

Le caractère natif fait que l’image est construite pour un os bien précis. Cependant, nous avons la capacité de construire des images natives pour tout type d’OS, donc la limite est négligeable et généralement nous avons notre OS (Système d’exploitation) cible du départ.

Complexité de Debug

A la différence des exécutions traditionnelles, le debug d’une application en image native est beaucoup plus difficile. Il nécessite des outils et techniques spécialisé dont voici quelques exemples :

  • Utiliser le Debugging Symbols ;
  • Utiliser Extensively Logging ;
  • Utiliser l’écosystème GraalVM ;
  • Activer le Remote Debugging, le Core Dumps, ainsi que le Heap Dump Analysis lors de la construction de l’image ;

Prévoir un temps de build plus long, mais cette contrainte peut être gérée avec un peu d’anticipation

Configuration Statique (parler de livereload)

Les constructions d’images natives requièrent une configuration statique des composants et des dépendances, cela limite la flexibilité et le comportement dynamique par rapport aux environnements interprétés ou compilés en JIT.

Néanmoins, cette limite peut être gérée avec le livereload, offert par certains Framework ou écosystèmes.

Le livereload consiste à recharger à chaud la configuration. Toutefois, il convient de ne pas utiliser en production, ou du moins avec parcimonie, et en évaluant les risques convenablement.

Chargement de Classe Dynamique

Le chargement de classe dynamique, une fonctionnalité courante dans les applications Java, peut nécessiter une configuration supplémentaire dans les constructions d’images natives, et cela pourrait impacter le comportement et la compatibilité de l’application. Donc, il faudra en tenir compte pour anticiper le comportement runtime.

Complexité de Gestion de Mémoire

La gestion de mémoire dans les images natives peut différer des environnements d’exécution traditionnels, nous devons gérer plus attentivement et rigoureusement l’utilisation de mémoire et l’allocation de ressources pour éviter les problèmes de performance ou les erreurs d’exécution.

Lister les dépendances nécessaires à l’exécution

Les constructions d’images natives requièrent une déclaration explicite des dépendances nécessaires à l’exécution, ce qui rend essentiel de spécifier et de gérer avec précision les dépendances pour garantir une bonne exécution de l’application.

4. Conclusion

En résumé, les constructions d’images natives offrent plusieurs avantages qui peuvent contribuer à réduire l’empreinte environnementale du développement et du déploiement de nos applications.

En améliorant l’efficacité de l’utilisation des ressources, en optimisant les performances et en faisant des pratiques durables et écoresponsable un point central, la technologie d’image native joue un rôle crucial dans la construction d’un écosystème plus respectueux de l’environnement.

Néanmoins, il reste un outil parmi tant d’autres. Donc, il est à utiliser de manière éclairée, ainsi que de la bonne manière selon les réalités qui s’impose, et enfin en complément de toutes les autres techniques et technologies qui nous permettent de produire les logiciels plus vertueux et écoresponsable.

Chez AXA France, avec la généralisation du CaaS (Container as a Service) (openpaas/kubernetes) comme cible de déploiement, nous avons déjà commencé la pratique de la compilation native. Bien entendu, nous gagnerons à sensibiliser pour mieux optimiser nos images natives et diffuser cette pratique le plus largement possible.

Tout cela sans oublier que ce sujet va forcément tirer d’autres sujets et initiatives comme SlimFaas et le dailyclean qui sont et qui vont largement être utilisés chez AXA France, et qui ont un apport considérable sur la réduction de notre empreinte environnementale.

Dans le prochain article, nous aurons l’occasion de parler green software craftmanship et comment le mettre en place via un cas pratique.

--

--

Thierno Diallo
Just-Tech-IT

Staff Engineer/Technical Leader And Green Champion at Axa France