Указатели реализации Objective-C - PullRequest
2 голосов
/ 30 апреля 2010

В настоящее время я пишу синтаксический анализатор 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 Delegate: Из 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];

Надеюсь, это поможет пролить немного света на то, что я делаю неправильно. Как я уже сказал, я новичок в этой области программирования (и на самом деле, я на самом деле математик, а не программист по образованию ...), поэтому я действительно с большим энтузиазмом учусь не тому, что делать !! 1027 *

Ответы [ 2 ]

3 голосов
/ 30 апреля 2010

Вы выполняете микрооптимизацию, не давая общего представления о проблеме.

Вы сканируете (SAX) XML или пересекаете структуру DOM? Есть ли проблемы с памятью? Даже если SAX-синтаксический анализ XML и у вас нет NSAutoreleasePools на месте, вы можете выделить много памяти.

Я не считаю, что диспетчеризация метода objc является источником вашей проблемы с производительностью. Вы должны использовать Акулу, чтобы определить узкое место. Сам разбор, конечно, не является проблемой: связанный файл XML размером 1,4 МБ занимает 0,1 сек. Для прохождения xmllint -format

Если вам нужна дополнительная помощь, вам нужно описать больше того, что вы делаете: тип парсера, какие данные или объекты вы создаете, больше кода.

1 голос
/ 30 апреля 2010

Есть поговорка:

Преждевременная оптимизация - корень всего зла.

Если вам нужно сравнить имя элемента с ожидаемым значением, вам нужно будет выполнить сравнение символьных строк в какой-то момент. Вы можете исключить некоторые определенные случаи, не равные, сравнив сначала хэши, но не забывайте, что вычисление хэша также имеет свою стоимость. И вообще, как вы думаете, Apple уже не думала об этих оптимизациях при реализации isEqualToString:?

Я провел профилирование приложений Objective C с использованием Shark и обнаружил, что в экстремальных случаях накладные расходы на obj_message_send могут составлять до 20-25%. Таким образом, гипотетически, если вы исключите каждое отдельное сообщение, отправленное , ваши 13 секунд могут снизиться до 10 секунд. Это достаточно хорошо? Я сомневаюсь в этом.

Рассмотрим также, что происходит внутри NSXMLParser. Он будет все время сравнивать строки, чтобы проанализировать фактический XML. По сравнению с тем, что он должен делать, ваши сравнения строк, вероятно, совершенно незначительны. Вам нужно для профилирования вашего кода, чтобы узнать, куда лучше направить ваши усилия по оптимизации. Если окажется, что 12 из 13 секунд потрачены на разрешение IP-адреса хоста, с которого вы загружаете XML, то ничто из того, что вы делаете со своим кодом, не поможет.

...