Быстрая параллельная операция медленнее в 2 раза - PullRequest
6 голосов
/ 19 марта 2019

У меня большой массив JSON, который мне нужно сохранить в Realm, проблема в том, что эта операция длится около 45 секунд, а это слишком долго. Я попытался запустить операцию сохранения для каждого элемента в массиве JSON следующим образом:

for element in jsonArray { // jsonArray has about 25 elements
  DispatchQueue.global(qos: .userInitiated).async {
    let realm = try! Realm()
    let savedObject = realm.objects(MyObject.self).filter("name == '\(element.name)'")

    for subElement in element { // element is an array that has around 1000 elements
      let myModel = MyModel(initWith: subElement) // MyModel initialization is a simple light weight process that copies values from one model to another
      savedObject.models.append(myModel)
    }

  }
}

Когда я пытаюсь запустить тот же код, но с DispatchQueue.main.async, он заканчивается примерно в 2 раза быстрее, хотя и не одновременно. Я также попытался запустить приведенный выше код с качеством обслуживания .userInteractive, но с той же скоростью.

Когда я запускаю этот код, загрузка процессора составляет около 30%, а памяти - около 45 МБ. Можно ли ускорить эту операцию или я зашел в тупик?

1 Ответ

3 голосов
/ 19 марта 2019
  1. Весь цикл должен находиться внутри блока DispatchQueue.global(qos: .userInitiated).async.
  2. Как указано на сайте Realm :

    Операции записи в области являются синхронными и блокирующими, а не асинхронными. Если поток A начинает операцию записи, то поток B начинает операцию записи в той же области, прежде чем поток A завершится, поток A должен завершить и зафиксировать свою транзакцию до того, как произойдет операция записи потока B. Операции записи всегда обновляются автоматически в beginWrite (), поэтому при наложении записей условия гонки не создаются.

    Это означает, что вы не получите никакой выгоды, пытаясь писать в несколько потоков.

...