iOS и Objective-C: большая часть процессорного времени тратится на [выпуск NSObject] и [сохранение NSObject], но метод класса не выполняет никаких операций с памятью

Приложения для обработки изображений работают быстро на симуляторе, но очень медленно на реальном устройстве (iPhone 4GS).

При запуске приложения под «инструментами» я вижу следующее дерево вызовов:

введите здесь описание изображения

Обратите внимание, что вызовы внутри красного кружка, как сообщается, занимают почти все время ЦП метода.

Рассматриваемый метод является методом класса (а не методом экземпляра) со следующим кодом:

@implementation Line2F

+ (CGFloat)signTested:(Point2F *)tested p1:(Point2F *)p1 p2:(Point2F *)p2
{
    return [Line2F signTestedX:tested.x testedY:tested.y
                           p1x:p1.x p1y:p1.y
                           p2x:p2.x p2y:p2.y];
}

+ (CGFloat)signTestedX:(CGFloat)testedX testedY:(CGFloat)testedY
                   p1x:(CGFloat)p1x p1y:(CGFloat)p1y
                   p2x:(CGFloat)p2x p2y:(CGFloat)p2y
{
  return (testedX - p2x) * (p1y - p2y) - (p1x - p2x) * (testedY - p2y);  
}

@end

Кто-нибудь может объяснить, почему большая часть процессорного времени тратится на [NSObject release] и [NSObject retain]?


person Guy    schedule 18.03.2013    source источник


Ответы (2)


Если он не знает ничего лучшего, ARC сохранит все аргументы метода и освободит их при выходе из метода (см. это электронная почта списка рассылки на языке objc).

Вы должны быть в состоянии избежать этого, аннотируя аргументы +signTested:p1:p2: с помощью __weak или __unsafe_unretained в зависимости от ваших потребностей.

person Community    schedule 18.03.2013
comment
Проблема не в +signTestedX:testedY:p1x:p1y:p2x:p2y:, который принимает аргументы CGFloat; как вы заметили, поплавки не являются объектами, и их семантика не имеет смысла. Проблема заключается в том, что +signTested:p1:p2: вызывает +signTestedX:testedY:p1x:p1y:p2x:p2y: и принимает Point2F аргументов, которые (похоже) являются объектами, которые могут сохраняться/освобождаться. - person ; 18.03.2013
comment
передача директивы __weak по-прежнему требует некоторой обработки ARC, но она быстрее. Единственный способ, которым я нашел полное удаление, - это просто передать CGFloat вместо объектов. - person Guy; 18.03.2013

Ну может быть много чего. Как говорит FrozenDevil, это может быть связано с ARC, если вы его используете. Я предполагаю, что, скорее всего, метод вызывается в разное время внутри огромного цикла. Попробуйте передать слабые ссылки, но, конечно, вы должны быть уверены, что они существуют на протяжении всего процесса. Я бы также попытался оптимизировать цикл, встраивающий каждый цикл в пул автовыпуска.

person Andrea    schedule 18.03.2013