逐渐写入文件时优化内存消耗

时间:2010-08-11 20:15:24

标签: iphone objective-c cocoa-touch nsfilehandle

我一直在做一些测试,我的一个需求是从不同的xml文件中读取数据并将它们堆叠在一个文件中。虽然我已经成功实现了这一目标,但内存消耗对于任务来说似乎相当大,iphone模拟器甚至没有提高内存警告,但我不认为真正的iPhone会容忍这个(我没有这是一个在这里尝试的设备,所以我大部分时间都是从我读过的内容中推测出来的 代码的(主要部分)如:

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];
    }

使用“构建和分析”命令不会泄漏或任何东西,并且代码在构建时不会引发警告,但是,内存消耗仍然在50到70mb之间(仅考虑实时字节,总体上它几乎加倍) )。
这个想法显然不是读取相同文件的100倍,而是作为测试数据,它足以满足要求,因为代码必须只读取xml文件中的内容并按接收顺序将它们发送到文件中。

在分配新的临时对象之前,有没有办法强制释放一些临时对象,我是否可以尝试重用一些变量,任何帮助我控制它的想法都是非常受欢迎的。

编辑 - 只是为了让事情变得更有趣:保持单个解析器的读写效果会更好,最好是坚持使用GDataXML,或者如果需要改变,使用KissXML,TinyXML或libxml - DOM,这些都似乎吸收了更多的内存,如here所述,所以如果有办法强制释放内存,那就是最好的。

提前致谢:)

2 个答案:

答案 0 :(得分:1)

实际上,这是一个非常简单的解决方案。

我所要做的就是实例化一个AutoReleasePool并在循环结束时将其排出。
像这样:

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

这强制释放在for内实例化的标记为自动释放的对象,这些对象在结束之后才被释放,正如预期的那样,不会干扰其他所有内容,因此在它们应该之前没有释放任何对象。
在循环期间,内存消耗从大约60~80mb下降到1,6mb,并且在它之后回到相同的600kb(这是一个虚拟应用程序就是这样)。

我仍然会暂时搁置这个问题,以防有人有更好的想法,但就目前而言,这似乎就是这样:)

答案 1 :(得分:0)

是的,您通过将其全部读入NSData,然后在GDataXMLDocument中解析为DOM,将其“加倍”。如果您希望经历这样的大量XML数据,循环遍历多个文件等,那么您应该consider SAX based parsing instead,并直接从文件中流式传输而不是将其预加载到NSData中。通过这种方式,您不必“释放临时对象”,因为您只需要解析所需的信息,因为它已被解析。