I have to perform set of operations based on some conditions like fetching data from database which takes approximately 10 seconds per query (ConnectedDevices.getAllDetails() takes 10 to execute and return result).
this may be similar to below question optimized way to search a device ip address within a range in iphone but in my case i need to perform operations in batches as shown in below code :
var isConditionTrue = false
var numProcessed = 0
let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
// case 1
for i in 1...10 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
// case 2
for i in 11...20 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
// case 3
for i in 21...30 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !ieachDBValue {
numProcessed++
}
}
}
}
// case 4
for i in 31...40 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
So if in case 1, if result is false for 1 to 10 then it should go to case 2. If result is true for any instance.. it should not execute any case 2,3,4.
Similarly for case 2, if result is false for 1 to 10 then it should go to case 3 else it should stop. All this i need to do based on the conditions.
This is my solution
This is the fake class I created to test your scenario. As you can see the method getAllDetails
does simulate your database access.
It waits for 10 seconds and then returns true
only if the input parameter is 40
. This way we can test this code on the worst case scenario since all the call will need to be done.
class ConnectedDevices {
class func getAllDetails(i:Int) -> Bool {
sleep(10)
return i == 40
}
}
This is the class that will interact with Grand Central Dispatch
.
class Loader {
private var numProcessed = 0
private let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
private let utilityQueue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
func search(completion:(result:Int?)->()) {
dispatch_async(utilityQueue) {
for group in [1, 11, 21, 31] {
if let indexFound = self.search10(group) {
completion(result: indexFound)
return
}
}
completion(result: nil)
}
}
private func search10(startingIndex:Int) -> Int? {
var indexFound : Int?
dispatch_apply(10, utilityQueue) { (delta) -> () in
let found = ConnectedDevices.getAllDetails(startingIndex + delta)
dispatch_sync(self.dbQueue) {
self.numProcessed++ // this is increased anyway
if found {
indexFound = startingIndex + delta
}
}
}
return indexFound
}
}
This synchronous method receives an Int
as param and executes 10 concurrent calls to ConnectedDevices.getAllDetails
. Each call is performed adding startingIndex
to delta
(delta
goes from 0
to 9
).
The result is synchronously put into a synchronous queue where numProcessed
is safely increased. If found
is true
then the "winning" index (startingIndex + delta
) is returned.
If found
never becomes true
then nil
is returned.
This is an asych
method. It's a simple for loop
where the group
variables is populated with 1
, then 11
, then 21
and finally 31
.
Each time search10
is invoked. If it does return an Int
the value is passed to the completion
closure, otherwise the loop does continue.
If the 4 cycles are performed with no value returned from search10
then nil
is passed to the completion
closure.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
debugPrintln("Begin: \(NSDate())")
Loader().search { (result) -> () in
debugPrintln(result)
debugPrintln("End: \(NSDate())")
}
}
}
40 sequential calls to ConnectedDevices.getAllDetails(...)
would require 40 * 10 = 400 seconds
.
In my iPhone Simulator without any optimization enabled this code requires about 120 seconds
.
Hope this is what you need.
numProcessed
also if the current result is true
.isConditionTrue
so I removed it.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With