Des fuites avec les images sous Core Animation?

MalaMala Membre, Modérateur
février 2008 modifié dans API AppKit #1
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.  :o

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à .  :o

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).

Réponses

  • MalaMala Membre, Modérateur
    19:33 modifié #2
    J'oubliais. Si certains on l'occasion de tester sur d'autre configs. Je suis sous 10.5.1 sur un MacBook. Même souci sur un iMac blanc 20". J'avais eu l'expérience avec des fuites sous  Core Image dont le résultat variait en fonction de la config.
  • Philippe49Philippe49 Membre
    19:33 modifié #3
    J'ai rencontré ce problème en faisant le site sur Core Animation.
    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.


  • MalaMala Membre, Modérateur
    19:33 modifié #4
    Je viens de télécharger ton projet pour voir. Chez moi Intrument montre que la mémoire monte régulièrement. En passant dans MallocDebug, la fuite semble venir de gl_blur_surface qui correspond à  l'animation appliquée en boucle à  ton layer. Cela m'inquiète de plus en plus ce problème.

    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

    <br />- (void)windowDidResize:(NSNotification *)notification<br />{<br />&nbsp; &nbsp; [CATransaction begin];<br />&nbsp; &nbsp; [CATransaction setValue:(id)kCFBooleanTrue <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  forKey:kCATransactionDisableActions];<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br />	if(selectedLayer==LEFTLAYER){<br />		selectionLayer.position=POSITION(leftLayer);<br />		selectionLayer.bounds=CGRectInset(leftLayer.bounds, -10., -10.);<br />	} else {	<br />		selectionLayer.position=POSITION(rightLayer);<br />		selectionLayer.bounds=CGRectInset(rightLayer.bounds, -10., -10.);<br />	}<br />	[self initKeyframeAnimations];<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; [CATransaction commit];<br />}<br />
    
  • Philippe49Philippe49 Membre
    19:33 modifié #5
    dans 1202659770:

    J'oubliais. Si certains on l'occasion de tester sur d'autre configs. Je suis sous 10.5.1 sur un MacBook. Même souci sur un iMac blanc 20". J'avais eu l'expérience avec des fuites sous  Core Image dont le résultat variait en fonction de la config.



    Même comportement sur MacBook Pro
  • Philippe49Philippe49 Membre
    février 2008 modifié #6
    dans 1202665761:

    Je viens de télécharger ton projet pour voir. Chez moi Intrument montre que la mémoire monte régulièrement. En passant dans MallocDebug, la fuite semble venir de gl_blur_surface qui correspond à  l'animation appliquée en boucle à  ton layer. Cela m'inquiète de plus en plus ce problème.

    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.
  • MalaMala Membre, Modérateur
    19:33 modifié #7
    dans 1202663523:

    Par contre, je ne détecte pas la disparition ddu phénomène avec le window resizing.

    Effectivement, cela ne contourne le problème sur mon test que si je fais le setFrame sur mon layer racine. A creuser.
  • ChachaChacha Membre
    19:33 modifié #8
  • MalaMala Membre, Modérateur
    19:33 modifié #9
    dans 1202746509:

    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.

  • Philippe49Philippe49 Membre
    19:33 modifié #10
    Une autre piste :
    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.
  • MalaMala Membre, Modérateur
    19:33 modifié #11
    En fait, le begin et commit ne sont pas obligatoire ici. Comme on est dans le thread principal, une modification  de CATransaction va s'appliquer à  tout les layers modifiés dans le windowDidResize. Le begin et le commit se font automatiquement dans le runLoop. J'ai tendance à  les mettre systématiquement par habitude comme j'utilise souvent des threads.

    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).
Connectez-vous ou Inscrivez-vous pour répondre.