4

この投稿の続き:NSMutableDictionaryとNSMutableArrayを使用して発生したパフォーマンスへの影響>

私は、パフォーマンスのギャップがNSArrayとNSDictionaryの間、およびそれらの可変のcoutnerpartsの間の読み取りと書き込みに非常に優れているかどうかを確認するために、少しテストを実行しようとしています...

ただし、「バランスの取れた」テストを見つけるのに苦労しています...辞書には2つ(またはこれをどのように見るかによっては3つ)のオブジェクトがあり、配列にはキーではなく、シークされた値を取得するためにループします。 1...

助言がありますか?

-詳細が必要な場合: 私が言いたいのは、例を通して説明する方が簡単です。

配列の場合:(配列内の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

I'd like to point you at the following article: "Array", by ridiculous_fish, an engineer at Apple. Cocoa arrays are not necessarily well-implemented naïve arrays as you might expect, nor are dictionaries simple hash tables. Their performance is very circumstantial, and depends on the number of objects they hold (as well as their values, etc.). This might not directly affect the answer, but it's something to consider (NSDictionary performance will, of course, vary with the speed and reliability of your hashing function, and so on).

Additionally, if you're looking for a 'balanced' test, you'd have to look for a way for both classes to behave as close to each other as possible. You want to rule out accessing values via keys in the dictionary, because that — regardless of how fast seek times are for the underlying data structures maintained by NSDictionary — is slower than simply pulling objects from an array because you're performing more operations to do it. Access from an array is O(1), for a hash table, O(1) at best and O(n) at worst (depending on the implementation, somewhere in the middle).

There are several ways to enumerate both dictionaries and arrays, as you mentioned above. You're going to want to use the methods that are closest to each other in terms of implementation, those being either block-based enumeration (enumerateObjectsUsingBlock: for NSArray and enumerateKeysAndObjects: for NSDictionary), or fast enumeration (using either allKeys or allValues for the NSDictionary). Because the performance of these algorithms is mainly empirical, I performed several tests to note access times (each with 10000 NSNumber objects):

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

As you can see from the results of this contrived test, NSDictionary is clearly slower than NSArray (around 7% slower using block enumeration, and 7–10% slower with fast enumeration). However, this comparison is rather pointless, seeing as using the fastest enumeration for NSDictionary simply devolves it into an array anyway.

So the big question is, why would you consider using a dictionary? Arrays and hash tables aren't exactly interchangeable; what kind of model do you have that allows drop-in replacement of NSArray with NSDictionary? Regardless of the times given by contrived examples to prove performance benefits one way or another, you should always implement your models in a way that makes sense — you can optimize later for performance if you have to. I don't see how you would uses these data structures interchangeably, but anyway, NSArray is the winner here, especially considering the sequential order in which you're attempting to access values.

于 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つ)のオブジェクトがあり、配列にはキーではなく、シークされた値を取得するためにループします。 1...

ここでは、有効ではない可能性が高いいくつかの仮定を行っています。どちらの種類のコンテナの要素にもアクセスするために、おそらく多くのループは必要ありません。

于 2012-05-11T12:21:36.857 に答える