Consommation mémoire hallucinante en parsant des fichiers xml
zeus
Membre
Bonjour,
Je suis en train d'écrire un programme qui est amené à parser une très grosse quantité de fichier xml (plusieurs dizaines de milliers). J'ai donc opté pour un NSXMLParser qui est un parseur événementiel, afin d'éviter de créer une représentation en mémoire du fichier xml courant. Jusque là tout vas bien. Là où les choses commence à se gâter, c'est quand je regarde l'occupation mémoire dudit programme. Lorsque je parse juste une centaine de fichier j'arrive déjà à une consomation mémoire de 212 Mb et 477 Mb de virtuelle. J'ai bien évidemment été vérifier avec ObjectAlloc si je n'avais pas un memory leackage et cela ne semble pas être le cas. J'ai aussi lancer mon application via MallocDebug et là pour le coup le programme m'indique que j'occupe 2Mb d'espace mémoire.
Comment dois-je faire pour que MallocDebug m'indique effectivement là ou je consomme la mémoire (car je ne pense pas que la commande top reporte un consommation mémoire erronée)?
Merci d'avance.
Jérôme
[EDIT]
Je viens de jouer un peu avec l'outils en ligne de commande qui se nomme "leaks" et, la, je constate que: primo ,j'ai le framework de cocoa qui leaks ,mais en plus de ça j'ai cette ligne forte intéressante:
Ce qui tendrait à prouver que je consomme bien 2Mb de ram. Alors pourquoi diable la commande top m'indique que 113 Mb sont alloué. Ce qui me semble très douteux, c'est que quand je parse un plus grand nombre de fichiers et que mon allocation mémoire dépasse le 1,65 Gb j'ai bien l'impression que le système swap (j'ai 2 Gb de ram). Des idées.
[/EDIT]
Je suis en train d'écrire un programme qui est amené à parser une très grosse quantité de fichier xml (plusieurs dizaines de milliers). J'ai donc opté pour un NSXMLParser qui est un parseur événementiel, afin d'éviter de créer une représentation en mémoire du fichier xml courant. Jusque là tout vas bien. Là où les choses commence à se gâter, c'est quand je regarde l'occupation mémoire dudit programme. Lorsque je parse juste une centaine de fichier j'arrive déjà à une consomation mémoire de 212 Mb et 477 Mb de virtuelle. J'ai bien évidemment été vérifier avec ObjectAlloc si je n'avais pas un memory leackage et cela ne semble pas être le cas. J'ai aussi lancer mon application via MallocDebug et là pour le coup le programme m'indique que j'occupe 2Mb d'espace mémoire.
Comment dois-je faire pour que MallocDebug m'indique effectivement là ou je consomme la mémoire (car je ne pense pas que la commande top reporte un consommation mémoire erronée)?
Merci d'avance.
Jérôme
[EDIT]
Je viens de jouer un peu avec l'outils en ligne de commande qui se nomme "leaks" et, la, je constate que: primo ,j'ai le framework de cocoa qui leaks ,mais en plus de ça j'ai cette ligne forte intéressante:
Process 1108: 20008 nodes malloced for 2173 KB
Ce qui tendrait à prouver que je consomme bien 2Mb de ram. Alors pourquoi diable la commande top m'indique que 113 Mb sont alloué. Ce qui me semble très douteux, c'est que quand je parse un plus grand nombre de fichiers et que mon allocation mémoire dépasse le 1,65 Gb j'ai bien l'impression que le système swap (j'ai 2 Gb de ram). Des idées.
[/EDIT]
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Je dois dire que je n'y croyais pas trop à cette idée d'éviter les éléments auto releasés, mais suite à un refactoring du code, j'ai essayé, quand même, pour voir ce que ça donnait. Et bien, je dois dire qu'après quelques tests préliminaire et la suppression de 4 éléments auto releasés (qui était dans des objets instanciés environ 1000 fois), j'ai pu diminué de plus 50% mon empreinte mémoire. Tout ceci sans parler du gain de temps lors de l'exécution.
Je vais donc encore me promener dans mon code voir si je n'ai pas d'autres candidats à l'éradication du auto release.
En tout cas merci Renaud pour l'idée. :adios!:
[tt]
NSAutoreleasePool *pool;
for ( i=0 ; i < x ; i++ ) {
pool = [NSAutoreleasePool new];
// ton code
[pool release];
}[/tt]
ça aide aussi.
Et il semble qu'Apple n'ait pas mis des autoreleasepool forcément partout non plus où ça aurait pu être nécessaire, dans son code "interne"
(Je pense en particulier aux grosses boucles travaillant sur les images, qui semblent garder en mémoire des objets temporaires jusqu'à la fin de la RunLoop, même si on a pris soin de notre côté de n'utiliser que des objets non autorelease)
Donc au final j'ai diminué l'empreinte mémoire de mon application d'un facteur 12, pas mal non.
Je pense que la diminution liée à la gestion de sa propre autorelease pool est particulièrement importante dans mon cas, de par le fait que je parse beacoup de fichiers et que dans cette opération je manipule beaucoup de NSMutableString (qui doivent utiliser quelque part des mécanisme de autorelease).
Merci encore a Renaud.
J'avais apris ici en effet que sur des grosses boucles ça faisait du bien (merci OC), mais je pensais pas que ça pouvait gagner à ce point... c'est énorme !!
Toujours bon à noter, ça va me donner envie d'y réfléchir plus souvent qd je fais des boucles