适用于iPhone的NSXMLParser内存分配效率

Sta*_*ros 6 iphone cocoa memory-management nsxmlparser

我最近一直在玩iPhone应用程序的代码来解析XML.坚持Cocoa,我决定使用NSXMLParser类.该应用程序将负责解析10,000多个"计算机",所有这些计算机都包含6个其他信息串.对于我的测试,我已经验证了XML的大小约为900k-1MB.

我的数据模型是通过唯一标识符将每台计算机保存在NSDictionary中.每台计算机也由NSDictionary代表信息.因此,在一天结束时,我最终得到一个包含10k其他NSDictionaries的NSDictionary.

我遇到的问题不是泄漏内存或高效的数据结构存储.当我的解析器完成后,分配的对象总量只会增加大约1MB.问题是当NSXMLParser运行时,我的对象分配高达13MB.我能理解2(一个用于我正在创建的对象,一个用于原始NSData)加上一个小工作空间,但13似乎有点高.我无法想象NSXMLParser效率低下.思考?

码...

开始解析的代码......

NSXMLParser *parser = [[NSXMLParser alloc] initWithData: data];
[parser setDelegate:dictParser];
[parser parse];
output = [[dictParser returnDictionary] retain];        
[parser release];
[dictParser release];
Run Code Online (Sandbox Code Playgroud)

而解析器的委托代码......

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {

    if(mutableString)
    {
        [mutableString release];
        mutableString = nil;

    }

    mutableString = [[NSMutableString alloc] init];     

}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 
    if(self.mutableString)
    {

        [self.mutableString appendString:string];

    }
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {

    if([elementName isEqualToString:@"size"]){
        //The initial key, tells me how many computers
        returnDictionary = [[NSMutableDictionary alloc] initWithCapacity:[mutableString intValue]];
}

    if([elementName isEqualToString:hashBy]){
    //The unique identifier
        if(mutableDictionary){
            [mutableDictionary release];
            mutableDictionary = nil;
    }       

        mutableDictionary = [[NSMutableDictionary alloc] initWithCapacity:6];

        [returnDictionary setObject:[NSDictionary dictionaryWithDictionary:mutableDictionary] forKey:[NSMutableString stringWithString:mutableString]];
}

    if([fields containsObject:elementName]){
        //Any of the elements from a single computer that I am looking for
        [mutableDictionary setObject:mutableString forKey:elementName];
}
}
Run Code Online (Sandbox Code Playgroud)

一切都正确初始化和发布.再次,我没有得到错误或泄漏.效率低下.

谢谢你的任何想法!

mfa*_*kas 6

NSXMLParser是一个记忆猪:

  1. 它不是真正的流解析器:: initWithURL将在处理之前下载完整的xml.对于内存使用,这是不好的,因为它必须为完整的xml分配内存,直到解析结束才能回收.对于性能而言,它也很糟糕,因为您不能交错下载的IO密集部分和解析的CPU密集部分.
  2. 它不会释放记忆.似乎在解析期间创建的字符串/字典一直保持到解析结束.我试图通过创造性的使用改进它, NSAutoreleasePool但没有任何成功.

替代方案是libxml和AQXMLParser,它是围绕libxml或ObjectiveXML的NSXMLParser兼容包装器.

有关详细信息,请参阅我的博客文章


Vla*_*mir 3

无法具体说明您的代码,但请看一下 Apple 的XMLPerformance示例 - 它比较了 NSXMLParser 和 libxml 性能 - 结果肯定有利于后者。在我的一个项目中,从 NSXMLParser 切换到 libxml 极大地提高了性能,因此我建议使用它。