Swift Grand Central Dispatch

Grand Central Dispatch provides queues to manage submitted tasks. The queues manage these submitted tasks and execute them in a FIFO order. This ensures that the tasks are started in the order they were submitted but that doesn't mean they will end in the same sequence. It all depends on the type of queue.

GCD provides 3 types of queues:
  • Serial queues: Tasks in a serial queue are executed one at a time in the order they were submitted. Each task is started only after the preceding task is completed. 
  • Concurrent queues: Tasks in a concurrent queue execute concurrently; however, the tasks are still started in the order that they were added to the queue. The exact number of tasks that can be executed at any given instance is variable and is dependent on the system resources. 
  • Main dispatch queue: The main dispatch queue is a globally available serial queue that executes tasks on the application's main thread. It is usually called when some background processing has finished and the UI needs to be updated.

import UIKit

func requestWebPage(url: String) {
    
    let url = URL(string: url)!
    let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
        guard data != nil else { return }
    }
    task.resume()
}

func performTask(id: String, url: String, count: Int) {
    
    let start = CFAbsoluteTimeGetCurrent()
    print("Start time for \(id): \(start) \n")
    
    for _ in 0 ..< count {
        requestWebPage(url: url)
    }
    
    let end = CFAbsoluteTimeGetCurrent()
    print("End time for \(id): \(end)")
    print("Total time spent for \(id): \(end-start) \n")
}

//will execute on the main queue
DispatchQueue.main.async {
    performTask(id: "M1", url: "https://www.google.com", count: 50)
}

//concurrent processing
let parallelQueue = DispatchQueue(label: "p.com.mysamplecode", attributes: .concurrent)
parallelQueue.async {
    performTask(id: "P1", url: "https://www.google.com", count: 20)
}
parallelQueue.async {
    performTask(id: "P2", url: "https://www.google.com", count: 2)
}
parallelQueue.async {
    performTask(id: "P3", url: "https://www.google.com", count: 10)
}

//will execute on the main queue
DispatchQueue.main.async {
    performTask(id: "M2", url: "https://www.google.com", count: 50)
}

//process one after another
let serialQueue = DispatchQueue(label: "s.com.mysamplecode")
serialQueue.async {
    performTask(id: "S1", url: "https://www.google.com", count: 20)
}
serialQueue.async {
    performTask(id: "S2", url: "https://www.google.com", count: 2)
}
serialQueue.async {
    performTask(id: "S3", url: "https://www.google.com", count: 10)
}

Here are the Results

  • As you can see from the results none of the M1 or M2 jobs started earlier because the main queue was occupied even thought we kicked them off earlier. 
  • Now in case of parallel jobs P1,P2 and P3 they all started in sequence but ended based on how much time it took them to process, basically running concurrently until they were finished. 
  • With regards to S1, S2 and S3 jobs each one started only after the previous one finished. 

Now you can decide based on the application need which queue to use.

Start time for P1: 577300830.560195 

Start time for P2: 577300830.560626 

Start time for P3: 577300830.560646 

Start time for S1: 577300830.560727 

End time for P2: 577300830.611294
Total time spent for P2: 0.05066800117492676 

End time for P3: 577300830.612932
Total time spent for P3: 0.05228590965270996 

End time for P1: 577300830.669353
Total time spent for P1: 0.10915803909301758 

End time for S1: 577300830.67013
Total time spent for S1: 0.10940301418304443 

Start time for S2: 577300830.670222 

End time for S2: 577300830.700119
Total time spent for S2: 0.029896974563598633 

Start time for S3: 577300830.700301 

End time for S3: 577300830.706292
Total time spent for S3: 0.0059909820556640625 

Start time for M1: 577300830.746559 

End time for M1: 577300830.802805
Total time spent for M1: 0.05624592304229736 

Start time for M2: 577300830.803108 

End time for M2: 577300830.8545
Total time spent for M2: 0.0513920783996582 

No comments:

Post a Comment

NO JUNK, Please try to keep this clean and related to the topic at hand.
Comments are for users to ask questions, collaborate or improve on existing.