Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abusing Objective-C Shorthand Notation

Tags:

Other than giving old school Objective-C programmers heart attacks, are there any other performance implications to doing this:

NSMutableArray *derp = @[].mutableCopy

Versus this:

NSMutableArray *derp = [[NSMutableArray alloc] init];
like image 821
Luke The Obscure Avatar asked Aug 26 '13 21:08

Luke The Obscure


2 Answers

I am going to give a different sort of answer than the ones below.

Unless you've measured the performance of your app and found it lacking, and found it lacking right in that part of the code, you're optimizing for the wrong thing. (And if you have done that, you can easily measure which one is faster.)

You should be optimizing for clarity of code, speed with which you can write it, and likelihood that it's correct.

In that respect, I would favor the second code snippet over the first. It says pretty much exactly what you're trying to do. The first snippet is not only harder to read; it also commits the style error of using dot notation to invoke a method, not get the value of a property.

Plus causing heart attacks just isn't nice. :)

like image 149
dpassage Avatar answered Sep 28 '22 07:09

dpassage


Class clusters do not have an extra allocation and it has nothing to do with compiler magic. So yes, there is a significant difference between your examples (btw, -1000 internet points for dot-notation abuse.) Your first example has two allocations, the second has only one.

Since we don't have access to the actual source code for NSArray, we can look at GNUStep (an open source implementation) to see how they handle it. In NSArray.m (simplifying and omitting irrelevant stuff):

static GSPlaceholderArray   *defaultPlaceholderArray;
+ (void) initialize
{
    defaultPlaceholderArray = (GSPlaceholderArray*)
        NSAllocateObject(GSPlaceholderArrayClass, 0, NSDefaultMallocZone());
}

+ (id) alloc
{
    return defaultPlaceholderArray;
}

What's going on here is that NSArray defines a singleton, placeholder object that it always returns in alloc. When init is called on this singleton it instantiates the proper private subclass and returns that.

So, how can we tell if Apple's Foundation is doing the same thing? Pretty easy, we just run this test:

NSArray *a1 = [NSArray alloc];
NSArray *a2 = [NSArray alloc];
NSLog(@"%p, %p", a1, a2);

> "0x100102f30, 0x100102f30"

a1 and a2 do have the same memory location meaning Apple is also likely using the singleton approach. If we print out the class name it's __NSPlaceholderArray so that pretty much confirms it.

So yeah, stick with [NSMutableArray new] :)

UPDATE: Greg Parker points out that @[] is also a singleton so @[].mutableCopy results in only one allocation. So performance-wise the two examples are the same.

like image 20
Ben Dolman Avatar answered Sep 28 '22 08:09

Ben Dolman