Ios NSMutableArray如何在快速枚举中实现如此高的速度

Ios NSMutableArray如何在快速枚举中实现如此高的速度,ios,objective-c,performance,linked-list,iteration,Ios,Objective C,Performance,Linked List,Iteration,y轴表示列表/阵列中每个节点的平均访问时间(以ns为单位)(访问所有元素的总时间除以元素数) x轴表示迭代数组中的元素数 其中红色是NSMutableArray的实现,蓝色是我的链表(CHTape) 在每个外部循环中,每个列表/数组都附加了一个空字符串@“。在内部循环中,检索每个列表/数组中的每个字符串,并对其进行计时和记录。之后,我们的时间以Wolfram语言输出,以产生一个情节 NSMutableArray如何获得如此惊人且一致的结果?如何才能实现类似的目标 我的NSFastEnumerat

y轴表示列表/阵列中每个节点的平均访问时间(以ns为单位)(访问所有元素的总时间除以元素数)

x轴表示迭代数组中的元素数

其中红色是
NSMutableArray
的实现,蓝色是我的链表(
CHTape

在每个外部循环中,每个列表/数组都附加了一个空字符串
@“
。在内部循环中,检索每个列表/数组中的每个字符串,并对其进行计时和记录。之后,我们的时间以Wolfram语言输出,以产生一个情节

NSMutableArray
如何获得如此惊人且一致的结果?如何才能实现类似的目标

我的NSFastEnumeration实现:

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])stackBuffer count:(NSUInteger)len
{
    if (state->state == 0)
    {
        state->state = 1;
        state->mutationsPtr = &state->extra[1];
        state->extra[0] = (unsigned long)head;
    }

    CHTapeNode *cursor = (__bridge CHTapeNode *)((void *)state->extra[0]);

    NSUInteger i = 0;

    while ( cursor != nil && i < len )
    {
        stackBuffer[i] = cursor->payload;
        cursor = cursor->next;
        i++;
    }
    state->extra[0] = (unsigned long)cursor;

    state->itemsPtr = stackBuffer;

    return i;
}
-(nsInteger)countByEnumeratingWithState:(NSFastEnumerationState*)状态对象:(id\uu不安全\u未恢复[])堆栈缓冲区计数:(nsInteger)len
{
如果(状态->状态==0)
{
状态->状态=1;
state->mutationsPtr=&state->extra[1];
状态->额外[0]=(无符号长)磁头;
}
CHTapeNode*光标=(u桥CHTapeNode*)((void*)状态->额外[0]);
整数i=0;
while(光标!=nil&&i有效负载;
光标=光标->下一步;
i++;
}
状态->额外[0]=(无符号长)光标;
state->itemsPtr=stackBuffer;
返回i;
}
完整的测试代码:

NSMutableArray *array = [NSMutableArray array];
CHTape *tape = [CHTape tape];

unsigned long long start;

unsigned long long tapeDur;
unsigned long long arrayDur;

NSMutableString * tapeResult = [NSMutableString stringWithString:@"{"];
NSMutableString * arrayResult = [NSMutableString stringWithString:@"{"];

NSString *string;

int iterations = 10000;

for (int i = 0; i <= iterations; i++)
{
    [tape appendObject:@""];
    [array addObject:@""];

    // CHTape
    start = mach_absolute_time();
    for (string in tape){}
    tapeDur = mach_absolute_time() - start;


    // NSArray
    start = mach_absolute_time();
    for (string in array){}
    arrayDur = mach_absolute_time() - start;


    // Results

    [tapeResult appendFormat:@"{%d, %lld}", i, (tapeDur/[tape count])];
    [arrayResult appendFormat:@"{%d, %lld}", i, (arrayDur/[array count])];

    if ( i != iterations)
    {
        [tapeResult appendString:@","];
        [arrayResult appendString:@","];
    }
}

[tapeResult appendString:@"}"];
[arrayResult appendString:@"}"];

NSString *plot = [NSString stringWithFormat:@"ListPlot[{%@, %@}]", tapeResult, arrayResult];
NSLog(@"%@", plot);
NSMutableArray*array=[NSMutableArray];
cTape*磁带=[cTape磁带];
无符号长启动;
无符号长带;
无符号长数组;
NSMutableString*tapeResult=[NSMutableString stringWithString:@“{”];
NSMutableString*arrayResult=[NSMutableString stringWithString:@“{”];
NSString*字符串;
int迭代次数=10000次;
对于(int i=0;i

通过在链接列表上强制关闭ARC,相关文件的效率显著提高。它将访问时间从~70ns减少到~14ns。虽然这仍然较慢,但平均而言,NSArray的速度仅为其平均速度的两倍,而不是十倍

虽然ARC可以使一些代码更快,但在迭代情况下会添加不必要的释放/保留调用


通过注释发现。

NSMutableArray-很可能它只是按照您使用的大小作为原始C数组实现的。它还针对迭代进行了高度优化,因为这是数组上最常用的操作之一。如果您希望深入研究所有的sourc,您可能还可以在中找到所有答案e、 另请参见:
countByEnumeratingWithState:…
实现无需复制元素。您的-countByEnumeratingWithState…方法是否已启用ARC?NSArray的实现已关闭ARC,以避免不必要的保留/释放调用。