Bientôt disponible! Voir flutter/devtools#3951.
Le texte ci-dessous est en construction.
Il s’agit d’un framework pour le suivi des fuites de mémoire pour les applications Dart et Flutter.
Démarrage rapide pour suivre les fuites pour Flutter
Application flottante
- Avant
runApp
invocation, activez le suivi des fuites et connectez les événements d’allocation de mémoire Flutter :
import 'package:flutter/foundation.dart';
import 'package:leak_tracker/leak_tracker.dart';
...
enableLeakTracking();
MemoryAllocations.instance
.addListener((ObjectEvent event) => dispatchObjectEvent(event.toMap()));
runApp(...
- Exécutez l’application en mode débogage et surveillez les avertissements liés aux fuites. Si vous voyez un avertissement, ouvrez le lien pour enquêter sur les fuites.
TODO(polina-c) : implémentez le lien et ajoutez un exemple d’avertissement.
Essais de flottement
Enveloppez vos tests avec withLeakTracking
pour configurer la vérification automatique des fuites :
test('...', () async {
final leaks = await withLeakTracking(
() async {
...
},
);
expect(leaks, leakFree);
});
Comment fonctionne le suivi des fuites
Avant de lire sur le suivi des fuites, comprenez Concepts de mémoire de fléchettes.
Types de fuites traitées
Le traqueur de fuites ne peut détecter que certains types de fuites, en particulier celles liées au moment de l’élimination et de la collecte des ordures. Avec une bonne gestion de la mémoire, cet outil suppose que la suppression et la récupération de place d’un objet se produisent en succession rapide. C’est-à-dire que l’objet doit être récupéré lors du prochain cycle de récupération de place après élimination.
En surveillant les événements d’élimination et de récupération de place, l’outil détecte différents types de fuites :
-
Non éliminé, mais GCed (non éliminé):
-
Définition: un objet jetable a été GCed, sans avoir été éliminé au préalable. Cela signifie que le contenu jetable de l’objet utilise de la mémoire une fois que l’objet n’est plus nécessaire.
-
Réparer: invoquer
dispose()
pour que l’objet libère de la mémoire.
-
-
Disposé, mais non GCed (non GCed):
-
Définition: un objet a été éliminé, mais pas GC après un certain nombre d’événements GC. Cela signifie qu’une référence à l’objet l’empêche d’être ramassé une fois qu’il n’est plus nécessaire.
-
Réparer: Pour corriger la fuite, affectez toutes les références accessibles de l’objet à null après élimination :
myField.dispose(); myField = null;
-
-
Disposé et GCed tard (GCed-late):
-
Définition: un objet a été éliminé puis GCé, mais le GC s’est produit plus tard que prévu. Cela signifie que le chemin de rétention gardait l’objet en mémoire pendant un certain temps, mais a ensuite disparu.
-
Réparer: le même que pour non GCed
-
-
Disposé, mais pas GCed, sans chemin (non-GCed-sans-chemin):
-
Définition: un objet a été éliminé et non GC comme prévu, mais le chemin de rétention n’est pas détecté, cela signifie que l’objet sera très probablement GC dans le prochain cycle GC, et la fuite se convertira en GCed-tard fuir.
-
Réparer: s’il vous plaît,
créer un problème
si vous voyez ce type de fuites, cela signifie que quelque chose ne va pas avec l’outil.
-
Coupables et victimes
Si vous avez un ensemble d’objets non GCed, certains d’entre eux (victimes) peuvent ne pas être GC-ed parce qu’ils sont détenus par d’autres (coupables). Normalement, pour réparer les fuites, vous devez uniquement réparer les coupables.
Victime: un objet ayant fui, pour lequel l’outil pourrait trouver un autre objet ayant fui qui, s’il était réparé, réparerait également la première fuite.
Coupable: un objet qui fuit et qui n’est pas détecté comme étant la victime d’un autre objet.
L’outil détecte les objets qui ont fui sont coupables, vous savez donc où vous concentrer.
Par exemple, sur quatre fuites non GCed sur le schéma suivant, une seule est coupable, car, lorsque l’objet est réparé et GCed, les victimes auxquelles il fait référence seront également GCed :
flowchart TD; l1[leak1nculprit] l2[leak2nvictim] l3[leak3nvictim] l4[leak4nvictim] l1-->l2; l1-->l3; l2-->l4; l3-->l4;
Limites
Par classes suivies
Le traqueur de fuites détectera les fuites uniquement pour les objets instrumentés (voir notions pour plus de détails).
Cependant, la bonne nouvelle est :
-
La plupart des classes Flutter Framework jetables incluent l’instrumentation. Si la façon dont votre application Flutter gère les widgets entraîne des fuites, Flutter les détectera.
-
Si une fuite concerne au moins un objet instrumenté, la fuite sera captée et tous les autres objets, même non instrumentés, cesseront également de fuir.
Voir le guidage de l’instrumentation.
Par mode de construction
La disponibilité du traqueur de fuite diffère selon les modes de construction. Voir Modes de construction de fléchettes
ou alors Modes de construction flottants.
Développement Dart et débogage Flutter
Le suivi des fuites est entièrement disponible.
Profil flottant
Le suivi des fuites est disponible, mais MemoryAllocations qui écoute les objets instrumentés Flutter, doit être allumé
si vous souhaitez suivre les objets Flutter Framework.
Production de fléchettes et lancement de Flutter
Le suivi des fuites est désactivé.
REMARQUE : Si vous souhaitez activer le suivi des fuites pour le mode de libération, veuillez commenter ici.
Instrumentez votre code
Si vous souhaitez détecter les fuites d’objets en dehors de Flutter Framework (qui sont déjà instrumentés), vous devez les instrumenter.
Pour chaque objet suivi, la bibliothèque doit recevoir deux signaux de votre code : (1) l’objet est créé et (2) l’objet n’est pas utilisé. Il est plus pratique de donner le premier signal dans le constructeur et le deuxième signal dans le dispose
méthode:
import 'package:leak_tracker/src/leak_tracker.dart';
class InstrumentedClass {
InstrumentedClass() {
dispatchObjectCreated(
library: library,
className: '$InstrumentedClass',
object: this,
);
}
static const library = 'package:my_package/lib/src/my_lib.dart';
void dispose() {
dispatchObjectDisposed(object: this);
}
}
Démarrer/arrêter le suivi des fuites
Pour démarrer le suivi des fuites, appelez enableLeakTracking()
arrêter: disableLeakTracking()
.
TODO(polina-c) : notez que Flutter Framework active le suivi des fuites par défaut, lorsque c’est le cas.
Collecter les fuites
Il y a deux étapes dans la collecte des fuites : (1) obtenir le signal que des fuites se sont produites (résumé des fuites) et (2) obtenir des détails sur les fuites.
Par défaut, le tracker de fuite recherche les fuites toutes les secondes et, s’il y en a, génère le résumé sur la console et l’envoie à DevTools. Ensuite, vous pouvez obtenir des détails sur les fuites soit en les demandant à DevTools, soit en appelant collectLeaks()
par programme.
Vous pouvez modifier le comportement par défaut en passant personnalisé
configuration
pour enableLeakTracking()
:
- Désactivez la vérification régulière des fuites et vérifiez les fuites en appelant
checkLeaks()
. - Désactivez la sortie vers la console ou vers DevTools.
- Écoutez les fuites avec un gestionnaire personnalisé.
Voir DevTools > Memory > Leaks
des conseils sur la façon d’interagir avec le traqueur de fuites.
TODO : ajouter un lien vers la documentation DevTools.
Résoudre les fuites
Collecter la pile d’appels
Stacktrace pour les événements du cycle de vie de l’objet peut aider à détecter la cause première de la fuite. L’événement du cycle de vie sera la création pour les fuites non éliminées et l’élimination pour les fuites non GCed.
Par défaut, le tracker de fuite ne collecte pas les stacktraces, car la collecte peut avoir un impact sur les performances et l’empreinte mémoire.
Il existe des options pour activer la collection stacktrace pour le dépannage :
- En passant
stackTraceCollectionConfig
pourwithLeakTracking
ou alorsenableLeakTracking
.
collect_callstack.mov
- Utilisation de l’interface utilisateur interactive dans DevTools > Mémoire > Fuites.
TODO : lier la documentation de DevTools avec une explication
Vérifier les chemins de retenue
Ouvrez DevTools > Mémoire > Fuites, attendez que les fuites non GC soient détectées, puis cliquez sur « Analyser et télécharger ».
À FAIRE : ajouter des détails
Impact sur les performances
Mémoire
Le Leak Tracker stocke un petit enregistrement supplémentaire pour chaque objet vivant suivi et pour chaque fuite détectée, ce qui augmente l’empreinte mémoire.
Pour le Demande de galerie
en mode profil sur macos
le suivi des fuites a augmenté l’empreinte mémoire de la page d’accueil d’environ 400 Ko, soit environ 0,5 % du total.
CPU
Le suivi des fuites a un impact sur le processeur dans deux domaines :
-
Suivi par objet. Ajout de ~0,05 milliseconde (~2,7 %) au temps de chargement total de
Galerie page d’accueil en mode profil surmacos
. -
Analyse asynchrone régulière des objets suivis. A pris ~ 2,5 millisecondes pour
Galerie page d’accueil en mode profil surmacos
.
GitHub
Voir Github