2012-09-10 62 views
0

有誰知道什麼是循環VS收集一個接一個使用valueForKeyPath與收集運營商之間的性能差異和手工做的計算?例如:Objective-C的valueForKeyPath性能VS循環

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; 

有什麼想法?

+1

你肯定'valueForKeyPath:@ 「@ sum.myProperty」'薩姆將達到整數值(而不是說,雙打?) – dasblinkenlight

+0

我相信它會返回NSNumber,但這裏的示例假定涉及的所有值都是int。 – clx

回答

3

我相信你的問題是基於共同使用收集運營商的誤解。核心數據的常見用途是,可以在SQL中更有效地累積數據,而不必錯誤地整個對象。

以我的經驗,簡單的循環是內存NSSetNSArray後備存儲快得多。

+0

該函數的最初目的是彙總來自通過關係連接的核心數據對象的值。假設集合中的所有對象都由於以前的函數調用而出現故障和內存,循環和valueForKeyPath方法是否會產生類似的性能? – clx

+0

您應該針對您的具體情況進行測試。這不是一個艱難的A/B測試。如果你能保證沒有錯誤或任何其他方面的行爲,那麼簡單循環總是比任何其他解決方案都快。在實踐中,有時很難保證對於大數據集(對於小數據集無關緊要)。 –

1

我會懷疑第一個實現更快,因爲一個經典的實現一組是通過哈希映射基於密鑰,從而使通過密鑰的O(1)算法查找與您手動爲O(n)實現。

這就是說,沒有比快速實驗更好的了。用數以千計的值加載您的NSSets並查看哪一個更快。

+1

的第一個片段是不是查找,在其實施有一個循環的地方:) :) :) – dasblinkenlight

+2

這裏期望的結果意味着,任何程序將不得不通過集合中的所有對象 - 有沒有辦法讓它比O(n)無關。 –

+0

同意約翰。隨着對象的添加,您可以保持一個正在運行的計數器,以避免稍後可能的大量求和例程,但是您必須訪問每個對象才能將它們添加到一起。 – MikeS

0

在我的與一組十萬名成員測試條件下,我發現,第二種方法中,簡單的循環也較快 - 0秒VS 32秒。有一百萬名成員,這是0秒vs 3秒。這確實假定所有數據都在記憶中,並且與Rob Napier的經驗一致。下面是測試代碼:

- (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); 
} 

而且TestObject的只是有這個在init:

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