Potentielle solution "radicale" contre la fragmentation de mémoire (heap)

Bonjour,

Au vu des dommages que peuvent causer la fragmentation de la mémoire suite à des allocations dynamiques anarchiques et l'usage abusive de la class String par exemple j'ai pensé à une idée qui pourrait peut être une solution "universelle" à ce problème. A vous de me dire si je dis n'importe quoi.

Naturellement je comprends qu'il n'y a probablement pas mieux qu'un travail rigoureux dans l'écriture du code pour optimiser l'usage de la mémoire dynamique. Toutefois, cette éventuelle solution soumise à votre appréciation pourrait convenir aux débutants comme moi qui ne maitrisent pas forcement toutes syntaxes et astuces pour optimiser un code au maximum et éviter les crashs dans le long terme.

L'idée est la suivante, si les contraintes pratiques du projet ne l'empêchent pas pourquoi ne pas inclure une fonction de deepsleep() de 5s dans chaque code appelé à s'exécuter longtemps. Cette fonction s'exécutera périodiquement (exemple chaque 10jours, c'est selon) et à chaque fois fera donc un reset de la SRAM (et ainsi je suppose la "défragmentera").

Merci d'avance.

deepsleep : tu parles de quelle plateforme ?

Si c'est un ARDUINO, aucune chance.

Déplacé...

rebooter son arduino pour nettoyer la mémoire c'est la méthode du mauvais développeur... et Murphy frappant toujours où on ne l'attend pas, vous aurez le bug au bout de 9 jours :slight_smile:

hbachetti:
deepsleep : tu parles de quelle plateforme ?

Si c'est un ARDUINO, aucune chance.

Bonjour,
Dans mon cas il s'agit de l'ESP32. Mais vu que l'arduino a aussi une bibliothèque Low Power est ce que ca ne marcherait pas aussi ?
Pour le ESP32 vous confirmez que cela pourrait bien marcher tout de même ?

J-M-L:
rebooter son arduino pour nettoyer la mémoire c'est la méthode du mauvais développeur... et Murphy frappant toujours où on ne l'attend pas, vous aurez le bug au bout de 9 jours :slight_smile:

Bonjour,

Oui j'imagine bien qu'un développeur pro serait géné de publier un code où il est obligé de rebooter son matos pour eviter la fragmentation de sa mémoire. Là je parle dans le cas des débutants comme moi, en attendant de maitriser les bonnes pratiques, est ce que le Deep Sleep (Library Low Power Arduino ou "nativement" avec le ESP32 ) ca marche ?

l'ESP perd sa mémoire (sauf si stockée au bon endroit) et reboot.

un "arduino" (Uno, Mega) est vraiment juste en sommeil donc vous retrouvez le contenu de la mémoire et vous continuez là où vous vous étiez endormi

J-M-L:
l'ESP perd sa mémoire (sauf si stockée au bon endroit) et reboot.

un "arduino" (Uno, Mega) est vraiment juste en sommeil donc vous retrouvez le contenu de la mémoire et vous continuez là où vous vous étiez endormi

Merci pour cette réponse.
Si je comprends bien c'est bien une méthode qui marche (bien que pas très élégant ni "régulière").

Sinon pas moyen alors pour les arduino de leur faire perdre la mémoire par un reset (programmable) ou un restart comme le ESP.restart() de l'ESP32 ?

c'est pas clean non... C'est un peu comme si on vous disait "rebootez votre PC tous les 10 jours pour être sûr que tout va bien"... vous ne seriez pas super satisfait.. (euh, bon c'est le cas avec Windows, les gens se sont habitués mais pas sur linux ou sur mac :slight_smile: )

ou pour prendre une autre image si vous étiez en avion, il faudrait qu'il se pose vite parce qu'il faut rebooter la boussole...

bref c'est nul comme approche et encore plus quand on est débutant il faut pas essayer de planquer la m*rde sous le tapis, il faut apprendre à débuger son code...

sur un Arduino standard on peut faire un reset soit en appelant asm volatile ("  jmp 0"); soit en utilisant le watchdog

#include <avr/wdt.h>
void software_Reboot()
{
  wdt_enable(WDTO_15MS);
  while(true);
}

soit en pilotant par une pin la pin reset du micro-processeur.

Dans tous les cas, c'est moche !

Pour le ESP32 vous confirmez que cela pourrait bien marcher tout de même ?

J'aimerais bien savoir où tu as vu des problèmes de fragmentation mémoire sur ESP32.
As-tu un cas précis ?
Je dis cela parce qu'avant-hier j'ai fait un test intensif d'envoi de requêtes vers un serveur ESP32, sur lequel je ne me suis pas privé d'utiliser des String. Après 5000 requêtes je n'ai pas vu de problème.

Quant à l'ARDUINO j'estime que rebooter pour éviter les problèmes est une piètre solution.
Comment estimer la fréquence des redémarrages ? ? ?
Cette fréquence risque de dépendre fortement de l'utilisation.
Faut-il mesurer en permanence la mémoire restante dans le tas ?
C'est n'importe quoi.

@dabakh : arduino-la-fragmentation-memoire
Apprends à utiliser les C strings.

J'espère que TESLA ne reboot pas trop souvent ses voitures...
Le reboot systématique n'est vraiment pas une bonne solution me semble t'il.

petit truc qui avait circulé il y a une bonne quinzaine d'années:


Et si microsoft fabriquait des voitures ...

Voilà un petit texte trouvé sur le net et qui d'après le site, raconte des faits rééls :

Lors d'un salon informatique (ComDex), Bill Gates a comparé l'industrie informatique avec l'industrie automobile: "Si GENERAL MOTORS (GM) avait eu la même progression technologique que l'industrie informatique, nous conduirions aujourd'hui des automobiles coûtant 25 dollars et qui pourraient rouler 1000 miles avec un gallon d'essence."

A cela GM (par Mr. WELCH en personne) répondit ouvertement les choses suivantes lors d'une conférence de presse :

" Si GM avait développé sa technologie comme Microsoft, les voitures que nous conduirions aujourd'hui auraient les propriétés suivantes :

  1. Votre voiture aurait un accident sans raison compréhensible 2 fois par jour.

  2. Chaque fois que les lignes blanches seraient repeintes, il faudrait racheter une nouvelle voiture.

  3. Occasionnellement, une auto quitterait l'autoroute sans raison connue. Il faudrait simplement l'accepter, redémarrer l'auto et reprendre la route.

  4. Parfois, lors de manoeuvres particulières, comme par exemple prendre une courbe à gauche, l'auto ferait un simple tout droit puis refuserait de repartir. Pour cela, il faudrait procéder à un échange standard du moteur.

  5. Les autos ne seraient livrées qu'avec un seul siège, car il faudrait choisir entre " Car95 " et " CarNT ". Chaque siège supplémentaire devrait être commandé à l'unité.

  6. Macintosh développerait des voitures fonctionnant à l'énergie solaire, fiables, cinq fois plus rapides et deux fois plus légères. Mais elles ne pourraient emprunter que 5% des routes.

  7. Les témoins d'huile, de température et de batterie seraient remplacés par un unique témoin " Défaillance Générale ".

  8. Les sièges exigeraient que chaque passager ait la même taille et le même poids.

  9. L'airbag demanderait " êtes-vous sur ? " avant de s'ouvrir.

  10. Occasionnellement la condamnation centralisée de la voiture se bloquerait. Vous ne pourriez alors la rouvrir qu'au moyen d'une astuce, comme par exemple simultanément tirer la poignée de porte, tourner la clé dans la serrure et d'une autre main attraper l'antenne radio.

  11. GM vous forcerait à acheter avec chaque voiture un jeu de cartes routières De Luxe de la société Rand McNally (depuis peu filiale de GM), même lorsque vous ne souhaitez pas ou n'avez pas besoin de ces cartes. Au cas ou vous ne prendriez pas cette option, la voiture roulerait 50% moins vite (ou plus). A cause de cela, GM deviendrait une cible fréquente de procès.

  12. A chaque fois que GM sortirait un nouveau modèle, chaque conducteur devrait réapprendre à conduire, car aucune des commandes ne fonctionnerait exactement comme dans les modèles précédents.

  13. Enfin, il faudrait appuyer sur le bouton " démarrer " pour stopper le moteur.

J-M-L:
c'est pas clean non... C'est un peu comme si on vous disait "rebootez votre PC tous les 10 jours pour être sûr que tout va bien"... vous ne seriez pas super satisfait.. (euh, bon c'est le cas avec Windows, les gens se sont habitués mais pas sur linux ou sur mac :slight_smile: )

ou pour prendre une autre image si vous étiez en avion, il faudrait qu'il se pose vite parce qu'il faut rebooter la boussole...

bref c'est nul comme approche et encore plus quand on est débutant il faut pas essayer de planquer la m*rde sous le tapis, il faut apprendre à débuger son code...

sur un Arduino standard on peut faire un reset soit en appelant

asm volatile ("  jmp 0");

soit en utilisant le watchdog

#include <avr/wdt.h>

void software_Reboot()
{
 wdt_enable(WDTO_15MS);
 while(true);
}



soit en pilotant par une pin la pin reset du micro-processeur.

Dans tous les cas, c'est moche !

Bonsoir,
C'est bien ce que ce que je pensais, c'est pas une méthode glorieuse, mais bon...
Sinon pour le

sur un Arduino standard on peut faire un reset soit en appelant

asm volatile ("  jmp 0");

soit en utilisant le watchdog

#include <avr/wdt.h>

void software_Reboot()
{
 wdt_enable(WDTO_15MS);
 while(true);
}

ca parrait super, je vais tester à l'occasion (si entre temps j'ai pas encore maitrisé les bonnes pratiques). Merci

hbachetti:
J'aimerais bien savoir où tu as vu des problèmes de fragmentation mémoire sur ESP32.
As-tu un cas précis ?
Je dis cela parce qu'avant-hier j'ai fait un test intensif d'envoi de requêtes vers un serveur ESP32, sur lequel je ne me suis pas privé d'utiliser des String. Après 5000 requêtes je n'ai pas vu de problème.

Bonjour,
Oui pour l'ESP32 en effet c'est assez peut probable tellement il ya de la marge. Toutefois pour des string je ne pense pas qu'on soit dans le domaine des pratiques dangeureuses totalement. Parce que meme pour 5000 string par exemple avec des empruntes d'environs 50bytes chacune, il reste tout de meme toujours prés 50% de marge restante (au mieux quoi).
Ma crainte va plutot pour des Document Json Dynamic par exemple où un paquet peut démarrer avec du 2048 et s'agrandir pour finir on ne sais où (le principe meme du dynamique). Si pire c'est mis dans une boucle avec beaucoup d'itérations qui est censé répéter cette opération de création de Document Json dynamic, ça peut etre problématique je suppose.

Quant à l'ARDUINO j'estime que rebooter pour éviter les problèmes est une piètre solution.
Comment estimer la fréquence des redémarrages ? ? ?
Cette fréquence risque de dépendre fortement de l'utilisation.
Faut-il mesurer en permanence la mémoire restante dans le tas ?

Là je me disais qu'il fallait le faire en raisonnant au pire des cas (période donnée, taille max de paquet à charger en mémoire, fréquence max, etc...) je me dis que des "sleep-wakeup" répétés tant que c'est pas exagérément fréquent (exemple chaque 1 min) c'est pas très dommageable au board(merci de me corriger si je me trompe).
Merci

Dans tous le cas, ARDUINO avec 2.5Kb de RAM ou ESP32 avec 500Kb, je pense que la cible doit être adaptée au but recherché.

Dans mon exemple de 5000 requêtes j'aboutis à un fichier historique de 150Kb. Si je veux visualiser ce fichier sur une page WEB je n'ai pas assez de mémoire car la taille du plus gros bloc disponible et de seulement 113Kb.
Je précise que la taille de ce bloc, que ce soit avant ou après l'envoi des 5000 requêtes, ne change pas, donc redémarrer ne donnera rien de plus.
Donc soit j'affiche le fichier sur plusieurs pages, soit je change de module pour avoir plus de mémoire.

Pour ce qui est du cas ARDUINO, redémarrer n'est n'est pas une solution viable car cela suppose soit une prédictibilité de la fragmentation soit une mesure de celle-ci.
Si la solution d'un redémarrage périodique est adoptée pour des raisons de non compétence du développeur, ce même développeur sera de toutes façons incapable de prédire ou de calculer la fréquence du redémarrage.

Il est tout de même aberrant qu'une application s'autorise un redémarrage alors qu'une opération X ou Y est en cours, surtout si un utilisateur de l'application a demandé cette opération et en attend un résultat. Cela supposerait une sauvegarde de contexte pour le reprise de l'opération interrompue en vue de sa reprise après redémarrage, un développement loin d'être à la portée de l'amateur.

En général dans le monde de l'embarqué sur petits processeurs il est rare que l'on s'autorise l'allocation dynamique, et cela concerne même de très grosses applications sur des cibles possédant plus de 100kb de mémoire RAM.

hbachetti:
Dans tous le cas, ARDUINO avec 2.5Kb de RAM ou ESP32 avec 500Kb, je pense que la cible doit être adaptée au but recherché.

Dans mon exemple de 5000 requêtes j'aboutis à un fichier historique de 150Kb. Si je veux visualiser ce fichier sur une page WEB je n'ai pas assez de mémoire car la taille du plus gros bloc disponible et de seulement 113Kb.
Je précise que la taille de ce bloc, que ce soit avant ou après l'envoi des 5000 requêtes, ne change pas, donc redémarrer ne donnera rien de plus.
Donc soit j'affiche le fichier sur plusieurs pages, soit je change de module pour avoir plus de mémoire.

Pour ce qui est du cas ARDUINO, redémarrer n'est n'est pas une solution viable car cela suppose soit une prédictibilité de la fragmentation soit une mesure de celle-ci.
Si la solution d'un redémarrage périodique est adoptée pour des raisons de non compétence du développeur, ce même développeur sera de toutes façons incapable de prédire ou de calculer la fréquence du redémarrage.

Il est tout de même aberrant qu'une application s'autorise un redémarrage alors qu'une opération X ou Y est en cours, surtout si un utilisateur de l'application a demandé cette opération et en attend un résultat. Cela supposerait une sauvegarde de contexte pour le reprise de l'opération interrompue en vue de sa reprise après redémarrage, un développement loin d'être à la portée de l'amateur.

En général dans le monde de l'embarqué sur petits processeurs il est rare que l'on s'autorise l'allocation dynamique, et cela concerne même de très grosses applications sur des cibles possédant plus de 100kb de mémoire RAM.

Trés instructif merci.