2010-08-11 11 views
0

J'ai effectué quelques tests et l'un de mes besoins consiste à lire les données de différents fichiers XML et à les empiler dans un seul fichier. Alors que j'ai réussi à accomplir cela, la consommation de mémoire semble être assez grande pour la tâche, le simulateur iphone n'a même pas augmenté l'avertissement de la mémoire, mais je ne pense pas que le vrai iPhone tolérerait cela (je n'ai pas un appareil pour l'essayer ici, donc je spécule surtout à partir de ce que j'ai lu).
La (partie principale du) Code est comme:Optimisez la consommation de mémoire lors de l'écriture progressive dans un fichier

Boolean success = [fileManager createFileAtPath:documentsPath contents:nil attributes:nil]; 
[fileManager release]; 

if (success) { 
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:documentsPath]; 
    for (int i = 0; i < 100; i++) { 

     NSString *path = [[NSBundle mainBundle] pathForResource:@"mensagem_de_arquivo" 
                 ofType:@"xml"]; 
     NSData *data = [NSData dataWithContentsOfFile:path]; 
     GDataXMLDocument *xml = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil]; 
     NSArray *tokens = [xml nodesForXPath:@"//message/data" error:nil]; 
     if (tokens.count > 0) { 
      GDataXMLElement *token = (GDataXMLElement *)[tokens objectAtIndex:0]; 
      [fileHandle writeData:[[token stringValue] dataUsingEncoding:NSASCIIStringEncoding]]; 
     } 
     [xml release]; 
    } 

En utilisant la commande « Build and Analyze » me donne pas de fuite ou quoi que ce soit, et le code ne soulève pas d'avertissement lors de la construction, mais encore, la mémoire la consommation se situe entre 50 et 70 mégaoctets (en considérant seulement les octets vivants, dans l'ensemble, elle double presque). L'idée n'est évidemment pas de lire 100 fois le même fichier, mais en tant que données de test, il suffit de lire le contenu des fichiers xml et de les envoyer dans un fichier dans l'ordre où ils sont reçus.

Existe-t-il un moyen de forcer la libération de certains objets temporaires avant que de nouveaux ne soient alloués, pourrais-je essayer de réutiliser certaines variables, toutes les idées qui m'aident à garder ce contrôle sont vraiment les bienvenues.

Modifier - juste pour rendre les choses un peu plus intéressant: il serait préférable de garder un seul analyseur pour lire et écrire, et en ce que le mieux serait de rester avec GDataXML ou, si un changement était nécessaire , pour utiliser KissXML, TinyXML ou libxml-DOM, qui semblent tous aspirer un peu plus de mémoire, comme dit here, donc s'il y avait un moyen d'imposer la libération de la mémoire ce serait le meilleur.

Merci à l'avance :)

Répondre

1

En fait, c'était une résolution assez simple.

Tout ce que je devais faire était d'instancier un AutoReleasePool et de le vider à la fin de la boucle.
Comme ceci:

for (int i = 0; i < 100; i++) { 
    NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init]; 
    //... do everything I've done before... 
    [pool drain]; 
} 

Cette contrainte de publier des objets marqués comme autorelease instancié à l'intérieur du car, qui viennent d'être libéré après sa fin, comme il était prévu, sans interférer dans tout le reste, donc pas d'objets ont été libérés avant qu'ils devraient.
La consommation de mémoire a chuté de 60 ~ 80mb à quelque chose comme 1,6mb pendant la boucle, et revenir à la même 600kb après (c'était une application fictive qui fait juste cela).

Je laisse toujours cette question ouverte pendant un certain temps, au cas où quelqu'un a une meilleure idée, mais pour l'instant, semble que ce sera la façon :)

0

Ouais, vous avez « doublé » en lisant tout en un NSData, puis l'analyse syntaxique dans un DOM en GDataXMLDocument. Si vous envisagez de parcourir de nombreuses données XML comme celle-ci, de boucler plusieurs fichiers, etc., vous devriez alors consider SAX based parsing instead, et le diffuser directement à partir du fichier plutôt que de le précharger dans un NSData. De cette façon, vous n'aurez pas à "libérer des objets temporaires", car vous extrayez uniquement les informations dont vous avez besoin, car elles sont analysées.

+0

Ouais, « doublé » est une grande estimative, changer à base de SAX basé sur l'analyse de la consommation de la mémoire presque réduite de moitié, étant en mesure d'accomplir la même chose en utilisant 38mb, mais en prenant près de 5 fois plus pour terminer. Je garde le handle de fichier en tant que variable privée sur mon délégué et j'écris directement dans le fichier à partir de la méthode "foundCharacters", est-ce qu'il y a une meilleure façon de faire, vu que je n'ai besoin que d'un seul noeud? – wintermute

+0

Y at-il une raison de conserver le fichier ou le fichier XML une fois que vous avez trouvé ce noeud? Je copiais toutes les informations dont j'avais besoin hors du nœud, plutôt que de garder le nœud, puis je disposais de tout ce qui avait trait au fichier XML après cela. – jbm