Busted! Eight Reasons not to use ARC

On June 28, 2012, in idevblogaday, by Steffen Itterheim

So, you’ve heard about Objective-C automatic reference counting (ARC). And you’ve read about it here and there and every where. But you’re not using it.

Guess what? You’re not alone. There are developers out there who refuse to use ARC, who delay using it, who believe they just can’t use it or expressly decided against using ARC for the time being. They all have their reasons.

Most of them are wrong.

Here’s a summary of reasons I’ve heard (repeatedly) in the past months from developers who aren’t using ARC, or have tried it but gave up using it. And I’ll tell you why these rationalizations are wrong, or at least over-inflated.

Continue reading »

Whaaaaaat?

You heard right: if you want to forget about using retain, release and autorelease in your code, then the newly introduced automatic reference counting (ARC) mechanism (aka “automatic memory management”) is the way to go. And guess what?

Kobold2D Preview 6 fully supports ARC out of the box!

Download Kobold2D Preview 6

You may have heard that Cocos2D is incompatible with ARC at this time, and you’re right. However, the Cocos2D version in Kobold2D Preview 6 released just now has been improved to work with ARC. This post explains the most important changes to make Cocos2D compatible with ARC. All 15 Kobold2D example projects compile with and without ARC, just like the other libraries Kobold2D makes use of!

Continue reading »

iPhone Performance Killers

On March 8, 2011, in Programming, by Steffen Itterheim

Have a look at the following code, and then answer these questions before reading on:

  1. Which function will run faster?
  2. What will be the framerate for each function when run 100 times per frame on an iPhone 3G?
  3. Will wrapping the 100 calls to function1 in an NSAutoreleasePool show any difference?

[cc lang=”ObjC” height=”465″]
-(void) function1
{
CGPoint pos = [self position];
id x = [NSNumber numberWithFloat:pos.x];
id y = [NSNumber numberWithFloat:pos.y];
id objects = [NSArray arrayWithObjects:x, y, nil];
id keys = [NSArray arrayWithObjects:@”x”, @”y”, nil];
id dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
dict; // avoid compiler warning, is a noop
}

-(void) function2
{
CGPoint pos = [self position];
id x = [[NSNumber alloc] initWithFloat:pos.x];
id y = [[NSNumber alloc] initWithFloat:pos.y];
id objects = [[NSArray alloc] initWithObjects:x, y, nil];
id keys = [[NSArray alloc] initWithObjects:@”x”, @”y”, nil];
id dict = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
[x release];
[y release];
[objects release];
[keys release];
[dict release];
}
[/cc]

The Answers

  1. Which function will run faster? Answer: function1
  2. What will be the framerate for each function when run 100 times per frame on an iPhone 3G? Answer: 27 fps for function1 and 24 fps for function2.
  3. Will wrapping the 100 calls to function1 in an NSAutoreleasePool show any difference? Answer: no, but memory of temporary objects is released immediately.

Needless to say, on an iPod (4th Generation) and an iPad these tests all run at 60 fps and give no indication whatsoever that the performance on an iPhone 3G would suffer this much (and neither does the Simulator, of course). All the more reason to test early and often on older devices.

To autorelease or not?

Common wisdom may tell you that alloc/release is faster than autorelease. Even Apple recommends avoiding autorelease, right?

Not quite, because this is often misunderstood: Apple recommends to avoid autorelease but only for functions which create a lot of temporary objects and because of the constrained memory - not because it’s slow or even dangerous - autorelease is not dangerous.

Since memory is so constrained on 1st and 2nd generation iOS devices, it’s best to release that memory as soon as possible and don’t leave it allocated for longer than necessary. To achieve this, you can choose to do two things in this case: use alloc/release or enclose the loop in an NSAutoreleasePool. The latter option is preferred since it will release the memory right away, and not some time later. And autorelease is generally preferable because you will never, ever forget to send a release message to an object - which means it’ll be leaked and forever use up memory.

You can write well-performing, even better-performing code by using autorelease and using NSAutoreleasePool around tight loops creating many temporary autorelease objects.

Innocent looking code kills framerate

Did you expect that creating 100 rather simple NSDictionary instances each frame would drag the framerate down to around 24-27 fps? Me neither. I knew the code wasn’t going to be blazing fast, but I never expected it to have such an impact. However, it can be optimized somewhat since I’m unnecessarily creating two NSArray instances to hold the keys and values respectively before using them to create the NSDictionary. In fact we can get rid of them by using dictionaryWithObjectsAndKeys and doing this in a single step:

[cc lang=”ObjC”]
-(void) function1Optimized
{
CGPoint pos = [self position];
id x = [NSNumber numberWithFloat:pos.x];
id y = [NSNumber numberWithFloat:pos.y];
id dict = [NSDictionary dictionaryWithObjectsAndKeys:x, @”x”, y, @”y”, nil];
dict; // avoid compiler warning, is a noop
}
[/cc]

Sometimes it helps to look around what other ways there are to run the same code. In terms of performance this is an order of a magnitude faster and now clocks in at 42 fps. Still not good enough for realtime rendering obviously but an improvement of over 50% by cutting two NSArray allocations is a very simple and effective optimization.

Just as a general guideline, when I get rid of the two NSNumber instances and simply pass empty strings for x and y the framerate went back up to 60 fps. Of course that’s over-optimizing to the point where the code doesn’t work anymore. It just goes to show how expensive the creation of NSDictionary and NSArray are, as is wrapping simple types in NSNumber or NSValue objects.

If you can avoid allocation and temporary objects, avoid it. If you can’t, at least avoid creating temporary objects every frame. Re-use objects as much as possible. Unfortunately, that’s not an option for NSNumber objects since you can’t change the value of a NSNumber instance.

cocos2d Book, Chapter 2: Getting Started

On July 2, 2010, in Announcements, book, cocos2d, by Steffen Itterheim

Chapter 2 - Getting Started

This chapter starts with the usual prerequisites. Download and install iPhone SDK and cocos2d. Installing cocos2d Templates. Creating the first project from a cocos2d project template.

From what I already wrote I estimate that will be about one third of the chapter. I think what would be most interesting in this chapter is to talk about general code structure of cocos2d projects. The basic elements like Scenes, Layers and Nodes. How to transition from one screen to another, to see that we’re actually doing something cool with little effort. For that I think the scheduled selectors should also be introduced to time transitions, and one screen might be a Layer which is waiting for touch input to advance to the next screen.

It might also be a good place to discuss cocos2d memory management, like static autorelease initializers, and making sure dealloc gets called when you switch scenes - otherwise you’re obviously having a memory leak.

The goal is to get the reader into a position where he feels comfortable laying out a screen structure in cocos2d. He knows how to initialize objects and how to add and remove them from the scene. The foundation of working with cocos2d if you so will.

What do you think should be in Chapter 2?

Let me know if you think I’m missing anything important. If you don’t have any suggestions then just think about what you would expect from the chapter by reading this description, that might give you some thoughts.

Also I would welcome any tips and the common pitfalls first-time cocos2d developers might trap themselves into. Expert tips are also welcome, those little nasty things or habits which could bite you later on if you don’t consider them from the beginning.

I’m looking forward to your feedback! The earlier the better. Chapter 2 will be submitted next Friday, July 9th.

What’s planned for the Chapter after this one

Just to put Chapter 2 in context, for Chapter 3 I’m planning to talk about essential cocos2d classes and processes. Sprites, Labels, Menus, Actions, etc. It’ll show you how to work with them using small code snippets. The chapter will probably have a “reference” character with various code samples, so that experienced users feel comfortable skipping ahead while beginners still find it easy and encouraging to pick up the details.

Tagged with: