Приемлемо ли использовать прямой доступ к ивару извне класса для эффективности? - PullRequest
2 голосов
/ 20 февраля 2012

Я могу определить класс со свойством для доступа к моим иварам вне класса.

Я также могу просто использовать синтаксис myInst-> ivar для доступа в стиле C-struct.

В C ++ я бы использовал аксессоры, но в target-c есть некоторые случаи, когда мне может понадобиться прямой доступ. Система обмена сообщениями подвергается значительному снижению производительности с помощью средства доступа, что имеет значение в некоторых контекстах, поскольку сообщение не является встроенным, как это может быть с методами C ++.

Например, в классе, который имеет ивар, называемый скаляр, и определенное для него свойство. скаляр - это простое значение с плавающей точкой:

-(void) doWorkWithMyClass:(MyClass*)myinst
{
   // array and other locals declaration omitted 
   for (int i = 0; i < reallyBigX; i++) {
      result += [myinst scalar] * array[i];
      [myinst computeNextScalar:i];
   }
}

Если я поменяю [myinst scalar] на myinst-> scalar, метод будет работать намного быстрее, так как использование вызовов с аксессором займет большую часть процессора в этом цикле.

Как и в случае с C ++, я понимаю, что прямой доступ к ивару вообще не рекомендуется, но в этом контексте, когда скорость имеет значение, приемлемо ли это? Если нет, есть ли более предпочтительный метод, который все еще использует класс target-c?

Ответы [ 2 ]

6 голосов
/ 20 февраля 2012

Многие вещи становятся приемлемыми, когда они оказывают существенное влияние на производительность, но в приведенном вами примере, похоже, есть гораздо лучшие решения.

Во-первых, почему [myinst computeNextScalar:i] не возвращает новый скаляр? Если бы вы сделали это, вам не нужно было бы его извлекать, и все было бы намного быстрее.

Нельзя ли перенести работу в myinst? Я имею в виду, вы не можете создать что-то вроде:

result = [myinst totalOverArray:array];

Если reallyBigX действительно большой, то вам следует рассмотреть здесь Accelerate.framework. Это может значительно улучшить производительность при выполнении операций, которые вы выполняете. (Вы должны выполнить тестирование производительности с помощью инфраструктуры Accelerate. Это может быть существенно медленнее для некоторых операций, но это может быть быстрее.)

Наконец, рассмотрим шаблон Objective-C get.... Это выглядит так:

int *scalars = calloc(reallyBigX, sizeof(int));
[myinst getScalars:scalars range:NSMakeRange(0, reallyBigX)];
for (int i = 0; i < reallyBigX; i++) {
   result += scalars[i] * array[i];
}
free(scalars);

Кстати, вышесказанное определенно является кандидатом на vDSP_dotpr(), хотя вы должны проверить его на производительность. Во многих случаях простой цикл выполняется быстрее, чем эквивалентный вызов vDSP при шаге = 1 (поскольку вы можете использовать простое приращение вместо += stride).

1 голос
/ 20 февраля 2012

Да, это приемлемо: модификаторы доступа @public, @private и т. Д. Были введены частично для поддержки проектов, где требуется доступ к ivars вне класса.Тем не менее, вам следует избегать записи непосредственно в ivars.

...