Objective-C valueForKeyPath performance vs looping

Does anyone know what's the performance difference between using valueForKeyPath with collection operator vs looping the collection one-by-one and manually does the calculation? For example:

NSSet* myObjects = [NSSet setWithObjects:obj1, obj2, obj3, nil];
NSNumber* sum = [myObjects valueForKeyPath:@"@sum.myProperty"];

vs

NSSet* myObjects = [NSSet setWithObjects:obj1, obj2, obj3, nil];
int sum = 0;
for(MyObject* obj in myObjects)
    sum += obj.myProperty.intValue;

Any thoughts?

Answers


I believe your question is based on a misunderstanding of the common use of collection operators. The common use is for Core Data, where the data can be accumulated more efficiently in SQL without having to fault the entire object.

In my experience, simple loops are much faster for in-memory NSSet or NSArray backing stores.


I would suspect that the first implementation is faster because one classic implementation of a set is through a hash map based on the key, thereby making the lookup by key an O(1) algorithm vs. your manual O(n) implementation.

This being said, there's nothing better than a quick experiment. Load up your NSSets with thousands of values and see which one is faster.


Under my test conditions with a set of ten million members, I found that the second method, the simple loop was faster -- 0 seconds vs 32 seconds. With a million members it was 0 seconds vs 3 seconds. This does assume all the data is in memory, and agrees with Rob Napier's experience. Here is the test code:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    NSMutableSet *testSet = [NSMutableSet set];
    int i = 0;
    while (i <10000000) {
        [testSet addObject:[[TestObjects alloc] init]];
        i++;
    }
    NSLog(@"%@",[NSDate date]);
    NSNumber* sum = [testSet valueForKeyPath:@"@sum.myProperty"];
    NSLog(@"%@",[NSDate date]);
    NSLog(@"%@",sum);

    NSLog(@"%@",[NSDate date]);
    long long sum2 = 0;
    for(TestObjects *obj in testSet)
        sum2 += obj.myProperty;
    NSLog(@"%@",[NSDate date]);
    NSLog(@"%lld",sum2);
    NSLog(@"%ld",testSet.count);
}

And the TestObject had just this in the init:

-(id)init {
    if (self = [super init]) {
        self.myProperty = arc4random() %100;
    }
    return self;
}

Need Your Help

How to add image to navigation bar

html css

How to add image to navigation bar

Screen Orientation Issue on Page using Jquery Mobile

html5 jquery-mobile orientation

I have just started working on mobile web apps, i am making HTML5 pages using Jquery Mobile. I tested my pages on iPhone &amp; iPad. The issue is that when i change from portrait to landscape and...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.