Оптимизация NSNumber numberWithInt: - PullRequest
0 голосов
/ 27 марта 2012

Я профилирую приложение для 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-15xостальные звонки.Я проверил, что результаты согласуются, если я перетасовываю строки (первая строка всегда медленная, в том же соотношении).Что-то происходит, о чем я не знаю?

Возможно, это происходит потому, что этот блок находится внутри try / catch?

Ответы [ 2 ]

1 голос
/ 27 марта 2012

Если бы мне пришлось угадывать, NSNumber выполняет некоторый код в своей реализации +load, что замедляет первоначальный вызов класса.Также обратите внимание, что NSNumber кэширует его возвращаемое значение, поэтому будущие вызовы +numberWithInt: с тем же значением выполняются быстрее, чем раньше, что может быть частью проблемы.

0 голосов
/ 25 марта 2013

Может быть, первое значение намного больше?Помимо кэширования CFNumber в CoreFoundation, «новая» среда выполнения использует теговые указатели, позволяя кодировать целые числа в диапазоне 24 бита непосредственно в указатель - среда выполнения затем выясняет, является ли он теговым указателем, глядя на последний бит (и что егоCFNumber, рассматривая 3 бита перед последним битом и размер целевого числа - 8, 16, 32, 64 бита - используя следующие 4 бита ранее).В 32-разрядной системе (текущие айфоны) это означает, что для («малых») отрицательных 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;
        }

(обратите внимание, что * 324 * верно для 32-разрядных систем)

Взято из: http://www.opensource.apple.com/source/CF/CF-744.12/CFNumber.c

Также существует механизм кэширования, который предотвращает повторное создание диапазона чисел, просто ищите «__CFNumberCache» в том же исходном файле.

...