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

查看:79
本文介绍了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,这非常慢并且将我的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.)

哦,您也可以尝试这一步,看看NSMutableArrayCFMutableArray到底有多快:

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

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