Objective c nsdictionary与nsarray的读取性能

Objective c nsdictionary与nsarray的读取性能,objective-c,c,xcode,performance,benchmarking,Objective C,C,Xcode,Performance,Benchmarking,继续此帖子: 我正在尝试运行一个小测试,看看NSArray和NSDictionary以及它们的可变Coutnerpart之间的读写性能差距是否有那么大 然而,我很难找到一个“平衡”的测试。。。因为字典有2个(或3个,取决于您如何看待这一点)对象要循环通过以获取查找的值(而不是键),而数组只有一个 有什么建议吗 --如果您需要更多详细信息: 我的意思更容易通过例子来解释 对于阵列: (对于数组中的NSString*str){do smth with the string} 查字典 (for NSS

继续此帖子:

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

然而,我很难找到一个“平衡”的测试。。。因为字典有2个(或3个,取决于您如何看待这一点)对象要循环通过以获取查找的值(而不是键),而数组只有一个

有什么建议吗

--如果您需要更多详细信息: 我的意思更容易通过例子来解释

对于阵列: (对于数组中的NSString*str){do smth with the string}

查字典

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

甚至

NSArray *valuesOrKeys = [dictionary allKeys/allValues];

(for NSString *str in valuesOrKeys) {string }
对字典来说,“最公平”的测试是什么

--编辑(评论)

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


我问这个问题的原因是,我正在构建的一个应用程序速度非常慢,所以我试图弄清楚使用不同的数据类型是否会改变这一切,我正在考虑使用基本的c数组。。。在这一点上,我有选择权,因此我可以更改内部工作以适合我想要的任何类型…

我想向您介绍以下文章:“,作者,苹果公司的一名工程师。Cocoa数组不一定像您预期的那样是实现良好的原始数组,字典也不是简单的哈希表。它们的性能是非常间接的,取决于它们所持有的对象的数量(以及它们的值等)。这可能不会直接影响到答案,但这是要考虑的事情(<代码> NS字典)/代码>性能当然会随哈希函数的速度和可靠性而变化,等等。

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

如上所述,有几种方法可以枚举字典和数组。您需要使用在实现方面彼此最接近的方法,这些方法可以是基于块的枚举(
enumerateObjectsUsingBlock:
用于
NSArray
enumerateKeysAndObjects:
用于
NSDictionary
),也可以是快速枚举(使用
NSDictionary
allKeys
allValues
)。由于这些算法的性能主要是经验性的,我进行了几次测试来记录访问时间(每个测试有10000个
NSNumber
对象):

从这个人为测试的结果可以看出,
NSDictionary
明显比
NSArray
慢(使用块枚举大约慢7%,使用快速枚举大约慢7-10%)但是,这种比较是毫无意义的,因为对
NSDictionary
使用最快的枚举只会将其转移到数组中

所以,最大的问题是,为什么你要考虑使用字典?数组和哈希表不是完全可互换的,你有什么样的模型允许用<代码> NSCORCHON/<代码>来替换<代码> NSArray < /代码>?应该始终以合理的方式实现您的模型-如果有必要,您可以稍后进行性能优化。我不知道您将如何互换使用这些数据结构,但无论如何,
NSArray
在这里是赢家,特别是考虑到您尝试访问值的顺序。

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

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    // do something with objects    
}];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    // do something with objects    
}];
我正在尝试运行一个小测试,看看性能差距是否如此 非常适合在NSArray和NSDictionary以及 他们的可变Coutnerpart

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

然而,我很难找到一个“平衡”的测试…因为 字典中有2个(或3个,具体取决于您对此的看法)对象 循环以获取所查找的值(而不是键),而数组 只有一个


您在这里所做的一些假设可能是无效的。访问这两种容器的元素可能不会涉及太多循环。

这个答案假设创建一个值数组,然后枚举该数组是枚举字典内容的最快方法。这当然不是保证ed,可能是,也可能不是。事实上,没有性能保证,因此最好使用快速枚举策略。因此,您需要的是-[NSDictionary objectEnumerator]。或者,最好删除循环并调用enumerateKeysAndObjectsUsingBlock:(为了公平起见,在数组上调用enumerateObjectsUsingBlock:)。但是,这里的其他几点都是有效的。实际上,objectEnumerator甚至不能保证是直接快速枚举,因此block方法是确保尽可能快的唯一方法。以下是我通过快速测试得到的数字:-[NSDictionary allValues]3.60,直接枚举NSDictionary的键,然后调用objectForKey:
NSArray *valuesOrKeys = [dictionary allKeys/allValues];

(for NSString *str in valuesOrKeys) {string }
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
[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    // do something with objects    
}];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    // do something with objects    
}];