2010-04-30 87 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地址,那麼您對代碼做的任何事情都不會有所幫助。