L’observatoire Bouygues Télécom réalisé par le CSA relayé par inflexia-marketing sur “Usage du smartphone par les français en 2018 !”) se retrouvent inévitablement sur la mémoire de stockage des appareils Android.
On retrouve les informations mémoires de ces usages en cliquant sur "Stockage" dans le menu “Système d’Android” :
En 2021 la tendance du stockage interne (flash) des smartphones Android est majoritairement 64 Go ou 128 Go (voire 512 Go pour les modèles les plus puissants). On est loin des 256 Mo en 2008 complétés par une carte mémoire 1 Go de base (pouvant aller jusqu'à 32 Go) du HTC G1, premier smartphone commercialisé avec le système d'exploitation Android de Google.
De même, la mémoire vive (RAM) smartphones Android est passée en 13 ans de 192 Mo ( HTC G1) à aujourd’hui majoritairement 4 ou 6 Go, voire 12 Go pour les modèles les plus puissants.
Au-delà de la mémoire, d’autres exemples illustrent ces tendances inflationniste du hardware :
Bref, les applications ne sont qu’un moyen parmi d’autres de satisfaire les multiples besoins des utilisateurs des appareils mobiles, sollicitant de plus en plus un espace mémoire qui, en réponse, augmente constamment.
2021 : la pénurie de semi-conducteurs paralyse tout le marché de l’automobile, malgré les efforts de TSMC (Taiwan Semiconductor Manufacturing Company).
2051 : dans 30 ans, l’épuisement des ressources abiotiques pourrait marquer la fin du numérique.
En effet, la fabrication d’un appareil numérique repose sur des ressources critiques, non renouvelables et qui seront épuisées prochainement (des experts parlent d’une 1 à 2 générations au rythme actuel). Comme le montre très bien Fairphone dans une Vidéo de janvier 2021 de Fairphone de 4 minutes : “The hidden impact of the smartphone industy” :
Ce constat alarmant nous conduit à questionner un système complexe mixant le marché des terminaux, les habitudes des utilisateurs, la responsabilité des métiers de l’IT. Parmi les multiples pistes de solution que nous avons commencé à explorer : la taille des applications qui encombrent nos smartphones.
Un des enjeux majeurs du numérique responsable réside dans la limitation du nombre de terminaux. Or nos comportements d’utilisateurs de mobiles vont dans la direction opposée. D’après l’ADEME, “88 % des Français changent leur téléphone portable alors qu’il fonctionne encore et en moyenne nous changeons notre téléphone tous les deux ans” alors qu’après un rapport de l'Institut Fraunhofer : “l'utilisation d'un smartphone pendant cinq à sept ans peut réduire les émissions de CO2 de 28 à 40% par an”.
Devons-nous considérer l’impact environnemental de cette course au renouvellement comme inéluctable ? Et si le problème ne résidait pas seulement au niveau des terminaux, mais aussi du côté de la taille des applications qui les encombrent ?
Qu’entendons-nous par “taille “ ? Nous parlons ici de la quantité de données associées à la vie d’une application, sur le terminal, sur les réseaux et dans les data centers.
Pour agir au mieux, il convient de comprendre les différentes natures de données qui transitent autour d'une application Android, depuis sa phase de développement jusqu'à sa mise à jour sur l'appareil Android.
Nous nous sommes intéressés à la circulation des données durant 4 étapes :
A partir d’une présentation globale, nous détaillerons chaque phase, et plus particulièrement la mise à jour qui a fait l’objet de travaux d'optimisation de la part de Google.
Lors de la phase de développement, l'application que manipulent les développeurs contient l'ensemble des données et ressources nécessaires pour la faire tourner sur un grand nombre d'appareils Android et prendre en compte les différents types (tailles d'écran, les langues, …) de tous les appareils cibles.
Cette application est donc potentiellement bien plus grosse que celle qui sera envoyée pour être installée sur un appareil Android spécifique.
Afin de simplifier nos explications, nous considérons qu’aujourd’hui, l’équipe de développement transmet au Play Store de Google l'application sous la forme d’un Android App Bundle (AAB) ainsi que la clé de signature de l’application. Ceci est devenu le standard depuis août 2021 (cf. Android Developers Blog: The future of Android App Bundles is here).
L'application choisie par le propriétaire du smartphone sera créée (2.2) et signée par les services de Google Play pour être optimisée pour l'appareil en question. C'est pourquoi la taille de l'application peut varier d'un appareil à l'autre suivant sa version d'Android et sa configuration.
Cette taille est indiquée sur le Play Store et lors du téléchargement.
Ce travail sur les serveurs de Google permet de diminuer significativement les données envoyées et installées sur l’appareil Android. Ceci grâce à l’utilisation de l’Android App Bundle utilisant le “dynamic delivery” en remplacement du format APK “universel” (cf. illustration animée).
Une fois envoyée (2.3), elle sera décompressée pour être installée (2.5) sur l'appareil. On peut retrouver cette taille dans le menu paramètres des applications du système Android.
A noter qu'une copie de l'application au format APK reste sauvegardée sur l’appareil, nous y reviendrons dans l’étape 4 de mise à jour de l’application.
Si vous souhaitez connaître la taille réelle d’une application avant de la télécharger, le mode opératoire est le suivant :
Depuis le Play Store quand on sélectionne une application (ici Firefox) pour l'installer, dans les informations "A propos de l’appli” (A), on retrouve la taille de données téléchargées (B) correspondant à la version de l’application à installer ici 66,47 Mo. Ce qui se retrouve lors du téléchargement (E) une fois avoir lancé l'installation (D).
Puis on retrouve l’étape d’installation, c’est-à-dire de décompression de l’application (F). Que l’on peut enfin utiliser (G).
Une fois installée, on retrouve dans les informations des applications en passant par les paramètres du système Android et en sélectionnant “l'espace de stockage et cache” (I). Une fois décompressée et installée, la taille de l'application Firefox est de 226 Mo. À ne pas confondre avec la taille de 262 Mo (H) qui est la taille obtenue en additionnant la taille de l'application et les données utilisateurs (J+K). Le "Total" (M) correspond également à l'ensemble de l’espace complet que prend l’application, c'est-à-dire avec le cache utilisé par l‘application (M=J+K+L).
Durant l'utilisation de l'application, des données peuvent transiter :
De manière générale, il y aurait beaucoup d'autres choses à dire pour cette étape mais nous avons fait le choix de ne pas trop nous attarder sur cette partie. Le but étant ici de se concentrer sur les données autour de l'application spécifiquement Android. Nous reviendrons sur certains points pour optimiser les données lors de l'utilisation de l'application dans le chapitre “À propos des tailles de l’application elle-même et de ses mises à jour”.
Nous allons nous attarder un peu plus sur cette étape qui a été le sujet de quelques recherches afin de comprendre ce qui se passe lors de la mise à jour des applications.
Depuis fin 2016, les équipes Android de Google ont mis en place un processus de mise à jour différentielle permettant d'envoyer uniquement les données qui changent entre les deux versions. Les termes “File-by-File patching”, “Delta update” voire “Delta X” font tous référence à ce procédé.
Les grandes étapes du processus “Delta update” sont :
Il peut arriver que la taille des informations différentielles pour un petit fichier soit plus grosse que le fichier lui-même. Ceci est dû à la surcharge liée à la création du fichier delta;
À noter que ce processus n'est pas magique. La diminution de la quantité de données transférées entre les serveurs Google Play et l'appareil Android se fait au prix d’un processus complexe qui nécessite du temps de calcul supplémentaire. C'est pourquoi les mises à jour automatiques Android se déroulent généralement la nuit, lorsque l’appareil est branché sur le secteur et qu’il n’est pas utilisé.
Vous retrouverez bien plus de détails dans cet intéressant article dans l’article PDF : “DELTA ‘X’ Reducing Size of an Android Application Update” de l'International Journal of Engineering Research & Technology (IJERT) et Why does Android keep APK files of installed apps?.
Concrètement, on peut retrouver différentes estimations de la taille de la mise à jour affichées à plusieurs étapes du processus de mise à jour manuelle.
Comme on peut le voir illustré avec Firefox ci-dessous, une première estimation est réalisée sur la page décrivant l’ensemble des mises à jour disponibles (A). Une deuxième estimation (C) est disponible quand on clique sur les détails des “Nouveautés” (B). La taille réelle de la mise à jour n'apparaît que pendant le téléchargement (F) juste après avoir cliqué sur “Mettre à jour” (E) . A noter que (A), (C) et (F) sont parfois différents en plus ou en moins.
Une fois téléchargée, l’application est modifiée avec le contenu de la mise à jour.
Nous avons procédé à l'observation durant 4 mois de l'installation et de la mise à jour (MAJ) sur un smartphone Android d’un panel de 18 applications d’utilisation courante (bancaires, de transport, réseaux sociaux, messageries, utilitaires, navigateurs internet) : certaines préinstallées et d’autres choisies sur le Play Store.
Nous constatons peu de différences entre les 5 applications préinstallées et les 13 du Play Store, à part une fréquence de mise à jour en moyenne deux fois plus élevée pour les premières.
Voici une synthèse des chiffres des applications installées depuis le Play Store :
D’après notre observation on estime que la méthode "delta update" fait diminuer en moyenne de plus de la moitié (55%) la quantité de données transmise. Nous avons isolé deux applications extrêmes, l'une (App #1) avec 15% de gain avec la méthode de mise à jour différentielle et l'autre (App #2)avec 87% de gain avec la méthode de mise à jour différentielle.
Google fournit aux équipes de développement plusieurs outils leur permettant de mesurer et d’analyser la taille de leurs applications et le poids des mises à jour.
Cet outil est un complément de l’utilisation de R8 (Proguard) et d’un “linteur”, qui en amont optimisent et signalent les fichiers/ressources/méthodes non utilisées et qui s'intègrent très bien dans l’usine de développement.
Par exemple en glissant (drag and drop) un fichier APK dans Android Studio, on active l'outil “Android Size Analyzer” :
Cela permet aisément de parcourir le contenu d'un APK pour vérifier qu’il n'y a pas d'éléments / ressources inutiles à supprimer de l’application.
A savoir que l’outil fonctionne aussi avec les fichiers au format AAB et qu'il y a un moyen de lancer en ligne de commande (CLI : “size-analyzer check-bundle …”). Plus d'informations sont disponibles sur developer.android.com / Reduce your app size.
L'outil “Android Size Analyzer” lancé sur une application peut donner des conseils pour l’alléger. On peut notamment y arriver par des chargements dynamiques de modules de fonctionnalités pour une livraison personnalisée (feature modules for custom delivery) pour certaines parties de l’application.
Pour plus d’info : Android Developers / Android Studio / User guide / Analyze your build with APK Analyzer
Voilà un exemple d’analyse de Google d’une application en production :
Le graphique concerne une application de taille conséquente, les chiffres sont :
Afin de réaliser une estimation de la volumétrie des données en jeu qui transitent sur les infrastructures réseaux, nous pouvons raisonnablement nous appuyer sur ces chiffres pour estimer l’impact de nouvelles installations et des mises à jour à pondérer avec leur fréquence et le nombre des appareils des utilisateurs.
Pour revenir sur l’observation de quelques applications durant 4 mois, nous avons constaté que les 5 applications préinstallées (dans notre cas développées par Google) étaient mises à jour avec une fréquence quasi doublée par rapport aux 13 applications installées depuis le Play Store.
Dans ce cas précis Google est certainement dans une logique “d’Extreme Programming (XP)” avec des livraisons fréquentes (et sans surprise avec l’étude Accelerate,). Il est donc compréhensible que la fréquence de mise à jour soit plus importante (en moyenne 9 mises à jour sur les 4 mois au lieu de 5 avec les applications installées depuis le Play Store).
Ce qui peut apparaître comme étonnant, c'est qu'avec une taille moyenne d’application comparable aux applications pré installées Google, la taille moyenne de mise à jour est quasiment similaire. Alors qu'on aurait pu s’attendre qu'avec une fréquence de mise à jour bien supérieure, la taille moyenne serait significativement plus petite. Des mises à jour éparses dans le code en sont probablement la cause. D’où l’importance d'essayer au maximum de “penser modulaire” (nous y reviendrons) et de favoriser le plus possible des mises à jour localisées dans le code pour diminuer la taille des mises à jour différentielles. Le subtil équilibre entre fréquence et taille des mises à jour restant à trouver et fonction des tailles des équipes, de leurs spécialisations, des priorités / plannings et des méthodologies (pour ne pas dire philosophie) de travail.
Au-delà du scope de cet article, les gros sujets autour de l'architecture logicielle et des bonnes pratiques software craftsmanship ne seront pas explicitement abordés.
Voici tout de même en quelques mots des intentions derrières l'éco-conception de service numérique : c’est en priorité l’art de se concentrer collectivement (clients, utilisateurs, décideurs, managers et les équipes autour du développement au sens très large) uniquement sur ce qui est vraiment utile pour les utilisateurs finaux. Cela permet de dégager du temps aux équipes qui réalisent l'application pour pouvoir développer agilement et fièrement une application conformément aux principes du software craftsmanship.
Idéalement et à l’instar des applications Web, les développeurs auront à cœur de diminuer le nombre de requêtes internet et des domaines utilisés. Il est parfois pertinent d'utiliser une API spécifique pour l’application mobile et de chercher à mutualiser les requêtes Internet afin d'en diminuer le nombre.
Dans cet esprit, il est parfois bien éclairant de mesurer le trafic de données généré sur le Web par l'application développée et de faire attention aux “trackers” / pisteurs que l’on peut embarquer parfois sans même le savoir, par exemple par effet de bord, via l’utilisation de SDKs et librairies tiers non maîtrisés. N'hésitez donc pas à détecter les pisteurs avec exodus-standalone en intégrant des appels automatiques dans l’usine de développement (CI/CD).
Des mise en cache manuelle, automatique via Android ou avec des Services Workers (cf. ServiceWorkerController) peuvent être utilisées pour une WebView) sont également des pistes à ne pas négliger.
Depuis quelques années, on constate que la tendance est de bien choisir les architectures logicielles et les méthodes de travail en équipe pour faciliter la maintenance de l'application mobile développée. Mais les tailles de l'application mobile et des mises à jour ne sont pas toujours suffisamment surveillées et tendent à augmenter au fil des versions. Peu de personnes pensent à remettre en question cette tendance qui paraît, à tort, inéluctable.
Certains secteurs, comme les jeux vidéo, ont réussi à garder aujourd’hui une forte culture du développement sous contraintes. Le rôle du “data management” y est bien défini : il consiste à gérer toutes les informations en tous genres (images, vidéos, audios, voire certains textes, …) et à en assurer l’unicité et l’usage d’un format approprié (qualité, taille et compression adaptées à l’usage).
A minima, une bonne pratique consiste à choisir des formats appropriés et à centraliser ces ressources qui seront correctement nommées et rangées. Les équipes UI/UX et de développement devront collaborer dans ce sens autour d’une nomenclature claire des données ainsi référencées. Sans ce minimum de rigueur, le risque est, qu’au final, cela se traduise par des copies plus ou moins fidèles de données sur les appareils des utilisateurs.
Dans l'absolu il convient de distinguer plusieurs types de mises à jour :
Aujourd'hui, seulement “Android Entreprise” avec une "gestion de la mobilité en entreprise" (EMM - enterprise mobility management) permet d’avoir différents scénarios et niveaux de priorités des mises à jour. Y compris pour fournir une mise à jour critique aussi rapidement que possible pouvant interrompre l'utilisation de l'appareil. Cf. Aide Android Enterprise/ Advanced app management / Gérer la mise à jour des applications pour plus d’informations.
Mais via le Play Store classique, il n'y a pas vraiment de distinction entre les différentes mises à jour d'une application Android. Et en pratique, sans changement de Google, cela semble malheureusement difficile à gérer dans le temps pour maintenir différentes branches de développement en fonction des versions utilisées.
Avec les outils de développement via la console Play Store, il y a des moyens concrets de suivre l'évolution des chiffres concernant les tailles moyennes des données nécessaires pour :
Une bonne pratique serait de surveiller ces deux chiffres afin de détecter, en amont, des variations trop importantes de la taille de l'application ainsi que des mises à jour.
Actuellement la collecte de ces données se fait manuellement. En hackant un peu les requêtes réseau et au prix d’un risque d'instabilité, il serait en théorie possible d’automatiser cette collecte d'informations.
Il ne serait d'ailleurs pas étonnant que Google fasse évoluer la console du Play Store (avec une API par exemple), afin de pouvoir intégrer une automatisation permettant de récupérer ce genre de données et de les intégrer dans l’usine de développement (CI/CD).
De manière manuelle ou automatique, l'idée serait de pouvoir avertir l'équipe de développement de changements inquiétants afin de susciter une discussion et comprendre ce qui ce passe.
Combien de fois l’introduction d’un nouvel SDK ou d'une librairie externe a-t-elle des conséquences d’une ampleur insoupçonnée ? Un refactoring de code engendre aussi des grosses mises à jour en touchant un grand nombre de fichiers de l'application.
Concernant la taille des applications, on remarque donc que la modularité du code est importante et permet d’optimiser la taille des mises à jour différentielles. Cela revient à minimiser le nombre de fichiers modifiés, s’ils sont localisés au même endroit dans un “module”.
Quand cela fait sens, isoler une fonctionnalité brassant des données utilisateur stockées en local (fichiers, base de données, …) peut être pertinent pour les réserver à ceux qui en ont réellement besoin via un chargement dynamique du module de cette fonctionnalité à la première utilisation.
On pourrait également porter attention à la gestion du cache de l’application. Cet espace mémoire permet de stocker des informations facilement accessibles théoriquement dans un but d'accélérer l'application; mais en réalité, combien d'applications consomment des dizaines de mégaoctets pour ce système de cache, sans que l'on comprenne vraiment pourquoi ? Pour des données vraiment encore utiles ? Pour des fichiers ? Ou autre chose ?
Suite à des dysfonctionnements ou des ralentissements inexpliqués sur une application, il peut être bien utile de faire le ménage :
Un dernier sujet sensible est celui des pisteurs hérités de l’utilisation de librairies tierces, qui peuvent prendre de la place dans les espaces de données utilisateur, voire de cache. Une raison de plus pour les détecter automatiquement, comme décrit dans le chapitre précédent.
Malgré tous les efforts que Google déploie autour de la distribution, de l'installation et de la mise à jour des applications Android, ces dernières continuent à grossir. Ce n’est pas sans rappeler ce qui s'est passé dans les datacenters entre 2010 et 2020. Comme le relate l'Agence internationale de l'énergie (Iea) dans un rapport de 2021, alors que leur consommation électrique est restée très stable durant cette période, le trafic Internet a été multiplié par 16. Autrement dit, tous les efforts faits par les gestionnaires pour réduire la consommation électrique de leurs serveurs ont été cachés (pour ne pas dire gâchés) par un trafic Internet qui a grandement augmenté durant cette période. Ce phénomène est malheureusement bien connu depuis au moins 1865 sous le nom de paradoxe de Jevons et effet rebond.
Nous pouvons tirer des leçons du passé : il ne faudrait pas que les efforts de Google dispensent les utilisateurs d'être vigilants sur le nombre d'applications inutilisées installées sur leurs appareils Android. A l’autre bout de la chaîne, c’est également aux équipes de développement et aux décideurs de veiller à ce que les applications ne consomment pas de ressources superflues (trafic réseau, puissance de calcul, besoin de stockage, besoin de mémoire vive) pour prolonger la durée de vie des terminaux Android. Ce qui correspond concrètement au travail d'éco-conception de services numériques.
Dans un prochain article, nous explorerons les pistes et retours de l'utilisation poussée du “dynamic delivery”.
A bientôt donc …
Merci à Brigitte Quinton pour son aide rédactionnelle et aux autres Octos qui se reconnaîtront pour leur travail pertinent et complémentaire de relecture critique et apports à cet article.