4

继续这篇文章:使用 NSMutableDictionary 与 NSMutableArray 产生的性能损失>

我正在尝试进行一个小测试,看看性能差距是否对于 NSArray 和 NSDictionary 以及它们的可变 coutnerparts 之间的读写有那么大...

但是,我很难找到“平衡”测试......因为字典有 2 个(或 3 个,取决于你如何看待这个)对象来循环获取所寻求的值(不是键),而数组只有一...

有什么建议么?

--如果你想要更多细节: 我的意思是通过例子更容易解释;

对于数组:(对于数组中的 NSString *str){ 用字符串做 smth }

对于字典

(for NSString *str in [dictionary allValues]) { string }

或者

(for NSString *str in [dictionary allKeys]) { [dictionary valueForKey:key] }

或者

(for NSString *str in [dictionary allKeys]) { string }

甚至

NSArray *valuesOrKeys = [dictionary allKeys/allValues];

(for NSString *str in valuesOrKeys) {string }

为字典做的“最公平”的测试是什么?

--编辑(评论)

正如你们都指出(并问我为什么想要那样),当使用字典时,这是因为它比数组更适合模型......

好吧,我问的原因是我正在构建的应用程序非常缓慢,所以我试图弄清楚使用不同的数据类型是否会改变其中的任何一个,我正在考虑使用基本的 c 数组......在这一点上我有选择权,所以我可以改变内部运作以适应我想要的任何类型......

4

3 回答 3

12

我想向您指出以下文章:“数组”,作者是 Apple 的工程师荒谬的_fish。Cocoa 数组不一定是如您所想的那样实现良好的朴素数组,字典也不是简单的哈希表。它们的表现是非常间接的,并且取决于它们持有的对象的数量(以及它们的值等)。这可能不会直接影响答案,但需要考虑(NSDictionary当然,性能会随着散列函数的速度和可靠性而变化,等等)。

此外,如果您正在寻找“平衡”测试,则必须寻找一种方法让两个类的行为尽可能接近。您想排除通过字典中的键访问值的可能性,因为这 - 无论维护的底层数据结构的查找时间有多快NSDictionary- 都比简单地从数组中拉出对象要慢,因为您正在执行更多操作来做到这一点. O(1)对于哈希表,从数组访问是O(1)最好O(n)的和最坏的(取决于实现,在中间的某个地方)。

如上所述,有几种方法可以枚举字典和数组。您将希望使用在实现方面彼此最接近的方法,这些方法要么是基于块的枚举(enumerateObjectsUsingBlock:forNSArrayenumerateKeysAndObjects:for NSDictionary),要么是快速枚举(使用allKeysor 或allValuesfor the NSDictionary)。因为这些算法的性能主要是经验性的,所以我进行了几次测试来记录访问时间(每个都有 10000 个NSNumber对象):

NSArray, Block Enumeration:
1. 10.5s
2.  9.1s
3. 10.0s
4.  9.8s
5.  9.9s
   -----
    9.9s Avg

NSArray, Fast Enumeration:
1.  9.7s
2.  9.5s
3.  9.3s
4.  9.1s
5. 10.5s
   -----
    9.6s Avg

NSDictionary, Block Enumeration
1. 10.5s
2. 10.6s
3.  9.9s
4. 11.1s
5. 11.0s
   -----
   10.6s Avg

NSDictionary, allKeys -> Fast Enumeration
1. 10.0s
2. 11.2s
3. 10.2s
4. 10.8s
5. 10.8s
   -----
   10.6s Avg

NSDictionary, allValues -> Fast Enumeration
1. 10.7s
2. 10.3s
3. 10.5s
4. 10.5s
5.  9.7s
   -----
   10.3s Avg

从这个人为测试的结果中可以看出,NSDictionary明显慢于NSArray(使用块枚举慢约 7%,使用快速枚举慢 7-10%)。然而,这种比较是相当没有意义的,因为无论如何使用最快的枚举NSDictionary只是将它转移到一个数组中。

所以最大的问题是,你为什么要考虑使用字典?数组和哈希表不能完全互换。你有什么样的模型可以直接替换NSArraywith NSDictionary?无论人为设计的示例给出的时间以某种方式证明性能优势,您都应该始终以一种有意义的方式实现您的模型——如果需要,您可以稍后优化性能。我看不出您将如何互换使用这些数据结构,但无论如何,NSArray这是赢家,特别是考虑到您尝试访问值的顺序。

于 2012-05-11T04:14:33.783 回答
5

这是使用快速枚举的“平衡”测试:

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    // do something with objects    
}];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    // do something with objects    
}];
于 2012-05-11T08:50:43.197 回答
1

我正在尝试进行一个小测试,看看性能差距是否对于 NSArray 和 NSDictionary 以及它们的可变 coutnerparts 之间的读写有那么大...

为什么?如果只是为了满足你的好奇心,那是一回事。但通常如果你需要字典,数组真的不行,反之亦然。因此,在给定的操作中,哪一个更快并不重要——这并不是说一个是另一个的好选择。

但是,我很难找到“平衡”测试......因为字典有 2 个(或 3 个,取决于你如何看待这个)对象来循环以获取所寻求的值(而不是键),而数组只有一...

您在这里做出了一些不太可能有效的假设。访问任何一种容器的元素可能并不涉及很多循环。

于 2012-05-11T12:21:36.857 回答