Iphone 优化NSNumber numberWithInt:
我正在分析一个iPhone应用程序,我注意到一个奇怪的模式。在某个频繁调用的代码块中Iphone 优化NSNumber numberWithInt:,iphone,objective-c,performance,nsnumber,Iphone,Objective C,Performance,Nsnumber,我正在分析一个iPhone应用程序,我注意到一个奇怪的模式。在某个频繁调用的代码块中 [item setQuadrant:[NSNumber numberWithInt:a]]; [item setIndex:[NSNumber numberWithInt:b]]; [item setTimestamp:[NSNumber numberWithInt:c]]; [item setState:[NSNumber numberWithInt:d]]; [ite
[item setQuadrant:[NSNumber numberWithInt:a]];
[item setIndex:[NSNumber numberWithInt:b]];
[item setTimestamp:[NSNumber numberWithInt:c]];
[item setState:[NSNumber numberWithInt:d]];
[item setCompletionPercentage:[NSNumber numberWithInt:e]];
[item setId_:[NSNumber numberWithInt:f]];
…对[NSNumber numberWithInt:]的第一次调用花费的时间太长,大约是其余调用的10-15倍。我已经验证了如果我洗牌这些行,结果是一致的(第一行总是慢行,比例相同)。有什么事我不知道吗
可能这是因为这个块在try/catch中?如果我不得不猜测的话,NSNumber在它的
+load
实现中执行一些代码,这会减慢对类的初始调用。还要注意的是,NSNumber
缓存了它的返回值,因此将来使用相同的值调用+numberwhithint:
会比以前更快,这可能是问题的一部分。可能第一个值要大得多?除了CoreFoundation的CFNumber缓存之外,“新”运行时还使用标记指针,允许将24位范围内的整数直接编码到指针中,然后运行时通过查看最后一位来确定它是标记指针(通过查看最后一位之前的3位和目标数字大小(8、16、32、64位,使用之前的下4位),这是一个CFNumber)。
在32位系统(当前的iPhone)上,这意味着对于(“小”)负32位数字或大的正数,CoreFoundation将分配一个对象。对于其他所有内容,它使用以下更快的表达式:
case kCFNumberSInt32Type: {
int32_t value = *(int32_t *)valuePtr; // this loads the actual numerical value passed to CFNumberCreate()
#if !__LP64__
// We don't bother allowing the min 24-bit integer -2^23 to also be fast-pathed;
// tell anybody that complains about that to go ... hang.
int32_t limit = (1L << 23);
if (value <= -limit || limit <= value) break;
#endif
uintptr_t ptr_val = ((uintptr_t)((intptr_t)value << 8) | (2 << 6) | kCFTaggedObjectID_Integer);
return (CFNumberRef)ptr_val;
}
案例kCFNumberSInt32Type:{
int32_t value=*(int32_t*)valuePtr;//这将加载传递给CFNumberCreate()的实际数值
#如果__
//我们不需要费心让最小24位整数-2^23也可以快速路径;
//告诉任何抱怨这件事的人去…等等。
int32\u t限制=(1L)每次运行的第一次调用占用的时间更长,还是启动应用程序后的第一次调用?第一次调用一个类的方法将花费更长的时间,因为运行时必须搜索实现,但它会为将来缓存它。您可能还需要考虑只使用int而不是NStEnter。
保留代表低值整数的实例的某种缓存;设置该缓存很可能就是它正在做的事情,但我认为你的意思是+初始化
,而不是+加载
。这是在类收到第一条消息之前发送的。谢谢,根据其他文档,这似乎是正确的答案在线。虽然官方API中没有记录,但低值确实被缓存。一些人报告低整数值的重新计数高于预期值,这与此时间问题一致。我刚刚发布了另一个答案。考虑到NSNumber实际上是CFNumber的包装器,它受到CFNumber优化和limi的影响tations——它是在@Riviera的代码作为运行时设置的一部分运行之前很久设置的,或者在UIApplicationMain()
期间设置的,因此+load
极不可能是性能差异的原因,考虑到@Riviera说这个块被称为“频繁”,这意味着它总是比较慢,而不仅仅是第一次(instruments计算平均值)。在提问时,情况并非如此。iOS 6和Mac OSX Lion中添加了带标记的整数,因此在给定的情况下,这不是一个问题。我们不应该将此作为个人讨论。我只想将其添加到“旧”中问题-根据我的信息,在iOS5中,带标签的指针被添加到运行时中,同时支持弱引用。