NSArray怎么会这么慢? [英] How can NSArray be this slow?
问题描述
我来自C ++/STL世界,我想检查与stl相比,objective-c容器的情况如何.
I'm coming from a C++/STL world and I wanted to check how objective-c containers are in comparison to stl.
我想比较一个数字数组,但是将数字添加到NSArray
的唯一方法是使用NSNumber
,这非常慢并且将我的ram喝空了,所以我想我需要手动释放它们.但是我不想测试副作用,所以我只是将[NSNull null]
添加到了数组中.
I wanted to compare an array of numbers but the only way to add a number to an NSArray
is using NSNumber
which is utterly slow and drank my ram empty so I guess I need to dealloc them manually. But I don't want to test side effects so I just added [NSNull null]
into the array.
将1万次事物添加到数组1k次的结果:
NSArray
-0.923411秒
vector<int>
-0.129984秒
The results of adding 10k things into array 1k times:
NSArray
- 0.923411 seconds
vector<int>
- 0.129984 seconds
我认为这可能是分配和释放,所以我将数组的数量(代码中的imax
)设置为1,将添加的数量设置为10000000(jmax
),但是它的速度甚至更慢了
NSArray
-2.19859秒
vector<int>
-0.223471秒
I thought it might be allocations and deallocations so I set the number of arrays(imax
in the code) to 1 and number of additions to 10000000(jmax
) but it was even slower
NSArray
- 2.19859 seconds
vector<int>
- 0.223471 seconds
正如评论中提到的那样,数组大小的不断增加可能是问题所在,所以我使用arrayWithCapacity
来创建NSArray
,但是也使用reserve
来创建vector
,它甚至比以前更慢(!)(imax
= 1,jmax
= 10000000).
NSArray
-2.55942
vector<int>
-0.19139
结束编辑
As mentioned in the comments the constant increasing size of the array might be the problem so I made NSArray
using arrayWithCapacity
, but vector
with reserve
too and it was even slower than before(!) (imax
= 1, jmax
= 10000000).
NSArray
- 2.55942
vector<int>
- 0.19139
End edit
为什么这么慢?
我的参考代码:
#import <Foundation/Foundation.h>
#include <vector>
#include <iostream>
#include <time.h>
using namespace std;
int main (int argc, const char * argv[])
{
int imax = 1000;
int jmax = 10000;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
cout << "Vector insertions" << endl;
clock_t start = clock();
for(int i = 0; i < imax; i++)
{
vector<int> *v = new vector<int>();
for(int j = 0; j < jmax; j++)
{
v->push_back(j);
}
delete v;
}
double interval = (clock() - start) / (double)CLOCKS_PER_SEC;
cout << interval << " seconds" << endl;
cout << "NSArray insertions" << endl;
start = clock();
for(int i = 0; i < imax; i++)
{
NSMutableArray *v = [[NSMutableArray alloc] init];
for(int j = 0; j < jmax; j++)
{
[v addObject:[NSNull null]];
}
[v dealloc];
}
interval = (clock() - start) / (double)CLOCKS_PER_SEC;
cout << interval << " seconds" << endl;
[pool drain];
return 0;
}
推荐答案
@JeremyP提供了出色的链接和信息.总是读鱼.不过,这是一些吃时间的细分,以及您可能会采取的措施.
@JeremyP provides an excellent link and information. Always read the fish. Here's some breakdown of what's eating time, though, and what you might do about it.
首先,有许多对objc_msgSend()
的调用用于动态调度.可以避免这些情况,您可以节省一些时间(尽管不如您想的那么多.objc_msgSend()
是
First, there's the many calls to objc_msgSend()
for dynamic dispatch. These can be avoided and you'll save some of the time (though not as much as you'd think. objc_msgSend()
is crazy optimized). But you'll knock maybe 5% off by skipping it:
IMP addObject = class_getMethodImplementation([NSMutableArray class], @selector(addObject:));
NSNull *null = [NSNull null];
start = clock();
for(int i = 0; i < imax; i++)
{
NSMutableArray *v = [[NSMutableArray alloc] init];
for(int j = 0; j < jmax; j++)
{
addObject(v, @selector(addObject:), null);
}
[v release];
}
retain
/release
占用了很多时间.您可以通过使用非保留的CFMutableArray
来避免这种情况(并使用实数而不是NSNumber
).这将使附加时间达到vector
的2倍左右.
A lot of time is eaten up with retain
/release
. You can avoid that (and stick real numbers in rather than NSNumber
) by using a non-retaining CFMutableArray
). This will get the append times to about 2x of vector
.
CFArrayCallBacks cb = {0};
for(int i = 0; i < imax; i++)
{
CFMutableArrayRef v = CFArrayCreateMutable(NULL, 0, &cb);
for(int j = 0; j < jmax; j++)
{
CFArrayAppendValue(v, &j);
}
CFRelease(v);
}
此代码的最大成本是对memmove()
(或Mac上可收集的版本)的调用.
The biggest cost of this one is the calls to memmove()
(or the collectable version of it on the Mac).
男人,NSMutableArray
肯定很慢.苹果怎么会这么愚蠢,对吗?我的意思是,真的...等等...我想知道NSMutableArray
是否比vector
更好?
Man, NSMutableArray
sure is slow. How could Apple be so stupid, right? I mean, really... wait... I wonder if there's something NSMutableArray
does better than vector
?
尝试将这些行替换为明显的对应行:
Try swapping out these lines for their obvious counterparts:
v->insert(v->begin(), j);
NSNumber *num = [[NSNumber alloc] initWithInt:j];
[v insertObject:num atIndex:0];
[num release];
(是的,包括创建和发布NSNumber
,而不仅仅是使用NSNull
.)
(Yes, including creating and releasing the NSNumber
, not just using NSNull
.)
哦,您也可以尝试这一步,看看NSMutableArray
和CFMutableArray
到底有多快:
Oh, and you might try this one too to see just how fast NSMutableArray
and CFMutableArray
really can be:
CFArrayInsertValueAtIndex(v, 0, &j);
在我的测试中,我得到:
In my tests I get:
Vector insertions
7.83188 seconds
NSArray insertions
2.66572 seconds
Non-retaining
0.310126 seconds
这篇关于NSArray怎么会这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!