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
,它非常慢并且我的内存喝空了,所以我我想我需要手动解除分配它们.但我不想测试副作用,所以我只是将 [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.
将10k个东西加入数组1k次的结果:NSArray
- 0.923411 秒vector
- 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
- 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
,但是 vector
与 保留
也是,它比以前更慢(!)(imax
= 1,jmax
= 10000000).NSArray
- 2.55942vector
- 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()
是 疯狂优化).但是如果跳过它,您可能会获得 5% 的折扣:
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).
Man,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);
在我的测试中我得到:
Vector insertions
7.83188 seconds
NSArray insertions
2.66572 seconds
Non-retaining
0.310126 seconds
这篇关于NSArray 怎么会这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!