Objective-C Implementation pointers
I am currently writing an XML parser that parses a lot of data, with a lot of different nodes (XML is not developed by me and I have no control over the content ...)
Anyway, it currently takes an unacceptably long time to load and read (about 13 seconds), so I am looking for ways to improve read performance.
I wrote a function to generate hash values โโso that the program no longer needs to do a lot of string comparisons (just NSUInteger comparisons), but that still doesn't reduce the complexity of reading in ...
So I thought maybe I can create an IMP array so that then I can do something like:
for(int i = 0; i < [hashValues count]; i ++)
{
if(currHash == [[hashValues objectAtIndex:i] unsignedIntValue])
{
[impArray objectAtIndex:i];
}
}
Or something like that.
The only problem is I don't know how to actually make the call to the IMP function?
I read that I am executing a selector that defines the IMP by going
IMP tImp = [impArray objectAtIndex:i];
tImp(self, @selector(methodName));
But, if I still need to know the name of the selector, what's the point?
Can someone help me with what I want to do? Or even a few more ways to improve the analyzer's efficiency ...
Here are some excerpts from my NSXMLParser delegate: From 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];
From 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];
Hope this helps shed some light on what I am doing wrong. As I said, I am new to this area of โโprogramming (and in fact, I am actually a mathematician, not a programmer, practicing ...), so I am very enthusiastic about learning what to do !! / p>
a source to share
You are optimizing microprovisioning without giving an overview of the whole problem.
Are you scanning (SAX) XML or traversing the DOM structure? Memory problems? Even when SAX is parsing XML and you don't have NSAutoreleasePools, you could allocate a lot of memory.
I don't believe objc method dispatch is the source of your performance problem. You must use a shark to identify the bottleneck. Of course, parsing is not a problem: a linked 1.4MB XML file takes 0.1s to execute throughxmllint -format
If you need more help, you need to describe more of what you are doing: the type of parser, what data or objects you create, more code.
a source to share
There is a saying:
Premature optimization is the root of all evil.
If you need to compare the name of an element with the expected value, you will need to perform character versus character string at some point. You can eliminate some specific cases not equal by comparing the hashes first, but remember that computing the hash has a cost as well. And in general, do you think Apple did not think about these optimizations when implementing isEqualToString :?
I have done some profiling of Objective-C applications using Shark and I have found that in a pinch, the overhead of obj_message_send can be as high as 20-25%. So, hypothetically, if you deleted every message, your 13 seconds could go down to 10 seconds. Is that good enough? I doubt it.
Let's also take a look at what's going on inside NSXMLParser. It will do string comparisons all the time to parse the actual XML. Compared to what it's supposed to do, your string comparisons are probably completely negligible. You absolutely need to profile your code to find out where to best direct your optimization efforts. If it turns out that 12 out of 13 seconds is wasted resolving the IP address of the host you are loading the XML from, nothing you do with your code will help you.
a source to share