Reputation: 104065
I would like to add some automated performance test to my Objective-C application. (This is a game, so that I would like to see the current performance of key parts of the engine by simply running a set of tests.) To do this I want to write some timing support routine, something like this:
- (void) benchmarkSelector: (SEL) msg onObject: (id) target
{
// run the selector thousands of times, print detailed stats
}
The problem is that I am interested in milliseconds and I am afraid that calling performSelector
in the benchmarking code would skew the results quite a bit. How would you go around this? Should I go down to objc_msgSend
?
Upvotes: 8
Views: 4965
Reputation: 49034
Use methodForSelector:
, which returns a function pointer to the actual implementation, like so:
IMP methodImp = [target methodForSelector:msg];
for (int i=0; i<1000; ++i) {
NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
methodImp(target, msg);
NSTimeInterval duration = [NSDate timeIntervalSinceReferenceDate] - start;
// Do something with duration
}
Note that this strategy is useful for measuring the actual runtime of a method, but if you're going to be calling it with standard Objective-C message-passing syntax, then it might be just as relevant to include the message-passing overhead in your measurements.
Also, note that if the method actually takes any other parameters, you should cast the result of methodForSelector:
to a function pointer with the appropriate parameters, to avoid unexpected conversion of floats to doubles, etc. See the NSObject Class Reference for more information and examples.
Upvotes: 11