2

我目前正在编写一个 XML 解析器,它解析大量数据,有很多不同的节点(XML 不是我设计的,我无法控制内容......)

无论如何,目前下载和阅读需要非常长的时间(大约 13 秒),所以我正在寻找提高阅读效率的方法。

我写了一个函数来创建哈希值,这样程序就不再需要做很多字符串比较(只是 NSUInteger 比较),但这仍然没有降低读取的复杂性......

所以我想也许我可以创建一个 IMP 数组,这样我就可以像这样:

for(int i = 0; i < [hashValues count]; i ++)
{
    if(currHash == [[hashValues objectAtIndex:i] unsignedIntValue])
    {
        [impArray objectAtIndex:i];
    }   
}

或类似的东西。

唯一的问题是我不知道如何实际调用 IMP 函数?

我读过我执行 IMP 定义的选择器

IMP tImp = [impArray objectAtIndex:i];
tImp(self, @selector(methodName));

但是,如果我无论如何都需要知道选择器的名称,那有什么意义呢?

任何人都可以帮我解决我想做的事情吗?甚至只是更多提高解析器效率的方法......

以下是我的 NSXMLParser 代表的一些摘录:来自 didStartElement

if([elementName isEqualToString:@"playingFilmData"])
{
    appDelegate.arrPlayingFilms = [[NSMutableArray alloc] init];
appDelegate.arrSessionTimes_ByFilm = [[NSMutableArray alloc] init];
appDelegate.arrSessionTimes_ByCinema = [[NSMutableArray alloc] init];
[self releaseData];
return;
}
else if([elementName isEqualToString:@"film_sessions"])
{
    aFilm.arrSessions = [[NSMutableArray alloc] init];
    [self releaseData];
    return;
}
else if([elementName isEqualToString:@"session"])
{
    aSession = [[ATM_SessionObject alloc] init];
    aSession.session_filmID = aFilm.film_id;
    [self releaseData];
    return;
}
else if([elementName isEqualToString:@"sess"])
{
    aFilm.arrSessions = [[NSMutableArray alloc] init];
    [self releaseData];
    return;
}
else if([elementName isEqualToString:@"cin"])
{
    cinID = [attributeDict objectForKey:@"id"];
    [self releaseData];
    return;
}
else if([elementName isEqualToString:@"s"])
{
    aSession = [[ATM_SessionObject alloc] init];
    aSession.session_filmID = aFilm.film_id;
    aSession.session_cinemaID = cinID;
    [self releaseData];
    return;
}
else if([elementName isEqualToString:@"flm"])
{
    aFilm = [[ATM_FilmObject alloc] init];
    aFilm.film_id = [attributeDict objectForKey:@"id"];
    aFilm.film_epNum = 0;

    [self releaseData];
    return;
}

[self releaseData];

从 didEndElement

/*
 *0 = nowShowing_lastUpdate
 *1 = s
 *2 = tit
 *3 = des
 *4 = rate
 *5 = dir
 *6 = act
 *7 = rel
 *8 = flm
 */

NSUInteger numHash = [appDelegate murmerHashKey:elementName WithLegth:[elementName length] AndSeed:42];

if(currentElementValue)
{
if(numHash == [[hashValues objectAtIndex:0] unsignedIntValue])
{
    appDelegate.strNowShowingUpdate = currentElementValue;

    self releaseData];
    return;
}
else if(numHash == [[hashValues objectAtIndex:1] unsignedIntValue])
{
    [aFilm.arrSessions addObject:aSession];
    [appDelegate.arrSessionTimes_ByFilm addObject:aSession];

    [aSession release];
    aSession = nil;
}
else if(numHash == [[hashValues objectAtIndex:2] unsignedIntValue])
{
    [aFilm setValue:currentElementValue forKey:@"film_title"];

    [self releaseData];
    return;
}
else if(numHash == [[hashValues objectAtIndex:3] unsignedIntValue])
{
    [aFilm setValue:currentElementValue forKey:@"film_description"];

    [self releaseData];
    return;
}
else if(numHash == [[hashValues objectAtIndex:4] unsignedIntValue])
{
    [aFilm setValue:currentElementValue forKey:@"film_rating"];

    [self releaseData];
    return;
}
else if(numHash == [[hashValues objectAtIndex:5] unsignedIntValue])
{
    [aFilm setValue:currentElementValue forKey:@"film_directors"];

    [self releaseData];
    return;
}
else if(numHash == [[hashValues objectAtIndex:6] unsignedIntValue])
{
    [aFilm setValue:currentElementValue forKey:@"film_actors"];

    [self releaseData];
    return;
}               
}

if(numHash == [[hashValues objectAtIndex:8] unsignedIntValue])
{
[appDelegate.arrPlayingFilms addObject:aFilm];

[aFilm release];
aFilm = nil;

[self releaseData];
return;
}

[self releaseData];

我希望这有助于更多地了解我做错了什么。就像我说的,我是这个编程领域的新手(实际上,我实际上是一名数学家,而不是受过培训的程序员......),所以我真的非常热衷于学习而不是做什么!

4

2 回答 2

3

您正在进行微优化,而没有概述整个问题的含义。

您是在扫描 (SAX) XML 还是遍历 DOM 结构?有内存问题吗?即使在 SAX 解析 XML 并且您没有 NSAutoreleasePools 到位时,您也可以分配大量内存。

我不相信 objc 方法调度是您的性能问题的根源。您应该使用 Shark 来识别瓶颈。解析本身肯定不是问题:链接的 1.4MB XML 文件需要 0.1 秒才能运行xmllint -format

如果您需要更多帮助,您必须描述更多您正在做的事情:解析器的类型、您正在生成的数据或对象、更多代码。

于 2010-04-30T01:19:18.467 回答
1

有句话说:

过早的优化是万恶之源。

如果需要将元素名称与预期值进行比较,则必须在某个时候逐个字符串进行比较。您可以通过首先比较哈希来消除一些确定的不等于情况,但不要忘记,计算哈希也有成本。无论如何,你认为 Apple 在实现 isEqualToString: 时没有考虑到这些优化吗?

我使用 Shark 对 Objective-C 应用程序进行了一些分析,我发现在极端情况下,obj_message_send 的开销可能高达 20-25%。所以假设,如果你消除了每一条消息发送,你的 13 秒可能会减少到 10 秒。这够好吗?我对此表示怀疑。

还要考虑 NSXMLParser 内部发生了什么。它将一直进行字符串比较以解析实际的 XML。与它必须做的相比,您的字符串比较可能完全无关紧要。您绝对需要分析您的代码,以找出最适合您的优化工作的地方。如果事实证明 13 秒中有 12 秒用于解析您从中下载 XML 的主机的 IP 地址,那么您对代码所做的任何事情都无济于事。

于 2010-04-30T08:42:19.523 回答