Objective c NSArray怎么会这么慢?

Objective c NSArray怎么会这么慢?,objective-c,optimization,stl,Objective C,Optimization,Stl,我来自一个C++/STL世界,我想检查objective-C容器与STL的对比情况 我想比较一个数字数组,但向NSArray中添加数字的唯一方法是使用NSNumber,这非常慢,而且我的内存是空的,所以我想我需要手动解除锁定。但是我不想测试副作用,所以我只是在数组中添加了[NSNull null] 将10k事物添加到数组1k次的结果: NSArray-0.923411秒 矢量-0.129984秒 我认为这可能是分配和解除分配,所以我将数组数(imax在代码中)设置为1,将添加数设置为100000

我来自一个C++/STL世界,我想检查objective-C容器与STL的对比情况

我想比较一个数字数组,但向
NSArray
中添加数字的唯一方法是使用
NSNumber
,这非常慢,而且我的内存是空的,所以我想我需要手动解除锁定。但是我不想测试副作用,所以我只是在数组中添加了
[NSNull null]

将10k事物添加到数组1k次的结果:
NSArray
-0.923411秒
矢量
-0.129984秒

我认为这可能是分配和解除分配,所以我将数组数(
imax
在代码中)设置为1,将添加数设置为10000000(
jmax
),但速度更慢
NSArray
-2.19859秒
矢量
-0.223471秒

编辑:
正如在评论中提到的,数组大小的不断增加可能是问题所在,因此我使用容量为
的数组创建了
NSArray
,但是也使用了
保留空间的
向量
,它甚至比以前慢(!)(
imax
=1,
jmax
=10000000)。
NSArray
-2.55942
向量
-0.19139
结束编辑

为什么这么慢

我的参考代码:

#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;
}
#导入
#包括
#包括
#包括
使用名称空间std;
int main(int argc,const char*argv[]
{
intimax=1000;
int jmax=10000;
NSAutoreleasePool*池=[[NSAutoreleasePool alloc]init];

cout重复增加NSArray的容量至少消耗了一部分时间。使用以下各项将NSArray初始化到正确(或至少更好)的容量应该更快:

[NSMutableArray arrayWithCapacity:10000];

它是一个成熟的Objective-C对象,这意味着每次添加对象时都会有开销,这是由于Cocoa的消息查找算法,这是实现正确的动态绑定所必需的


还有一点是,NSArray不一定在内部结构为一组连续的指针。对于非常大的数组,NSArray的性能要好得多(即具有更好的大O时间复杂性)这是一个简短的回答:是的,NSArray确实比C++ C++的STL集合类要慢很多。这与编译时间与运行时行为、编译器的优化机会以及许多实现细节有关。

#include <stdio.h>
#include <time.h>

int main (int argc, char **argv)
{
    int imax = 1000;
    int jmax = 10000;

    clock_t start = clock();

    for(int i = 0; i < imax; i++)
    {
        int array[jmax];
        for(int j = 0; j < jmax; j++)
            j[array] = 0;
    }

    double interval = (clock() - start) / (double)CLOCKS_PER_SEC;

    printf("%f\n", interval);

    return 0;
}

(Rob指出,NSMutableArray是随机插入的优化对象,比C++的性能更好)

真正的答案是:

微基准测试对于优化面向用户的应用程序毫无用处。

使用微观基准来做出实施决策正是过早优化的定义

您将很难找到一个面向iOS或Mac OS X的Objective-C应用程序,其中CPU评测将显示花费在与NSArray相关的代码路径上的任何重要时间,但这些应用程序中的绝大多数几乎完全使用NS*集合类

当然,在某些情况下,NS*的性能是不可行的,为此,您可以使用C++/STL

所有这一切都不意味着你的问题是无效的。如果没有更多的上下文,很难说观察到的性能差异是否真的重要(然而,根据我的经验,几乎每次开发人员提出基于微观基准的问题时,都会被误导)


哦,还有阅读。

@JeremyP提供了一个很好的链接和信息。一定要阅读鱼。不过,这里有一些关于什么是进食时间的分解,以及你可以做些什么

首先,对于动态调度,有很多调用
objc\u msgSend()
。这些调用可以避免,并且您可以节省一些时间(虽然没有您想象的那么多。
objc\u msgSend()
是)。但是跳过它,您可能会降低5%:

  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];
  }
这项技术的最大成本是调用
memmove()
(或Mac上的可收集版本)

伙计,
NSMutableArray
确实很慢。苹果怎么会这么蠢,对吧?我是说,真的……等等……我想知道是否有什么东西
NSMutableArray
vector
更好

尝试将这些行替换为明显的对应行:

 v->insert(v->begin(), j);

  NSNumber *num = [[NSNumber alloc] initWithInt:j];
  [v insertObject:num atIndex:0];
  [num release];
(是,包括创建和发布
NSNumber
,而不仅仅是使用
NSNull

哦,你也可以试试这个,看看
NSMutableArray
CFMutableArray
的速度到底有多快:

  CFArrayInsertValueAtIndex(v, 0, &j);
在我的测试中,我得到:

Vector insertions
7.83188 seconds
NSArray insertions
2.66572 seconds
Non-retaining
0.310126 seconds

如果你想以更快的速度存储整数,为什么不使用C数组呢?存储任何东西,即使是空值也需要10倍的速度。你错了,数组的容量实际上比没有的慢,看看我的edit@Dani-同意。您可以通过预先分配NSArray和std::vector,然后比较每个Performance。正如@Dani所指出的,预分配可能比让它扩展慢。我也看到过同样的行为。我的怀疑是因为扩展的
NSArray
不是连续布置的,所以它可以重用大量已经分配的小块。但当你预分配时,它可能会试图在一个地方获得所有内存,这很可能是错误的对于缓存系统来说,块太大了。只是我最初的预感。但是,在任何情况下,预分配在基础上都不是一定的赢家,也可能是一个损失。<代码> int数组[jMAX] >由编译器优化(即使是-O0)。,您在这里检查的是10000000
mov
s,而不是我测试的结果。虽然我同意这些结论,但我的测试表明,如果您进行随机插入,NSMutableArray比vector要快得多。我不会认为NSMutableArray的速度普遍较慢。它只是在附加时没有那么快。也就是说,唯一真正的工作是ld
  CFArrayInsertValueAtIndex(v, 0, &j);
Vector insertions
7.83188 seconds
NSArray insertions
2.66572 seconds
Non-retaining
0.310126 seconds