Быстродействие массива и словаря Swift, removeAll () vs new instance



У меня есть массив (или словарь), и мне нужно его очистить. С точки зрения производительности, лучше ли removeAll() или создать новый экземпляр?



var things = [Thing]()

// Need to clear things
things.removeAll()
// or
things = [Thing]()
540   1  

1 ответ:

(я случайно неправильно понял ваш вопрос и посмотрел его для Dictionary, см. ниже для Array)

Словарь

thing = [String : Thing]() vs. thing.removeAll()

Теперь, когда Swift является открытым исходным кодом, мы можем посмотреть, действительно ли эти два утверждения делают что-то другое.

Новая инициализация

Покопавшись в источнике, я нашел инициализатор для a Dictionary здесь :

public init() {
  self = Dictionary<Key, Value>(minimumCapacity: 0)
}

/// Create a dictionary with at least the given number of
/// elements worth of storage.  The actual capacity will be the
/// smallest power of 2 that's >= `minimumCapacity`.
public init(minimumCapacity: Int) {
  _variantStorage =
    .Native(_NativeStorage.Owner(minimumCapacity: minimumCapacity))
}

Как вы можете видеть, основное хранилище, которое является единственным свойством, назначается при инициализации.

RemoveAll

Теперь давайте посмотрим на removeAll() из Здесь :
  internal mutating func removeAll(keepCapacity keepCapacity: Bool) {
    if count == 0 {
      return
    }

    if !keepCapacity {
      self = .Native(NativeStorage.Owner(minimumCapacity: 2))
      return
    }

    if _fastPath(guaranteedNative) {
      nativeRemoveAll()
      return
    }

    switch self {
    case .Native:
      nativeRemoveAll()
    case .Cocoa(let cocoaStorage):
#if _runtime(_ObjC)
      self = .Native(NativeStorage.Owner(minimumCapacity: cocoaStorage.count))
#else
      _sanityCheckFailure("internal error: unexpected cocoa ${Self}")
#endif
    }
  }
Здесь вы можете видеть, что условие !keepCapacity будет истинным, потому что removeAll() - это просто removeAll(keepCapacity:) с аргументом по умолчанию false. Этот код из перечисления хранилища, поэтому он заменяет себя новым пустым хранилищем с минимальной емкостью 2.

Заключение

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

Массив

things = [Thing]() vs things.removeAll()

Новая инициализация

Для массива еще проще увидеть здесь :

public init() {
  _buffer = _Buffer()
}

RemoveAll

Смотрите здесь :

public mutating func removeAll(keepCapacity keepCapacity: Bool = false) {
  if !keepCapacity {
    _buffer = _Buffer()
  }
  else {
    self.replaceRange(self.indices, with: EmptyCollection())
  }
}

Как и в случае со словарем, _buffer является единственным свойством Array.

Заключение

То же самое, что и для Dictionary: оба утверждения делают практически то же самое в теории, но я могу себе представить, что на практике инициализация может быть оптимизирована, так что они делают точно то же самое.

Comments

    Ничего не найдено.