MutableCopy NSArray - проблемы производительности - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть следующая проблема.У меня есть фрагмент кода, в котором я очень беспокоюсь о производительности (если честно, я стараюсь сделать ее максимально оптимизированной).

У меня есть что-то вроде этого:

NSArray *array = [someInstance getArray];
if (something) {
   NSMutableArray *marray = [array mutableCopy];
   [marray removeObject:someObject];
   [marray insertObject:someObject atIndex:0];

   array = marray;
}

Цель - переместить someObject в начало массива - довольно просто.Однако дело в другом.Метод [someInstance getArray] возвращает NSArray *, но внутренне он также использует NSMutableArray:

- (NSArray *)getArray {
    NSMutableArray *array = [NSMutableArray new];
    // do some stuff here
    return array;
}

Я пытаюсь сохранить все мои интерфейсы, возвращающие неизменяемые коллекции.Но в приведенном выше случае я подумываю создать исключение из этого правила, поскольку меня очень заботит производительность в этом фрагменте кода.Поэтому я могу изменить метод getArray на следующий:

- (NSMutableArray *)getArray {
    NSMutableArray *array = [NSMutableArray new];
    // do some stuff here
    return array;
}

, а затем изменить свой ультраэффективный код следующим образом:

NSMutableArray *array = [someInstance getArray];
if (something) {
   [array removeObject:someObject];
   [array insertObject:someObject atIndex:0];
}

Имеет ли смысл указанное выше изменение всроки исполнения?

1 Ответ

0 голосов
/ 08 февраля 2019

NSArray поддерживает копирование при записи.Из Foundation Release Notes для macOS 10.13 и iOS 11 :

Коллекция Copy-on-Write

NSArray, NSDictionary и NSSet теперь реализуют «копировать нанаписать »(CoW), что означает, что копия изменяемого экземпляра часто будет не полной копией, а намного более дешевой операцией O (1).Полная копия выполняется только в том случае, если один из объектов (оригинал или копия) был видоизменен по линии.

См. Сессия WWDC 2017 244 «Эффективное взаимодействие с фреймворками» дляПодробнее об этом.

Это означает, что копирование массива дешево.Однако его изменение, пока оригинал все еще присутствует, потенциально дорого.

Таким образом, вы можете сделать следующее:

if (something) {
   NSMutableArray *marray = [array mutableCopy];
   array = nil;
   [marray removeObject:someObject];
   [marray insertObject:someObject atIndex:0];
   array = [marray copy];
}

В результате копирования два объекта совместно используют резервное хранилище.Убрав array перед мутацией marray, оригинал должен быть освобожден, оставив только один.Затем мутациям не нужно копировать его, потому что он больше не является общим.

Кроме того, как рекомендуется в этом видео WWDC, когда у вас есть метод, который создает массив, который может изменяться во время его настройки, ночто вы хотите вернуть как неизменяемый, вы можете и должны вернуть копию вместо простого указателя:

- (NSArray *)getArray {
    NSMutableArray *array = [NSMutableArray new];
    // do some stuff here
    return [array copy];
}

Это безопаснее и все еще дешево.

...