I am considering using an NSMutableDictionary in place of my current NSMutableArray. This is primarily for KVC/KVO reasons. The collection will undergo heavy mutation within the inner loop of my drawing method. Can I expect to incur a significant performance hit if I go ahead with this replacement?
我正在考虑使用NSMutableDictionary代替我当前的NSMutableArray。这主要是出于KVC / KVO的原因。该集合将在我的绘图方法的内循环中经历重度变异。如果我继续进行此次更换,我是否可以预期会受到重大影响?
Cheers, Doug
3 个解决方案
#1
The only way to be sure is to measure. None of us have enough knowledge about how NSMutableDictionary's and NSMutableArray's implementations work, so there's little point asking.
唯一可以确定的方法是衡量。我们都没有足够的知识来了解NSMutableDictionary和NSMutableArray的实现是如何工作的,所以毫无疑问。
Granted, you could probably expect some hit since the dictionary has to do additional hashing that a simple array would not. Whether or not that is "significant" is hard to say.
当然,你可能会期待一些打击,因为字典必须做一个简单的数组不会做的额外散列。这是否“重大”很难说。
Again, measure.
#2
As they say you need to test these things. But... the following simple test was instructive for me to get an idea of the relative difference in speed between the NSMutableDictionary and NSMutableArray collection classes in the case of small size high allocation rate examples.
正如他们所说,你需要测试这些东西。但是......以下简单的测试对于我了解在小尺寸高分配率示例的情况下NSMutableDictionary和NSMutableArray集合类之间的速度的相对差异是有益的。
Running the following program the times were: (with garbage collection on) (on a recent quad core machine)
运行以下程序的时间是:(打开垃圾收集)(在最近的四核机器上)
NSMutableDictionary 4.624478 seconds NSMutableArray 1.806365 seconds
NSMutableDictionary 4.624478秒NSMutableArray 1.806365秒
int main (int argc, const char * argv[])
{
NSLog(@"Hello, World!");
LNCStopwatch* stopwatch = [[LNCStopwatch alloc] init];
[stopwatch start];
for (int i = 1; i< 1000000; i++)
{
NSMutableDictionary* dict = [[NSMutableDictionary alloc]init];
[dict setObject:@"a" forKey:@"a"];
[dict setObject:@"b" forKey:@"b"];
[dict setObject:@"c" forKey:@"c"];
[dict setObject:@"d" forKey:@"d"];
[dict setObject:@"e" forKey:@"e"];
[dict setObject:@"y" forKey:@"a"];
[dict setObject:@"x" forKey:@"d"];
}
[stopwatch stopAndLogTimeAndReset];
[stopwatch start];
for (int i = 1; i< 1000000; i++)
{
NSMutableArray* arr = [[NSMutableArray alloc]init];
[arr addObject:@"a"];
[arr addObject:@"b"];
[arr addObject:@"c"];
[arr addObject:@"d"];
[arr addObject:@"e"];
[arr replaceObjectAtIndex:[arr indexOfObject:@"a"] withObject:@"y"];
[arr replaceObjectAtIndex:[arr indexOfObject:@"d"] withObject:@"x"];
}
[stopwatch stopAndLogTimeAndReset];
return 0;
}
(The absolute times I don't think are really all that important, its just the relative times which are more important for these small size classes. For larger size classes of course the nature of the collection class will dominate, eg NSMutableDictionary should be O(1) to find an element, etc... )
(我认为绝对时间并不是那么重要,它只是相对于这些小型类更重要的相对时间。对于更大的类当然,集合类的性质将占主导地位,例如NSMutableDictionary应该是O (1)找一个元素等...)
#3
When you say "primarily for KVC/KVO reasons", can you elaborate?
当你说“主要是为了KVC / KVO的原因”时,你能详细说明吗?
If you're seeing performance problems due to excessive KVO firing under heavy mutation, consider firing the KVO notifications yourself once you're done:
如果您因重度突变导致过度KVO射击而出现性能问题,请考虑在完成后自行触发KVO通知:
[self willChangeValueForKey: @"myArray"];
// loop and mutate
[self didChangeValueForKey: @"myArray"];
#1
The only way to be sure is to measure. None of us have enough knowledge about how NSMutableDictionary's and NSMutableArray's implementations work, so there's little point asking.
唯一可以确定的方法是衡量。我们都没有足够的知识来了解NSMutableDictionary和NSMutableArray的实现是如何工作的,所以毫无疑问。
Granted, you could probably expect some hit since the dictionary has to do additional hashing that a simple array would not. Whether or not that is "significant" is hard to say.
当然,你可能会期待一些打击,因为字典必须做一个简单的数组不会做的额外散列。这是否“重大”很难说。
Again, measure.
#2
As they say you need to test these things. But... the following simple test was instructive for me to get an idea of the relative difference in speed between the NSMutableDictionary and NSMutableArray collection classes in the case of small size high allocation rate examples.
正如他们所说,你需要测试这些东西。但是......以下简单的测试对于我了解在小尺寸高分配率示例的情况下NSMutableDictionary和NSMutableArray集合类之间的速度的相对差异是有益的。
Running the following program the times were: (with garbage collection on) (on a recent quad core machine)
运行以下程序的时间是:(打开垃圾收集)(在最近的四核机器上)
NSMutableDictionary 4.624478 seconds NSMutableArray 1.806365 seconds
NSMutableDictionary 4.624478秒NSMutableArray 1.806365秒
int main (int argc, const char * argv[])
{
NSLog(@"Hello, World!");
LNCStopwatch* stopwatch = [[LNCStopwatch alloc] init];
[stopwatch start];
for (int i = 1; i< 1000000; i++)
{
NSMutableDictionary* dict = [[NSMutableDictionary alloc]init];
[dict setObject:@"a" forKey:@"a"];
[dict setObject:@"b" forKey:@"b"];
[dict setObject:@"c" forKey:@"c"];
[dict setObject:@"d" forKey:@"d"];
[dict setObject:@"e" forKey:@"e"];
[dict setObject:@"y" forKey:@"a"];
[dict setObject:@"x" forKey:@"d"];
}
[stopwatch stopAndLogTimeAndReset];
[stopwatch start];
for (int i = 1; i< 1000000; i++)
{
NSMutableArray* arr = [[NSMutableArray alloc]init];
[arr addObject:@"a"];
[arr addObject:@"b"];
[arr addObject:@"c"];
[arr addObject:@"d"];
[arr addObject:@"e"];
[arr replaceObjectAtIndex:[arr indexOfObject:@"a"] withObject:@"y"];
[arr replaceObjectAtIndex:[arr indexOfObject:@"d"] withObject:@"x"];
}
[stopwatch stopAndLogTimeAndReset];
return 0;
}
(The absolute times I don't think are really all that important, its just the relative times which are more important for these small size classes. For larger size classes of course the nature of the collection class will dominate, eg NSMutableDictionary should be O(1) to find an element, etc... )
(我认为绝对时间并不是那么重要,它只是相对于这些小型类更重要的相对时间。对于更大的类当然,集合类的性质将占主导地位,例如NSMutableDictionary应该是O (1)找一个元素等...)
#3
When you say "primarily for KVC/KVO reasons", can you elaborate?
当你说“主要是为了KVC / KVO的原因”时,你能详细说明吗?
If you're seeing performance problems due to excessive KVO firing under heavy mutation, consider firing the KVO notifications yourself once you're done:
如果您因重度突变导致过度KVO射击而出现性能问题,请考虑在完成后自行触发KVO通知:
[self willChangeValueForKey: @"myArray"];
// loop and mutate
[self didChangeValueForKey: @"myArray"];