代码之家  ›  专栏  ›  技术社区  ›  wintermute

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

  •  0
  • wintermute  · 技术社区  · 14 年前

    我一直在做一些测试,我的一个需求是从不同的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];
        }
    

    使用“build and analyze”命令不会导致泄漏或任何问题,并且代码在生成时不会发出警告,但内存消耗仍介于50到70MB之间(仅考虑活动字节,总体来说几乎翻了一番)。
    显然,这个想法不是读取同一个文件的100倍,但是作为测试数据,它已经足够了,因为代码只需要从XML文件中读取内容,并按照接收的顺序将它们发送到一个文件中。

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

    编辑 -只是让事情更有趣一点:最好是保持一个解析器来读写,这样最好是坚持gdataxml,或者,如果需要更改,使用kissxml、tinyxml或libxml-dom,所有这些都会占用更多的内存,如前所述。 here 因此,如果有一种方法强制释放内存,那将是最好的。

    事先谢谢:)

    2 回复  |  直到 14 年前
        1
  •  1
  •   wintermute    14 年前

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

    我所要做的就是实例化一个autoreleasepool,并在循环结束时将其耗尽。
    这样地:

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

    这强制释放在for中被标记为autorelease的对象,正如预期的那样,这些对象在结束后才被释放,而不会干扰其他所有内容,因此在应该释放之前没有释放任何对象。
    在循环过程中,内存消耗从一个60~80MB的惊人值下降到了1,6MB,之后又回到同样的600KB(只是一个虚拟应用程序完成了这一点)。

    我还是会把这个问题留一段时间,以防有人有更好的想法,但目前看来,这是可行的方法:)

        2
  •  0
  •   jbm    14 年前

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