繁体   English   中英

NSMutableDictionary比Java Map慢得多......为什么?

[英]NSMutableDictionary much slower than Java Map… why?

以下代码将简单值持有者映射到一个对象,使用XCode 7 beta3,“最快,最具侵略性的优化[-Ofast]”,在Java中运行速度比Objective-C快15倍。 我可以在Java中获得超过280M查询/秒,但在objc示例中只能获得大约19M。 (我在这里发布了相应的Java代码,因为这开始是一个Swift比较: Swift Dictionary甚至在优化时缓慢:执行uncessary retain / release? )。

这是我的实际代码的简化版本,它肯定受哈希查找时间的约束,并且也展示了这种整体性能差异。 在下面的测试中,我正在测试null的值,只是为了确保编译器不会优化掉查找,但在真正的应用程序中,我会在大多数情况下使用该值。

当我查看乐器时,我发现在保留/释放,msgSend以及一些我不理解的锁定调用上花费了大量时间。

任何可以解释这个问题的想法比Java或任何变通方法慢10-15倍,我们将不胜感激。 我实际上可以像下面那样实现一个完美的哈希,所以我可以使用一个快速的int-object字典用于iOS,如果我找到一个。

@interface MyKey : NSObject <NSCopying>
    @property int xi;
@end

@implementation MyKey
    - (NSUInteger)hash { return self.xi; }
    - (BOOL)isEqual:(id)object    { return ((MyKey *)object).xi == self.xi; }
    - (id)copyWithZone:(NSZone *)zone { return self; }

@end

    NSMutableDictionary *map = [NSMutableDictionary dictionaryWithCapacity:2501];
    NSObject *obj = [[NSObject alloc] init];

    int range = 2500;
    for (int x=0; x<range; x++) {
        MyKey *key = [[MyKey alloc] init];
        key.xi=x;
        [map setObject:obj forKey:key];
    }

    MyKey *key = [[MyKey alloc] init];
    int runs = 50;
    for (int run=0; run<runs; run++)
    {
        NSDate *start = [NSDate date];

        int reps = 10000;
        for(int rep=0; rep<reps; rep++)
        {
            for (int x=0; x<range; x++) {
                key.xi=x;
                if ( [map objectForKey:key] == nil ) { NSLog(@"missing key"); }
            }
        }

        NSLog(@"rate = %f", reps*range/[[NSDate date] timeIntervalSinceDate:start]);
    }

您可以重新实现这样的-isEqual:方法以避免属性访问器:

- (BOOL) isEqual:(id)other
{
    return _xi == ((MyKey*)other)->_xi;
}

如果您的MyKey类可能是子类,那是不可接受的,但我从Java代码中看到那里的类是final

NSMutableDictionary的计算复杂性是下一个(来自CFDictionary.h文件):

The access time for a value in the dictionary is guaranteed to be at
worst O(N) for any implementation, current and future, but will
often be O(1) (constant time). Insertion or deletion operations
will typically be constant time as well, but are O(N*N) in the
worst case in some implementations. Access of values through a key
is faster than accessing values directly (if there are any such
operations). Dictionaries will tend to use significantly more memory
than a array with the same number of values.

意味着,几乎所有的时间都应该具有O(1)访问/插入/删除的复杂性。 对于Java HashMap你应该得到几乎相同的东西。

根据这项研究,使用dictionaryWithCapacity:便利初始化器没有任何好处。

如果您使用整数作为键,可能可以用数组替换字典。

在这个WWDC会话中,他们解释了objc_msgSend性能问题以及如何处理它们。 第一种解决方案是使用C ++和STL容器。 第二个是使用Swift,因为与Objective-C不同,它只是在注意到时才是动态的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM