我正在分析iPhone应用程序,我发现了一个奇怪的模式。在一段经常调用的代码块中......
[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中?
答案 0 :(得分:1)
如果我不得不猜测,NSNumber会在它的+load
实现中执行一些代码,这会减慢对该类的初始调用。另请注意,NSNumber
会缓存它的返回值,因此将来调用具有相同值的+numberWithInt:
比以前更快,这可能是问题的一部分。
答案 1 :(得分:-1)
也许第一个值要大得多?除了CoreFoundation的CFNumber缓存之外,“新”运行时使用标记指针,允许24位范围内的整数直接编码到指针中 - 然后运行时通过查看最后一位(并且它的位置)来确定它是标记指针CFNumber通过查看最后一位之前的3位和目标数字大小 - 8,16,32,64位 - 使用之前的下4位)。
在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;
}
(请注意,!__LP64__
适用于32位系统)
取自:http://www.opensource.apple.com/source/CF/CF-744.12/CFNumber.c
此外,还有一种缓存机制可以防止多次重新创建数字,只需在同一源文件中搜索“__CFNumberCache”。