NSArray 怎么会这么慢? [英] How can NSArray be this slow?

查看:20
本文介绍了NSArray 怎么会这么慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我来自 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.55942
vector - 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 肯定很慢.苹果怎么会这么蠢,对吧?我的意思是,真的......等等......我想知道是否有什么 NSMutableArrayvector 做得更好?

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.)

哦,你也可以试试这个,看看 NSMutableArrayCFMutableArray 到底有多快:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆