我已经调整了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的程序员也只是人类:)。
答案 0 :(得分:0)
该系统周围数十万个属性
虽然我不是这方面的专家,但我对处理器 - 内存总线内部工作的承诺表明,更改附近值(L1-3)要好得多缓存命中)而不是彼此相距很远的值(L1-3缓存未命中)。
因此,对于快速存储的值的简单连续 C数组,你会不会更好?