Des fuites avec les images sous Core Animation?
Mala
Membre, Modérateur
J'aimerais vous soumettre un problème qui me laisse perplexe. Je suis actuellement sur un projet qui utilise massivement Core Animation et le volume de données grimpant, je me suis aperçu que malgré la suppression de mes layers au fur et à mesure mon soft avait des fuites très importantes.
Je passe mon code en revue avec MallocDebug et Instruments et... rien. Alors que le moniteur d'activité m'indique que mon appli frise les 300Mo, Instruments m'en annonce 30 (ce qui me semblerait plus logique en tout état de cause vu les données chargées)! C'est louche.
J'ai donc décidé de me faire un petit projet de test pour identifier la fuite avec le moniteur d'activité. Et bien cela semble venir du chargement des images dans un layer. Le problème c'est que tous les exemples que j'ai trouvé sur le Web se contentent de charger une série d'images (CoverFlow et cie) mais ne font jamais le ménage.
Pensant que cela venait de mon code, j'ai essayé trois méthodes différentes pour charger mon layer et le résultat est identique. Dès que je fais le "setContents" pour assigner l'image au layer ça fuit au moment de la destruction. C'est doublement louche là .
Et là comme d'un fait exprès, j'avais le moniteur d'activité sous les yeux, j'ai redimensionné ma fenêtre et boum ma mémoire est retombée à un niveau tolérable! Puis ça remonte à nouveau. Et ainsi de suite. Il semble que la retaille de la vue (donc du layer dans mon projet de test) force le "nettoyage". Cela semble confirmé par un "setFrame" juste avant la suppression du layer.
Le bug en image:
Vidéo quicktime...
Si cela intéresse certains, voici mon projet de test (je charge un layer en boucle toutes les 2 secondes):
CALayerImageLeaks
Si vous avez une idée, je suis preneur.
Je suis en train de faire des essais de swizzling sous Léopard afin de hacker la destruction des layers (et ainsi éviter de devoir surcharger tous les CALayer que j'utilise) mais j'ai des soucis pour le moment. Je n'arrive pas à remplacer la méthode de la classe CALayer par celle de mon controleur (je me retrouve avec un loop infini sur mon removeFromSuperlayer) sous Léopard alors que j'y arrivais très bien sous Tiger (mais les méthodes sont deprecated).
Je passe mon code en revue avec MallocDebug et Instruments et... rien. Alors que le moniteur d'activité m'indique que mon appli frise les 300Mo, Instruments m'en annonce 30 (ce qui me semblerait plus logique en tout état de cause vu les données chargées)! C'est louche.
J'ai donc décidé de me faire un petit projet de test pour identifier la fuite avec le moniteur d'activité. Et bien cela semble venir du chargement des images dans un layer. Le problème c'est que tous les exemples que j'ai trouvé sur le Web se contentent de charger une série d'images (CoverFlow et cie) mais ne font jamais le ménage.
Pensant que cela venait de mon code, j'ai essayé trois méthodes différentes pour charger mon layer et le résultat est identique. Dès que je fais le "setContents" pour assigner l'image au layer ça fuit au moment de la destruction. C'est doublement louche là .
Et là comme d'un fait exprès, j'avais le moniteur d'activité sous les yeux, j'ai redimensionné ma fenêtre et boum ma mémoire est retombée à un niveau tolérable! Puis ça remonte à nouveau. Et ainsi de suite. Il semble que la retaille de la vue (donc du layer dans mon projet de test) force le "nettoyage". Cela semble confirmé par un "setFrame" juste avant la suppression du layer.
Le bug en image:
Vidéo quicktime...
Si cela intéresse certains, voici mon projet de test (je charge un layer en boucle toutes les 2 secondes):
CALayerImageLeaks
Si vous avez une idée, je suis preneur.
Je suis en train de faire des essais de swizzling sous Léopard afin de hacker la destruction des layers (et ainsi éviter de devoir surcharger tous les CALayer que j'utilise) mais j'ai des soucis pour le moment. Je n'arrive pas à remplacer la méthode de la classe CALayer par celle de mon controleur (je me retrouve avec un loop infini sur mon removeFromSuperlayer) sous Léopard alors que j'y arrivais très bien sous Tiger (mais les méthodes sont deprecated).
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
il me semblait l'avoir résolu par le choix correct de l'initialisation des images, mais tes ennuis m'ont fait réessayer l'une des applis. Je me trouve dans un cas similaire pour l'appli BigLetterView (téléchargements
La mémoire réelle reste stable avec quand même des montées et des descentes sur une durée assez longue, mais la mémoire virtuelle monte régulièrement. Par contre, je ne détecte pas la disparition ddu phénomène avec le window resizing.
Sinon, rien à voir, mais comme je jouais avec la taille de ta fénêtre, j'ai remarqué que tu as une latence dans le repositionnement de tes layers. Tu peux la supprimer en désactivant les actions le temps du redimensionnement en modifiant ton windowDidResize comme ceci
Même comportement sur MacBook Pro
Effectivement, si on supprime les effets d'ombre dans la macro de DESIGN des Layer l'effet de fuite disparaà®t.
J'avais déjà eu ce phénomène dans la page Actions sans bien comprendre pourquoi l'ombrage crée des problèmes.
Effectivement, cela ne contourne le problème sur mon test que si je fais le setFrame sur mon layer racine. A creuser.
À tout hasard, est-ce que ça pourrait venir de ce bug connu :
http://developer.apple.com/releasenotes/GraphicsImaging/RN-CoreImage/index.html#//apple_ref/doc/uid/TP40006640-DontLinkElementID_2 ?
+
Chacha
Non, du moins je ne vois pas. Là il semble qu'il soit juste question d'évolution sur certains filtres Core Image entre Tiger et Leopard. Pas de lien avec Core Animation.
Dans la doc sur Core Animation, je n'ai pas vu clairement quand il fallait mettre le parenthésage d'instructions [CATransaction begin] [CATransaction commit]
Faut-il le mettre toujours (l'exemple donné dans la doc (Menu) ne le met pas) ?
Est-ce que ce ne serait un facteur de synchronisation, qui, lors de tâches particulièrement lourdes, serait indispensable ?
Je suis un peu surbooké cette semaine, je ne pourrais faire des comparaisons que la semaine prochaine.
On peut aussi utiliser une suite de begin/commit/flush pour enchaà®ner des modifications les unes derrières les autres sur différents layers (ex: faire apparaà®tre plusieurs boutons un par un avec une petite pose entre chaque).