Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift concurrent operation slower 2x times

I have a large JSON array that I need to save to Realm, the problem is that this operation lasts around 45 seconds and that's too long. I tried running the save operation concurrently for each element in JSON array like this:

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)
    }

  }
}

When I try to run the same code but with DispatchQueue.main.async it finished around 2x faster even though it's not concurrent. I also tried running the code above with quality of service .userInteractive but it is the same speed.

When I run this code CPU utilization is about 30%, and memory about 45 MB. Is it possible to speed up this operation or I reached dead end?

like image 274
Omega Avatar asked Mar 19 '19 12:03

Omega


1 Answers

  1. The entire loop should be inside the DispatchQueue.global(qos: .userInitiated).async block.
  2. As documented on the Realm website:

    Realm write operations are synchronous and blocking, not asynchronous. If thread A starts a write operation, then thread B starts a write operation on the same Realm before thread A is finished, thread A must finish and commit its transaction before thread B’s write operation takes place. Write operations always refresh automatically on beginWrite(), so no race condition is created by overlapping writes.

    This means you won't get any benefit by trying to write in multiple threads.

like image 109
rmaddy Avatar answered Sep 20 '22 13:09

rmaddy