提高设置Ivar的性能

时间:2013-11-01 10:53:52

标签: objective-c objective-c-runtime

我已经调整了objective-c类的默认setter,以允许某种KVO,而无需实际向属性添加观察者。这很好用。但在某些情况下,我需要在这个系统周围分配数十万个属性。

因此,出于性能原因,我有一个自定义属性描述符,允许直接设置ivar。为了调整性能,我保存了一些有关该属性的信息。

一个剩下的地方,我非常小心改变,是使用object_setIvar(),根据Instruments,在分配期间占据CPU时间的60%。 罪魁祸首是object_setIvar正在调用_class_getVariable,这比实际赋值(objc_storeStrong())长3倍。

长话短说:因为我可以提前将所有信息缓存到类'属性作为属性描述符的一部分,如何更快地设置ivar(避免使用object_setIvar())?

这是我的属性描述符类的实际对象setter函数(还有一个用于设置数值的等效函数):

- (id)setObjectValueNoKVOForOwner:(id)instance newObject:(id)newObject
{
    Class cls = object_getClass(instance);
    BOOL retainNewValue, copyNewValue, releaseOldValue;
    switch (self.setterSemantics)
    {
        case MemberDescriptionSetterSemanticsAssign:
            retainNewValue  = NO;
            copyNewValue    = NO;
            releaseOldValue = NO;
            break;

        case MemberDescriptionSetterSemanticsRetain:
            retainNewValue  = YES;
            copyNewValue    = NO;
            releaseOldValue = YES;
            break;

        case MemberDescriptionSetterSemanticsCopy:
            retainNewValue  = NO;
            copyNewValue    = YES;
            releaseOldValue = YES;
            break;
    }

    if (!_ivar)
    {
        _ivar = class_getInstanceVariable(cls, self.attributes.ivarName);
    }

    if (_ivar)
    {
        id oldObject = object_getIvar(instance, _ivar);
        if (newObject != oldObject)
        {
            if (retainNewValue)
            {
                newObject = [newObject retain];
            }
            else if (copyNewValue)
            {
                newObject = [newObject copy];
            }

            object_setIvar(instance, _ivar, newObject); // Improve this: avoid _class_getVariable

            if (releaseOldValue)
            {
                [oldObject release];
            }
        }
    }

    return [newObject autorelease];
}

更新:

我找到了与object_setIvar()相关的来源: https://github.com/opensource-apple/objc4/blob/master/runtime/objc-class.mm http://www.opensource.apple.com/source/objc4/objc4-532.2/runtime/objc-private.h http://www.opensource.apple.com/source/objc4/objc4-532.2/runtime/objc-runtime-new.mm

实现自己的object_setIvar()版本似乎并不“恶”,只是将已知类作为参数添加到它。不幸的是,它需要一个私有头文件。当我以iOS为目标时,我似乎应该放弃希望。

更新2:

我在苹果来源浪费时间的地方发现了这条评论:

“// FIXME:这可以优化。”

所以我应该放弃这一点,并希望将来能够改进。实际上我真的不明白,在为物业设置价值这一基本内容中存在这样的瓶颈。另一方面,很高兴看到Apple的程序员也只是人类:)。

1 个答案:

答案 0 :(得分:0)

  

该系统周围数十万个属性

虽然我不是这方面的专家,但我对处理器 - 内存总线内部工作的承诺表明,更改附近值(L1-3)要好得多缓存命中)而不是彼此相距很远的值(L1-3缓存未命中)。

因此,对于快速存储的值的简单连续 C数组,你会不会更好?