2010-04-30 92 views
2

我目前正在编写一个解析大量数据的XML解析器,其中包含许多不同的节点(XML不是由我设计的,我无法控制内容......)Objective-C实现指针

无论如何,它目前需要很长时间才能下载和阅读(大约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]; 

希望这有助于更清楚地表明我做错了什么。就像我所说的,我是这个编程领域的新手(实际上,我实际上是一名数学家,而不是一名训练有素的程序员),所以我非常热衷于学习不该做什么!

+0

你可以发布这个XML的例子吗?你正在做的事情几乎肯定不是做这件事的最好方式。 – 2010-04-30 00:33:32

+0

XML数据的一个例子可以在这里找到:http://rangers.theprojectfactory.com/_source/ATM_Data_NowShowing.xml – 2010-04-30 00:42:21

+0

我很困惑,为什么你认为需要知道选择器否定IMP缓存的整个点。 IMP缓存通常是一种微型优化,可以避免方法查找的开销 - 它不是绕过传递选择器参数的方式。另外,这对于在Objective-C中实现XML解析器的具体问题没有帮助,但我认为你会发现Core Foundation XML解析器比NSXMLParser快很多。 – Chuck 2010-04-30 01:50:27

回答

3

你是微观优化而不给出关于整个问题的概述。

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

我不认为objc方法调度是性能问题的根源。你应该使用鲨鱼来确定瓶颈。解析本身肯定不是问题:链接的1,4MB XML文件需要0.1秒才能运行xmllint -format

如果您需要更多帮助,则必须描述更多关于您正在执行的操作:类型解析器,你生产什么数据或对象,更多的代码。

+1

同意xml不是问题。通过“NSXMLParser”运行它只需要大约0.2秒。 – 2010-04-30 01:26:08

+0

谢谢:) 我子类NSXMLParser,所以我认为它遍历它(虽然我不完全确定,因为这个特定的区域对我来说是新的)。 我最初认为,也许很多很多很多的字符串比较是问题的原因,但是使用散列函数并没有加快速度。我会看看使用鲨鱼发生的事情! 失败的事情,我会更新我的问题与进一步的来源:) – 2010-04-30 01:29:08

+0

@Dwaine你为什么继承'NSXMLParser'?你不需要。你只需要提供一个自定义的委托对象。 – 2010-04-30 01:51:41

1

有句话说得好:

过早的优化是所有罪恶的根源。

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

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

请考虑NSXMLParser内部发生了什么。它将一直在进行字符串比较以分析实际的XML。与它所要做的相比,你的字符串比较可能是完全不重要的。您绝对需要需要来分析您的代码,以找出最适合您的优化工作的位置。如果事实证明13秒中有12秒被用来解析您从中下载XML的主机的IP地址,那么您对代码做的任何事情都不会有所帮助。