我已经为objective-c 类调整了默认设置器,以允许某种KVO,而无需实际向属性添加观察者。这工作正常。但在某些情况下,我需要围绕这个系统分配数十万个属性。
因此,出于性能原因,我有一个自定义属性描述符,它允许直接设置 ivar。为了调整性能,我保存了一些关于该属性的信息。
剩下的一个地方,我对更改相当小心,是使用 object_setIvar(),根据 Instruments,它在分配期间占 CPU 时间的 60%。罪魁祸首是 object_setIvar 正在调用 _class_getVariable,这比实际赋值 (objc_storeStrong()) 花费的时间长 3 倍。
长话短说:由于我可以将所有信息作为属性描述符的一部分提前缓存到类的属性中,我怎样才能更快地设置 ivar(避免 object_setIvar())?
这是我的属性描述符类的实际对象设置器函数(也有一个用于设置数值的等效函数):
- (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:
我在 Apple 资源中浪费时间的地方发现了这条评论:
"// FIXME: 这可以优化。"
所以我可能应该在这一点上放弃,希望将来会有所改善。实际上,我真的不明白在为属性设置值这样基本的东西中存在这样的瓶颈。另一方面,很高兴看到 Apple 的程序员也只是普通人 :)。