Objective-C to plain c iPhone game performance improvements

| | August 5, 2015

I’m testing a 2D OpenGL ES based iPhone game on both the iPhone 3G and the iPhone 4. It runs great on the iPhone 4… and pretty well on the 3G. The game state is updated at 60 Hz… and the rendering is done at 60 fps. Would the following conversion from Objective-C to c improve the performance at all?

// current Objective-C function
- (void) updateSomething {
    // simple update like x_position += 2.0;

// plain c function
void updateSomething(){
    // simple update like x_position += 2.0;

Assume these functions are called at a rate of 60 Hz. The reason I’m curious is this blog post. The author mentions substantial performance improvements when making a similar conversion.


Edit: after running w/ the CPU Sampler instrument in XCode it looks like about 65% of the function calls are to mach_msg_trap. objc_msgSend apparently takes up a trivial amount of resources.

4 Responses to “Objective-C to plain c iPhone game performance improvements”

  1. I have a couple of games up on the App Store right now that were written in 100% Obj-C. There are definitely some areas where a naive approach would suck in Obj-C (particles, for example), but overall it’s not as bad as some people make it out to be.

    By using Obj-C, I was able to make heavy use of the foundation collection classes, like NSMutableArray, NSMutableSet, etc, etc. I can’t stress how nice it was to be able to just use Obj-C’s fast enumeration to quickly apply a change to set of game objects. I use them everywhere.

    My suggestion would be to make sure your low level code is written well and not to worry about the higher level code unless you see something that needs to be addressed performance wise. There are plenty of games that you can write without having to worry about dropping down to C++ or C — even on the original iPhone.

  2. I think you might have been a bit inaccurate in your description of the problem. It sounds like you are calling this function 60Hz. That is 60 times per second. But given that it updates a position, I assume what you mean is it gets called 60 x number_of_game_objects times per second at least. So it depends on number of objects which you update position of.

    Also remember that most of the performance hit is likely due to lack of inlining and cache misses. That will not show up in your profiler as objc_msgSend taking up a lot of time, because the other instructions will be slowed down due to cache misses. A more Data Oriented Design could reduce these problems. E.g. if your Objective-C methods handle collections of objects rather than single objects. E.g. your update method could update several positions instead of just one.

    To be fair I don’t think your particular example would be a problem performance wise, but in my case I have to simulate that objects move down multiple paths each frame to find an optimal tactical path. Then these kind of update methods gets called a lot of times per frame, and need to be as fast as possible.

  3. I asked pretty much this question on Stackoverflow a while back. The conclusion was that it is quite a bit slower than a C++ virtual function call (which is what I’d compare it to rather than a C function call which is much faster still) and the compiler cannot inline them, but you shouldn’t worry about it unless you have a perf problem.

    Remember that Cocoa Touch is using Obj-C message dispatch to do all the communication of events within the user interface of the whole iPhone as well as for setting properties when it repositions a UIView during a scroll. So clearly it’s not a holdup for realtime animation, but I’m not as sanguine about it as some Cocoa fans. I wouldn’t, for example, have a particle system with each particle implemented as an Obj-C object, whereas I’d be happy to implement each as a C++ object (although without virtual functions because they wouldn’t be needed).

  4. For a function that is called at 60hz you’re not gonna notice a difference, a profiler pretty much can’t pick up on that. Rule #1, identity bottlenecks – and don’t mention fight club of course.

    Now if those functions call other functions that call other functions in a loop and call other functions, then it starts adding up.
    How much? That you can only find out by trying. But at least try it with the function that are called hundreds of times per frame to get any significant difference.
    If you don’t use ObjC functionality to begin with (might be smart to at least isolate it for porting purposes might the opportunity arise, and it’s good practise to keep platform dependencies wrapped away anyhow) the conversion should be fairly trivial.

Leave a Reply