Développement éco-responsable : votre code en action
Sommaire
- Introduction
- Optimiser votre code
- Concevoir des interfaces utilisateurs éco-énergétiques
- Optimiser les requêtes et les données
- SQL : vers des requêtes plus efficientes
- Java Hibernate : bonnes pratiques pour un code plus léger
- Gestion des données : minimiser l’impact à chaque étape
- Tests des performances
- Pendant les tests : identifier les gisements d’efficacité
- Pendant le build : appliquer des mesures continues
- Déploiement éco-responsable
- Conclusion
Introduction
Après avoir exploré les frameworks et les architectures, il est temps de plonger au cœur du processus : le développement éco-responsable lui-même. Cette étape, où les lignes de code prennent vie, constitue un levier essentiel pour réduire l’empreinte écologique des logiciels. En adoptant une approche proactive, les développeurs
jouent un rôle clé dans la transformation des objectifs de durabilité en résultats tangibles, contribuant ainsi à une technologie plus respectueuse de l’environnement.
- Intervenants :
Développeurs, ingénieurs en qualité, responsables de l’intégration continue.
- Objectif :
Créer un logiciel performant et éco-responsable. Cela implique l’utilisation de pratiques de codage et de technologies qui minimisent l’empreinte écologique, en réduisant la consommation de ressources et en améliorant l’efficacité énergétique du produit final.
Optimiser votre code
La portée de ce chapitre est vaste, englobant la diversité des technologies, des besoins techniques et fonctionnels. Cependant, l’objectif central réside dans la culture de la pensée critique envers notre code, qu’il s’agisse de révisions de code (“code reviews”) ou de l’utilisation de bases de code héritées (“legacy”).
Il est impératif de maintenir une attitude d’ouverture et de remise en question vis-à-vis de nos convictions et certitudes. Les avancées continues dans les technologies, les langages et les processeurs signifient que nous avons l’opportunité constante d’améliorer notre empreinte en matière de codage.
En fin de compte, l’optimisation du code doit être synonyme d’amélioration continue de notre pratique en matière de développement. C’est une démarche fondamentale afin de rester alignés sur les exigences changeantes et de contribuer de manière significative à la durabilité de notre secteur.
Voici quelques conseils pour optimiser l’efficacité de votre code dans une perspective d’éco-conception :
1- Choisissez des structures de données
appropriées
En sélectionnant les structures de données
judicieuses, qui conviennent le mieux à votre problème, vous pourrez considérablement améliorer les performances et réduire la consommation de mémoire. Vous pouvez par exemple dénormaliser vos bases de données. Cette stratégie est notamment utilisée pour augmenter les performances de ces dernières en regroupant les données redondantes.
Par exemple, si une entreprise possède une
table Clients et une table Commandes, elle peut dénormaliser la base de données en ajoutant une colonne Nombre De Commandes à la table Clients
pour stocker le nombre total de commandes passées pour chaque client.
Toutefois, la dénormalisation doit être utilisée avec prudence, car elle peut augmenter la complexité de la base et donc le maintien de la cohérence des données. Cela peut accélérer les requêtes
qui nécessitent de connaître le nombre total de commandes passées par client, mais cela complique également la mise à jour de la base de données lorsqu’une nouvelle commande est passée.
2- Optez pour des algorithmes efficaces
Recherchez et utilisez des algorithmes
optimisés pour résoudre vos problèmes.
Évaluez systématiquement la complexité de vos algorithmes et bannissez les complexités quadratiques ou pires, car cette complexité a des implications profondes sur l’écologie :
- Impacts directs : Une utilisation intensifiée des processeurs (CPU, GPU, etc.) entraîne une augmentation significative de la consommation d’énergie, ainsi qu’un besoin accru en matériel informatique récent,
capable de supporter les exigences élevées en puissance de calcul imposées par les algorithmes complexes.
- Impacts indirects : L’utilisation intensive des appareils entraîne un raccourcissement de leur durée de vie, augmentant ainsi la quantité de déchets électroniques. De plus, la
chaleur excessive générée par ces appareils nécessite des systèmes de refroidissement plus performants, qui consomment davantage d’énergie et requièrent plus de ressources lors de leur fabrication
3- Gérez la mémoire de manière efficace
L’un des impacts invisibles de l’utilisation excessive de la mémoire est la réduction de la densité de consolidation, qui se traduit par la limitation du nombre de serveurs virtuels qu’un seul serveur
physique peut supporter.
Assurez-vous de libérer correctement la mémoire lorsque vous n’en avez plus besoin, les fuites de
mémoire pouvant entraîner une utilisation inutile des ressources. Dans le cas d’un ORM tel que Hibernate, utilisez @BatchSize pour réduire le nombre de requêtes lors de la récupération de collections.
« Il est impératif de maintenir une attitude de remise en question vis-à-vis de votre code. Son optimisation doit être synonyme d’amélioration continue afin de contribuer à la durabilité de notre secteur. »
Prenons un exemple en Java pour illustrer un code efficace en termes d’éco-conception :
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.I0Exception;
public class LectureFichierEfficiente {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("fichier.txt"))) {
String ligne;
while ((ligne = br.readLine()) != null) {
System.out.println(ligne);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Dans cet exemple, nous utilisons BufferedReader, une classe Java optimisée pour la lecture de fichiers texte. Pourquoi est-ce efficace :
- Lecture ligne par ligne : Nous utilisons une boucle while pour lire le fichier ligne par ligne. Cela signifie que nous n’avons besoin que d’une seule ligne du fichier en mémoire à la fois, ce qui réduit la consommation. Pour les fichiers volumineux, cela évite une utilisation excessive de la RAM.
- Gestion des ressources : Nous utilisons le bloc try-with-resources pour garantir que les ressources, telles que le fichier, sont correctement fermées après utilisation. Cela évite les fuites de ressources.
- Minimisation des accès disque : Le BufferedReader lit et stocke en mémoire un tampon de données à partir du fichier, ce qui minimise les accès disque coûteux. En allégeant les IO, on permettra de réduire les scale d’infrastructures.
Exemple Java pour un codage non conforme (non-compliant) :
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
public class LectureFichierNonEfficace {
public static void main(String[] args) {
try {
List<String> lignes = Files.readAllLines(Paths.get("fichier.txt"));
for (String ligne : lignes) {
System.out.println(ligne);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Dans cet exemple non conforme, nous utilisons Files.readAllLines() pour lire toutes les lignes du fichier en une seule opération. Pourquoi est-ce inefficace :
- Lecture en bloc : Cette approche lit tout le contenu du fichier en mémoire en une seule fois, ce qui peut entraîner une utilisation excessive de la mémoire pour les fichiers volumineux. Cela peut également provoquer des ralentissements si le fichier est très grand.
- Pas de gestion des ressources : Nous ne gérons pas correctement les ressources. Si une exception est levée, le fichier peut ne pas être fermé correctement, ce qui peut entraîner des fuites de ressources.
- Accès disque excessifs : Lire tout le fichier en une seule fois peut entraîner des accès disque massifs, ce qui est énergivore et peut ralentir le système.
En résumé, l’approche choisie dans le premier exemple utilise moins de mémoire, optimise les accès disque et assure une gestion appropriée des ressources : une option plus respectueuse de l’environnement en termes de consommation de ressources.
Notre conseil : Il est important d’auditer en permanence les performances de vos applications, cela passe par une revue régulière du code pour identifier les anti-patterns qui peuvent nuire à l’efficacité énergétique.
Par ailleurs, le transfert de données sur le réseau consomme aussi de l’énergie.
Voici quelques stratégies techniques pour optimiser la consommation de la bande passante dans le développement de logiciels :
- Compression des données
Non-Compliant : Envoi de fichiers et de données au format brut sans compression.
Compliant : Utilisation d’algorithmes de compression comme gzip pour les fichiers textuels ou WebP pour les images.
- Caching
Non-Compliant : Toujours récupérer les mêmes ressources depuis le serveur.
GET /static/js/script.js
Compliant : Utiliser des en-têtes HTTP pour mettre en cache les ressources côté client.
GET /static/js/script.js
Cache-Control: max-age=3600
GraphQL : Contrairement aux API REST traditionnelles qui renvoient des données fixes, GraphQL permet aux clients de demander spécifiquement les données dont ils ont besoin, réduisant ainsi la quantité de données transférées.
WebSocket et HTTP/2 : Utiliser WebSocket pour des communications bidirectionnelles en temps réel au lieu de polling fréquent. De même, HTTP/2 peut améliorer la performance en permettant le multiplexage.
Mise en cache côté serveur : Bien que l’impact principal se répercute sur la charge CPU, l’utilisation des solutions de mise en cache (telles que Redis ou Memcached) pour stocker les résultats fréquemment sollicités, éviterait des requêtes répétitives à la base de données ou d’autres opérations coûteuses en bande passante.
Notre conseil : Si vous ne pouvez pas optimiser davantage : cherchez toujours du côté du cache !
Concevoir des interfaces utilisateurs éco-énergétiques
En plus des aspects techniques, la conception d’interfaces utilisateurs peut aussi affecter l’empreinte énergétique du logiciel.
- Optimisation des animations : Bien que les animations puissent améliorer l’expérience utilisateur, elles peuvent aussi être gourmandes en ressources.
Il est donc essentiel d’utiliser les animations avec parcimonie. Des outils tels que le Performance Monitor dans les navigateurs web peuvent aider à identifier et à réduire les animations coûteuses en termes de CPU. - Minimisation des fichiers : Il est également important de réduire la taille des fichiers CSS, JavaScript et HTML en supprimant les espaces blancs inutiles, les commentaires et en utilisant des outils de minification comme UglifyJS ou CSSNano.
- Utilisation du design sombre (dark mode) : Le mode sombre, populaire sur de nombreuses applications, peut réduire la consommation d’énergie sur certains types d’écrans, tels que les OLED.
- Mises à jour différées : Au lieu de mettre à jour l’interface utilisateur en temps réel pour chaque petite modification, envisagez d’agréger ces modifications et de les appliquer en une seule fois. Cela réduit les sollicitations inutiles du CPU et du GPU.
- Utilisation de la mise en veille : Si votre application détecte une inactivité de l’utilisateur pendant un certain temps, envisagez de mettre certains éléments de l’interface ou de l’application elle-même en mode veille ou faible consommation.
- Test sur de vrais appareils : Les émulateurs ne peuvent pas toujours refléter fidèlement la consommation d’énergie. Il est donc essentiel de tester l’interface utilisateur sur des appareils réels pour obtenir une mesure précise de la consommation d’énergie.
En intégrant ces pratiques dans la conception des interfaces, nous ne visons pas seulement à réduire l’impact environnemental, nous visons également à améliorer substantiellement l’expérience utilisateur, rendant les applications plus intuitives, agréables et responsables. Ce double bénéfice renforce l’argument en faveur de l’éco-conception comme philosophie centrale dans le développement de logiciels modernes.
Notre conseil : Je vous recommande vivement le livre « Éco-conception web : les 115 bonnes pratiques », une référence incontournable dans le domaine de la conception web éco-responsable.
Optimiser les requêtes et les données
L’optimisation des bases de données est essentielle pour garantir la performance et la pérennité d’une architecture logicielle. Des requêtes non optimisées induisent une complexité algorithmique pouvant générer une charge excessive sur les serveurs et accroître inutilement la consommation énergétique.
En adoptant de bonnes pratiques, il est possible d’améliorer la réactivité des systèmes tout en réduisant leur empreinte carbone. Dans ce chapitre, vous trouverez quelques pistes d’optimisation applicables dans un environnement Java/Spring. À noter que ces bonnes pratiques sont facilement transposables à d’autres langages et frameworks.
SQL : vers des requêtes plus efficientes
Optimiser les requêtes SQL, c’est réduire le temps de calcul, la consommation d’énergie et donc, l’empreinte environnementale des systèmes. Voici quelques suggestions pour optimiser ces requêtes :
- Utilisez des index : Les index permettent d’accélérer considérablement le temps de réponse des requêtes en évitant un balayage complet des tables. Néanmoins, une sur-indexation peut rendre les opérations d’insertion, de mise à jour et de suppression plus coûteuses en termes de performance, car chaque index ajouté doit être mis à jour. De plus, ils peuvent compliquer la sélection du plan d’exécution par l’optimiseur, en particulier pour les requêtes complexes. Il est donc primordial de trouver un équilibre entre le nombre d’index et leur impact sur les performances d’écriture.
2. Optimisez les jointures et l’utilisation de WHERE : Avant de plonger dans l’optimisation, il faut absolument comprendre les données et la fréquence des mises à jour, afin d’éviter de complexifier vos requêtes. Vous pouvez améliorer vos requêtes avec les bonnes pratiques suivantes :
- Utiliser des prédicats efficaces « pré-filtrage » : Formuler des conditions « WHERE » qui exploitent les colonnes indexées pour filtrer les enregistrements avant que des opérations plus coûteuses, comme les
jointures, ne soient effectuées. - Implémenter des Sargable Queries : Une requête est dite sargable lorsqu’elle est structurée de manière à tirer pleinement parti des index existants. Cela signifie que les conditions de recherche suivent l’ordre
naturel de l’index, comme l’ordre alphabétique pour les chaînes de caractères, numérique pour les nombres ou chronologique pour les dates. En revanche, les recherches ne sont généralement pas sargables dans les cas suivants : l’utilisation de NOT, OR ou IN avec plusieurs valeurs, ainsi que des opérations appliquées directement sur les colonnes, en particulier lorsqu’une colonne indexée est affectée. De telles pratiques peuvent annuler les bénéfices de l’indexation et alourdir le traitement des requêtes. - Choisir pertinemment le type et la stratégie de jointure : La logique du métier influence le type de jointure (INNER, LEFT…) tandis que la taille des tables et la présence d’index déterminent la stratégie appropriée (Nested Loop, Hash Join…).
- Utiliser judicieusement l’agrégation : Les opérations d’agrégation (SUM, COUNT, AVG, etc.) peuvent être coûteuses. Lorsque cela est possible, essayez de limiter le nombre de lignes sur lesquelles ces opérations sont effectuées en utilisant des clauses WHERE ou HAVING.
- Utiliser EXPLAIN PLAN : penser à systématiquement faire un explain plan sur les requêtes écrites à la main ou générées par l’ORM, en utilisant, dans ce cas, des outils comme pt-query-advisor pour MySQL ou Hypersistence Optimizer (solutions payantes) pour analyser les requêtes générées et les optimiser.
EXPLAIN SELECT * FROM orders WHERE customer_id = 123;
- Partitionner la table : Si votre table a des millions de lignes, le partitionnement peut améliorer les performances en permettant à la base de données de ne rechercher que dans une seule partition plutôt que dans la table entière.
- Utiliser des vues matérialisées : Les vues matérialisées stockent le résultat d’une requête à la manière d’un cache et peuvent être utilisées pour accélérer les requêtes complexes qui sont exécutées fréquemment.
Par exemple :
CREATE MATERIALIZED VIEW customer_order_counts
AS SELECT c.name, COUNT(o.id)
FROM customers c
JOIN orders o ON c.id = o.customer_id
GROUP BY c.name;
SELECT * FROM customer_order_counts;
Ici, vous créez une vue matérialisée appelée
customer_order_counts qui stocke le résultat de la requête précédente. Maintenant, chaque fois que vous voulez obtenir le nombre de commandes par client, vous pouvez simplement interroger
customer_order_counts au lieu de lancer à nouveau la requête complète. Cela peut vous faire gagner beaucoup de temps, surtout si les données sous-jacentes ne changent pas fréquemment.
Il est important de noter que les vues matérialisées ne sont pas automatiquement mises à jour lorsque les données sous-jacentes changent. Vous devez les rafraîchir manuellement avec la commande REFRESH MATERIALIZED VIEW. Ainsi, les vues matérialisées sont pertinentes lorsque vous avez des données qui ne changent pas fréquemment, ou lorsque vous tolérez que vos résultats soient légèrement décalés par rapport aux données actuelles.
Aussi, lorsqu’un REFRESH MATERIALIZED VIEW est exécuté, le moteur de base de données rejoue la requête d’origine et met à jour la vue avec les nouvelles données, équivalant ainsi à une recréation complète.
Cela signifie que si la requête initiale est coûteuse en termes de temps ou de ressources, le REFRESH le sera tout autant. C’est pourquoi il est important de planifier judicieusement l’actualisation des
vues matérialisées. Par exemple, si les données sous-jacentes évoluent rarement ou sont mises à jour à des moments précis (comme une mise à jour nocturne), il est judicieux de rafraîchir la vue juste après ces mises à jour. Cela garantit des données
récentes sans nécessiter des rafraîchissements inutiles.
Dans d’autres cas, si une actualisation en temps réel n’est pas indispensable, notamment pour des analyses ou des tableaux de bord fonctionnant avec un léger décalage (par exemple : J-1), un rafraîchissement moins fréquent permet
d’optimiser l’utilisation des ressources tout en maintenant une pertinence suffisante des données.
Java hibernate : bonnes pratiques pour un code plus léger
L’annotation @Query est principalement utilisée pour écrire des requêtes personnalisées ne pouvant pas être facilement exprimées à l’aide de la méthode de dérivation de requête Spring Data JPA. Par conséquent, l’utilisation de @Query est privilégiée lorsque les requêtes sont complexes et nécessitent un niveau de
personnalisation qui ne peut être obtenu par d’autres moyens.
De plus, @Query se révèle particulièrement avantageux pour invoquer des procédures stockées optimisées. Ces procédures, exécutées directement sur la base de données, peuvent améliorer les performances pour des opérations complexes. Cependant, il est important de noter que cette approche peut affecter la portabilité de votre application entre différents SGBD, puisque les procédures stockées peuvent dépendre de fonctionnalités propres à chaque système.
D’un autre côté, l’utilisation de SQL natif dans Hibernate est souvent privilégiée pour des besoins en performance optimales, afin de gérer des opérations de base de données héritées ou spécifiques difficiles à manipuler via HQL ou JPQL. C’est également une option pertinente lors de la migration d’une application existante reposant déjà sur du SQL.
Cependant, il convient de noter que l’utilisation de SQL natif peut compromettre la portabilité de la base de données comme nous l’avons évoqué en parlant de @Query, car les requêtes écrites peuvent être incompatibles avec d’autres systèmes de gestion de bases de données.
- Utilisez le fetch type approprié : Par défaut, Hibernate utilise une stratégie de récupération “EAGER” pour les relations @ManyToOne et @OneToOne, et une stratégie “LAZY” pour les relations @OneToMany et @ManyToMany. Dans certains cas, vous souhaiterez peut-être ajuster ces paramètres pour réduire le nombre de requêtes générées.
- Utilisez le cache de niveau 2 et le cache de requête : Hibernate offre la possibilité d’utiliser un cache de niveau 2 qui cache les entités à travers les sessions, ainsi qu’un cache de requête qui cache le résultat des requêtes.
- Désactivez la mise à jour automatique des statistiques sur des tables qui
varient très peu : Dans une architecture CQRS (Command Query Responsibility Segregation. Cf section « Le pattern CQRS « , page 29) par exemple.
Notre conseil : Il est important de surveiller les requêtes SQL générées par Hibernate (ou tout autre ORM)
et d’en analyser les performances. Vous pouvez utiliser des outils de profilage et d’analyse
pour repérer les problèmes potentiels, et adapter des stratégies en conséquence.
Gestion des données : minimiser l’impact à chaque étape
L’utilisation inefficace des données peut aussi conduire à une surcharge sur les serveurs et à une consommation d’énergie excessive. Les développeurs peuvent y remédier en adoptant des stratégies de gestion des données efficaces, telles que :
- L’archivage des données inutilisées
L’archivage des données inutilisées peut réduire la taille de la base de données active, ce qui peut augmenter les performances et réduire l’utilisation des ressources. Les données archivées peuvent être stockées sur des supports moins coûteux et moins énergivores, car elles sont rarement utilisées. Cela peut également
aider à améliorer la sécurité en réduisant la quantité de données sensibles stockée dans la base active.
Par exemple, si une entreprise conserve des informations sur les commandes passées par ses clients, elle peut choisir d’archiver les commandes qui ont plus d’un an. Ces commandes archivées peuvent être stockées dans un emplacement séparé et récupérées si nécessaire, mais elles ne ralentiront pas les requêtes sur les commandes récentes.
- La compression des données
La compression des données réduit la quantité d’espace de stockage nécessaire pour stocker les données, ce qui augmente l’efficacité et réduit l’utilisation des ressources. La compression peut être particulièrement efficace pour les données à forte redondance, comme le texte ou les images.
Par exemple, une entreprise qui stocke beaucoup de documents texte peut utiliser une méthode de compression comme le codage Huffman pour réduire la taille de ses documents. Cela augmente l’efficacité de la base en réduisant la quantité de données à lire à partir du disque lors de l’exécution de requêtes.
- Le nettoyage des données
Cette pratique implique l’élimination des données redondantes ou inutiles de votre base de données. Cela peut inclure les données en double, les erreurs de saisie, et les informations qui ne sont plus pertinentes. En nettoyant régulièrement vos données, vous pouvez réduire la quantité d’espace de stockage nécessaire et améliorer la vitesse de vos requêtes.
- La gestion du cycle de vie des données
Une bonne gestion des données repose sur une compréhension de leur évolution dans le temps afin d’anticiper leur utilisation et leur stockage de manière efficace.
Par exemple, certaines informations ont une forte valeur juste après leur création, mais perdent progressivement en pertinence. Gérer le cycle de vie des données permet d’adapter leur conservation et leur exploitation en fonction de ces tendances.
Chaque situation est unique, il convient donc d’évaluer les bénéfices et les inconvénients de chaque approche en fonction des besoins spécifiques du projet.
Tests des performances
Les tests s’appliquent à plusieurs maillons de la chaîne de valeur de l’éco-conception. Traditionnellement axés sur la validation de la fonctionnalité et de la fiabilité, ils évoluent pour englober l’aspect durabilité. Tester régulièrement un logiciel pour sa performance et son efficacité énergétique permet d’identifier et de corriger des anomalies pouvant conduire à une consommation d’énergie excessive. Mais comment intégrer ces préoccupations éco-responsables dans vos tests ?
Pendant les tests : identifier les gisements d’efficacité énergétique
Il existe des outils spécialisés qui peuvent mesurer la quantité d’énergie consommée par une application pendant son exécution. En surveillant ces mesures lors des tests, les équipes peuvent identifier les parties du code qui sont particulièrement gourmandes en énergie.
Nous identifions deux types de mesure distincts mais complémentaires :
- Les mesures physiques
Ces solutions, bien que simples à utiliser, peuvent être payantes. Elles offrent un premier aperçu d’une éventuelle surconsommation mais ne permettent pas d’identifier précisément quelle application est responsable sur le serveur.
Parmi ces outils, nous retrouvons les Power Distribution Units (PDU), des dispositifs qui contrôlent, gèrent et mesurent l’alimentation électrique dans un centre de données. Certains modèles dits « intelligents » intègrent des APIs permettant de récupérer ces mesures de manière automatisée. Une autre solution est l’utilisation d’un WattMeter, qui mesure la consommation énergétique globale d’un équipement, fournissant ainsi une vision d’ensemble utile pour détecter les anomalies de consommation.
- Les mesures logicielles
Les solutions logicielles permettent d’identifier précisément quelles applications consomment le plus d’énergie, complétant ainsi les mesures physiques. Peu coûteuses, flexibles et adaptables, elles offrent des niveaux de précision variables selon les outils et méthodes utilisés. Intel PCM, par exemple, fournit en temps réel des données sur la consommation énergétique, les performances du processeur et la température. Cette application est compatible avec Windows, macOS et Linux. Scaphandre, quant à lui, se distingue par sa capacité à collecter des métriques détaillées sur l’énergie consommée par différents services, en mesurant aussi bien les hôtes physiques que les machines virtuelles. Il permet l’exportation des données via Prometheus, la prise en charge de Kubernetes et la mesure individuelle des pods, tout en offrant la possibilité de regrouper plusieurs processus sous un même tag pour une analyse plus fine.
En complément, les tests de charge simulent des pics d’utilisation pour évaluer l’impact énergétique d’une application sous contrainte et détecter d’éventuels problèmes d’optimisation. Enfin, l’automatisation des tests éco-efficaces permet un suivi rapide et régulier de l’empreinte énergétique sans intervention manuelle,
facilitant l’amélioration continue des performances énergétiques du logiciel.
Pendant le build : appliquer des mesures continues
L’intégration de l’éco-surveillance dans les pipelines de CI/CD permet un feedback continu sur l’efficacité énergétique. Si une modification du code provoque une augmentation de la consommation d’énergie, l’équipe peut en être alertée immédiatement. La plupart des outils CI/CD connus intègrent ou offrent des options d’intégration avec des solutions de collecte et d’analyse de la performance énergétique :
- Jenkins, par exemple, dispose d’une vaste gamme de plugins et peut être intégré à des outils comme Intel® Power Gadget ou PowerTOP, via des scripts, afin de recueillir des données sur la consommation d’énergie.
- GitLab CI/CD offre également des possibilités d’intégration avec des outils de mesure de l’efficacité énergétique. Selon la nature de l’application, il est possible d’ajouter des scripts de monitoring personnalisés (Custom Monitoring Scripts) afin de surveiller l’utilisation des ressources (CPU, mémoire, etc.). Ces scripts, intégrés directement à GitLab, permettent d’évaluer l’impact énergétique des modifications apportées au code et d’optimiser la consommation des ressources en continu. Pour les applications conteneurisées, des outils comme Docker Stats et cAdvisor offrent des métriques détaillées sur les ressources consommées par chaque conteneur.
- SonarQube, principalement utilisé pour la qualité du code, peut être étendu avec le plugin ecoCode afin d’intégrer des métriques sur la consommation d’énergie.
- Prometheus, lui, collecte les indicateurs d’efficacité énergétique, tandis que Grafana permet de les visualiser. Pleinement intégrés dans le pipeline CI/CD, ils permettent un suivi en temps réel.
- Enfin, Datadog, solution de monitoring avancée, offre un suivi en temps réel de la consommation d’énergie et peut générer des alertes instantanées en cas d’anomalie.
Déploiement éco-responsable
Optimisation des environnements de développement : éco-conception et Infrastructure As Code
Dans la quête d’un développement logiciel plus durable, la gestion des environnements de développement, de test et de qualification mérite une attention particulière. Traditionnellement, ces environnements sont maintenus actifs en permanence, ce qui entraîne une consommation inutile d’énergie et des coûts opérationnels élevés. Cependant, en adoptant des stratégies d’optimisation basées sur les principes de l’Infrastructure as Code (IaC), il est possible de transformer cette situation.
- Mutualisation des infrastructures
La mutualisation des infrastructures de développement, de qualification et d’intégration est une stratégie efficace pour consolider l’usage des ressources. En partageant les mêmes ressources entre plusieurs équipes ou projets, il est possible de réduire le nombre de serveurs actifs nécessaires, minimisant ainsi la consommation énergétique globale.
- Consolidation des charges de travail
La consolidation des charges de travail, par exemple sur des plateformes comme Kubernetes, permet d’améliorer l’utilisation des ressources. Kubernetes optimise les conteneurs en orchestrant leur déploiement sur un nombre minimal de serveurs physiques tout en garantissant leur disponibilité et leur montée en charge. Cette orchestration, combinée avec les pratiques d’IaC, assure l’optimisation des environnements.
- Arrêt dynamique des environnements
L’un des leviers d’optimisation les plus efficaces est la capacité à arrêter les environnements lorsqu’ils ne sont pas utilisés. Les outils de gestion du cloud moderne permettent de programmer automatiquement l’arrêt et le démarrage des serveurs, assurant ainsi que les ressources ne sont consommées que lorsque cela est nécessaire. Par exemple, AWS propose des services tels qu’AWS Lambda pour exécuter des scripts de gestion des ressources, et AWS Auto Scaling pour ajuster automatiquement la capacité en fonction de la demande réelle.
- Provisionnement à la demande
Avec l’approche Infrastructure as Code, les environnements peuvent être rapidement provisionnés et déprovisionnés en fonction des besoins réels des équipes. Les scripts IaC, tels que ceux utilisés avec des outils comme Terraform ou Ansible, permettent de décrire et de déployer automatiquement l’infrastructure nécessaire. Cette flexibilité optimise, non seulement, l’utilisation des ressources mais favorise également une allocation plus précise des coûts d’infrastructures.
- Déploiement optimisé
En plus des méthodes traditionnelles d’optimisation de déploiement mentionnées précédemment, il est possible d’adapter les stratégies en fonction du type de produit déployé afin de réduire la consommation énergétique et les besoins matériels.
Par exemple, pour un Very Large Language Model (VLLM), plusieurs approches peuvent être mises en place :
- L’utilisation de hardware spécialisé, comme les GPUs et TPUs, permet d’optimiser les calculs matriciels et vectoriels tout en améliorant l’efficacité énergétique.
- Par ailleurs, la réduction de la taille des modèles, grâce à des techniques comme la distillation de modèles, le pruning (élagage) ou la quantification, contribue à diminuer la taille des modèles, constituant ainsi un avantage majeur.
Notre conseil :
- Implémentez des systèmes de surveillance afin de suivre l’utilisation des ressources et de détecter les éventuelles surconsommations. Des outils comme Prometheus et Grafana offrent des solutions efficaces pour monitorer l’activité et déclencher des alertes lorsque des ressources inutilisées restent actives.
- Définissez des politiques claires de rétention et de suppression des environnements de développement et de test. Par exemple, automatiser la suppression des environnements de test après 24 heures d’inactivité permet de limiter l’empreinte énergétique et d’éviter une consommation superflue.
Hébergement écologique : un levier clé pour des infrastructures durables
Réduire l’empreinte environnementale des infrastructures numériques passe par des choix d’hébergement plus responsables. L’optimisation énergétique des serveurs est donc un levier essentiel, notamment dans des usages intensifs comme l’entraînement des modèles d’intelligence artificielle. En adoptant des serveurs à faible consommation et des solutions d’hébergement fonctionnant avec des énergies renouvelables, vous limitez cet impact. Vous pouvez également recourir à des solutions d’hébergement vert (green hosting),
comme celles proposées par PlanetHoster, Infomaniak ou ex2 , qui contribuent à cette démarche en combinant énergies propres et initiatives écologiques. Enfin, l’optimisation matérielle, avec des serveurs conçus pour être plus sobres, notamment ceux équipés de processeurs ARM, constitue une approche
complémentaire pour un hébergement plus respectueux de l’environnement.
Conclusion
Le développement de logiciels avec une perspective éco-réponsable est essentiel pour réduire l’impact environnemental des technologies tout en améliorant la performance et l’efficacité des applications. Par l’optimisation du code, la gestion intelligente des données et l’utilisation d’infrastructures durables, les développeurs peuvent significativement réduire l’empreinte carbone de leurs projets.
Adopter des stratégies telles que le choix de structures de données appropriées, l’optimisation des requêtes SQL et l’utilisation d’algorithmes performants contribue à réduire la consommation d’énergie et les coûts liés à l’exécution des applications. De plus, des pratiques comme l’archivage, la compression et le nettoyage des données aident à minimiser l’utilisation des ressources et à prolonger la durée de vie des systèmes.
L’intégration de solutions d’hébergement écologiques, comme l’utilisation d’énergies renouvelables et d’infrastructures optimisées, est également cruciale pour limiter l’impact environnemental. Enfin, la collaboration entre les équipes de développement, les responsables de la qualité et les intégrateurs continue est essentielle pour garantir que les pratiques éco-réponsables sont intégrées de manière holistique dans le processus de développement.
En résumé, l’adoption de pratiques de développement durables non seulement réduit l’empreinte environnementale, mais aussi améliore la performance et l’expérience utilisateur, renforçant ainsi l’argument en faveur d’une approche éco-conçue comme un pilier central du développement de logiciels modernes.
Vous souhaitez en savoir plus ? Contactez-nous !
–>