Mutable классы "тяжелее?" - PullRequest
       14

Mutable классы "тяжелее?"

4 голосов
/ 07 февраля 2012

При некотором интуитивном (возможно, неправильном) представлении о производительности я всегда получаю copy изменяемого экземпляра, прежде чем сохранить его. Поэтому, если свойство ожидает NSArray, я беру изменяемый массив, с которым я работаю, и сохраняю его как self.array = mutableArray.copy (хотя свойство указано как strong или retain).

Это кажется мне глупым, внезапно, но так ли это? Выполняются ли изменяемые экземпляры, выполняющие одну и ту же задачу, одинаково?

Примечание: Изменяемый экземпляр выпадает из области видимости и (благодаря ARC) освобождается сразу после этого, поэтому не стоит беспокоиться о том, что он будет видоизменен после его присвоения свойству.

Ответы [ 3 ]

3 голосов
/ 08 февраля 2012

NSArray и NSMutableArray оба (насколько я знаю) реализованы поверх CFArray , который просто имеет флаг, указывающий, является ли он изменяемым. CFArray функции, которые требуют изменяемого массива, имеют утверждение в самом начале, проверяя этот флаг:

void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) {
    // snip...
    CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);

Изменяемые и неизменяемые CFArray идентичны, кроме передачи или провала этого утверждения, и так должно быть NSArray с и NSMutableArray с, с точки зрения производительности или иным образом.

3 голосов
/ 07 февраля 2012

Частично ответили здесь: Размер и изменчивость NSArray

NSMutableArray не заметно медленнее или больше (по памяти), чем NSArray.По сути, это просто NSArray, который перераспределяет себя, когда заполняется, как массив большего размера, и продолжает делать это, когда вы добавляете в него элементы.

Причина копирования изменяемых массивов как неизменяемых при назначении их значениям в вашемкласс, так что вы можете гарантировать, что их значения не меняются.Если вы храните изменяемый массив в своем классе, другой код может изменить его значения вне вашего класса, не вызывая ни один из ваших методов.Это делает вас уязвимым к сбоям из-за внутренних ошибок непостоянства в ваших классах.

Например, предположим, что когда массив был установлен, вы кэшировали длину массива как свойство int в вашем классе.Это было бы хорошо, если бы массив был неизменным, но если бы он был изменяемым, кто-то другой мог бы изменить массив, и ваше кэшированное значение теперь будет неправильным, но у вас нет возможности узнать это.

Однако этоне нужно делать копирование вручную.Если вы объявите свойства массива следующим образом:

@property (nonatomic, copy) NSArray *foo;

Затем, когда вы назначите массив для object.foo, он будет автоматически скопирован.Вам не нужно копировать это снова самостоятельно.Рекомендуется использовать тип свойства copy вместо strong / retain для любого типа, который имеет изменяемый вариант, например:

@property (nonatomic, copy) NSArray *foo;
@property (nonatomic, copy) NSString *foo;
@property (nonatomic, copy) NSDictionary *foo;
@property (nonatomic, copy) NSData *foo;
etc...

Однако будьте осторожны, чтобы не использовать его для изменяемых свойств, иначесделайте неизменную копию, хранящуюся в свойстве, которое думает, что оно изменчиво, и вызывает сбой, если вы пытаетесь изменить его.Свойство синтезированной копии недостаточно интеллектуально, чтобы автоматически использовать mutableCopy.

@property (nonatomic, copy) NSMutableArray *foo; //don't do this
2 голосов
/ 07 февраля 2012

Для ясности вы спрашиваете, если NSArray и NSMutableArray, оба подвергнутые множеству не мутирующих методов тестирования, NSArray работает заметно быстрее?Я указываю немутацию, потому что похоже, что вы копируете изменяемый массив в неизменяемый массив, полагая, что неизменяемый массив будет выполнять свои неизменяемые методы быстрее, чем изменяемый массив.В любом случае, ответ - нет.(Но не верьте мне на слово; профиль).

Даже если NSMutableArray отвергает некоторые немутантные методы (о которых мы так или иначе не можем знать), вам не нужнобеспокоиться об этом.Добавление пары циклов ЦП тривиально по сравнению с общей вычислительной сложностью операции.Пока NSMutableArray не удается превратить операцию поиска O (n) в операцию O (n 2 ), все будет хорошо в 99% случаев.(Эти сложности являются просто вымышленными примерами.)

Хотя есть вполне веские причины, по которым вам может понадобиться скопировать изменяемый массив в неизменяемый массив (на что указывает @NickLockwood), производительность не должна быть одной изих.В конце концов, преждевременная оптимизация очень плохая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...