Указатели реализации Objective-C
В настоящее время я пишу синтаксический анализатор 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];
Надеюсь, это поможет пролить немного света на то, что я делаю неправильно. Как я уже сказал, я новичок в этой области программирования (и на самом деле, я на самом деле математик, а не программист по образованию...), так что я действительно с энтузиазмом учусь не тому, что делать!!
2 ответа
Вы микрооптимизируете, не давая общего представления о том, в чем заключается проблема.
Вы сканируете (SAX) XML или просматриваете структуру DOM? Есть ли проблемы с памятью? Даже когда SAX-синтаксический анализ XML и у вас нет NSAutoreleasePools на месте, вы можете выделить много памяти.
Я не верю, что диспетчеризация метода objc является источником вашей проблемы с производительностью. Вы должны использовать Акулу, чтобы определить узкое место. Сам разбор, конечно же, не проблема: связанный файл 1,4 МБ XML проходит через 0,1 секунды xmllint -format
Если вам нужна дополнительная помощь, вам нужно описать больше того, что вы делаете: тип парсера, какие данные или объекты вы создаете, больше кода.
Есть поговорка:
Преждевременная оптимизация - корень всего зла.
Если вам нужно сравнить имя элемента с ожидаемым значением, вам придется выполнить сравнение символьных строк в какой-то момент. Вы можете исключить некоторые определенные случаи, не равные, сравнив сначала хэши, но не забывайте, что вычисление хэша также имеет свою стоимость. И вообще, как вы думаете, Apple уже не думала об этих оптимизациях при реализации isEqualToString:?
Я провел некоторое профилирование приложений Objective C с использованием Shark и обнаружил, что в крайних случаях накладные расходы obj_message_send могут составлять до 20-25%. Таким образом, гипотетически, если вы исключите каждую отправку сообщения, ваши 13 секунд могут снизиться до 10 секунд. Это достаточно хорошо? Я сомневаюсь.
Рассмотрим также, что происходит внутри NSXMLParser. Он будет все время сравнивать строки, чтобы проанализировать фактический XML. По сравнению с тем, что он должен делать, ваши сравнения строк, вероятно, совершенно незначительны. Вам абсолютно необходимо профилировать свой код, чтобы узнать, куда лучше направить ваши усилия по оптимизации. Если окажется, что 12 из 13 секунд потрачены на разрешение IP-адреса хоста, с которого вы загружаете XML, то ничто из того, что вы делаете со своим кодом, не поможет.