iOS GCD global queue priority both 0.5 - ios

I met the problem is why the following code print out priority is the same? Why is this? Thank you very much.
print("main:\(Thread.current)")
print("thread main priorities:\(Thread.current.threadPriority)")
DispatchQueue.global(qos: .utility).async {
print("utility:\(Thread.current)")
print("thread utility priorities:\(Thread.current.threadPriority)")
}
DispatchQueue.global(qos: .background).async {
print("background:\(Thread.current)")
print("thread background priorities:\(Thread.current.threadPriority)")
}
DispatchQueue.global(qos: .userInteractive).async {
print("userInteractive:\(Thread.current)")
print("thread userInteractive priorities:\(Thread.current.threadPriority)")
}
DispatchQueue.global(qos: .userInitiated).async {
print("userInitiated:\(Thread.current)")
print("thread userInitiated priorities:\(Thread.current.threadPriority)")
}
Log:
main:{number = 1, name = main}
thread main priorities:0.5
userInteractive:{number = 3, name = (null)}
utility:{number = 5, name = (null)}
background:{number = 6, name = (null)}
thread userInteractive priorities:0.5
userInitiated:{number = 4, name = (null)}
thread utility priorities:0.5
thread background priorities:0.5
thread userInitiated priorities:0.5

As you can see in the docs:
#available(iOS 4.0, *)
open var threadPriority: Double // To be deprecated; use qualityOfService below
threadPriority is deprecated. Also, Apple's GCD team has been very clear on the Thread - Queue topic. GCD will managed the threads for you. A queue priority is not a thread priority. Take a look at this example, which is the code you posted here, pretty much, I just added the "qos_class_self().rawValue", which is really how you should test the QoS, and not with the "threadPriority".
print("main:\(Thread.current), Thread main priorities:\(Thread.current.threadPriority), QoS: \(qos_class_self().rawValue)")
DispatchQueue.global(qos: .utility).async {
print("utility:\(Thread.current), Thread utility priorities:\(Thread.current.threadPriority), QoS: \(qos_class_self().rawValue)")
}
DispatchQueue.global(qos: .background).async {
print("background:\(Thread.current), Thread background priorities:\(Thread.current.threadPriority), QoS: \(qos_class_self().rawValue)")
}
DispatchQueue.global(qos: .userInteractive).async {
print("userInteractive:\(Thread.current), Thread userInteractive priorities:\(Thread.current.threadPriority), QoS: \(qos_class_self().rawValue)")
}
DispatchQueue.global(qos: .userInitiated).async {
print("userInitiated:\(Thread.current), Thread userInitiated priorities:\(Thread.current.threadPriority), QoS: \(qos_class_self().rawValue)")
}
I also combined the prints per closure so they don't get scrambled in different lines in the log. This shows you that QoS is maintained, whereas threadPriority is deprecated.
main:<NSThread: 0x6100000762c0>{number = 1, name = main}, Thread main priorities:0.5, QoS: 33
userInteractive:<NSThread: 0x610000261fc0>{number = 4, name = (null)}, Thread userInteractive priorities:0.5, QoS: 33
utility:<NSThread: 0x618000079100>{number = 3, name = (null)}, Thread utility priorities:0.5, QoS: 17
userInitiated:<NSThread: 0x608000078380>{number = 5, name = (null)}, Thread userInitiated priorities:0.5, QoS: 25
background:<NSThread: 0x610000262000>{number = 6, name = (null)}, Thread background priorities:0.5, QoS: 9
So, in the end, the take away is not to think in terms of threads, but to think in terms of Queues, their QoS and knowing that GCD will manage threads for you. Very different concept to what we were used to before Queues came around with GCD.

Related

Which thread will be blocked by sleep: in swift

Which thread is blocked by Swift's sleep: method?
let customConcurrentQueue = DispatchQueue(label: "CustomConcurrentQueue", attributes: .concurrent)
customConcurrentQueue.async {
sleep(5)
print("1")
}
print("2")
Will sleep method block the Main thread also?
No, the main thread will not be blocked.
It is because you are calling an async block on the customConcurrentQueue, which allows the main thread to continue running immediately. If you used sync instead, the main thread would wait until the sync block is finished running.

Swift 3 Cannot convert value of type '()' to expected argument type '__OS_dispatch_queue_attr?' [duplicate]

In Swift 2, I was able to create queue with the following code:
let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)
But this doesn't compile in Swift 3.
What is the preferred way to write this in Swift 3?
Creating a concurrent queue
let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
concurrentQueue.sync {
}
Create a serial queue
let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync {
}
Get main queue asynchronously
DispatchQueue.main.async {
}
Get main queue synchronously
DispatchQueue.main.sync {
}
To get one of the background thread
DispatchQueue.global(qos: .background).async {
}
Xcode 8.2 beta 2:
To get one of the background thread
DispatchQueue.global(qos: .default).async {
}
DispatchQueue.global().async {
// qos' default value is ´DispatchQoS.QoSClass.default`
}
If you want to learn about using these queues .See this answer
Compiles under >=Swift 3. This example contains most of the syntax that we need.
QoS - new quality of service syntax
weak self - to disrupt retain cycles
if self is not available, do nothing
async global utility queue - for network query, does not wait for the result, it is a concurrent queue, the block (usually) does not wait when started. Exception for a concurrent queue could be, when its task limit has been previously reached, then the queue temporarily turns into a serial queue and waits until some previous task in that queue completes.
async main queue - for touching the UI, the block does not wait for the result, but waits for its slot at the start. The main queue is a serial queue.
Of course, you need to add some error checking to this...
DispatchQueue.global(qos: .utility).async { [weak self] () -> Void in
guard let strongSelf = self else { return }
strongSelf.flickrPhoto.loadLargeImage { loadedFlickrPhoto, error in
if error != nil {
print("error:\(error)")
} else {
DispatchQueue.main.async { () -> Void in
activityIndicator.removeFromSuperview()
strongSelf.imageView.image = strongSelf.flickrPhoto.largeImage
}
}
}
}
Compiled in XCode 8, Swift 3
https://github.com/rpthomas/Jedisware
#IBAction func tap(_ sender: AnyObject) {
let thisEmail = "emailaddress.com"
let thisPassword = "myPassword"
DispatchQueue.global(qos: .background).async {
// Validate user input
let result = self.validate(thisEmail, password: thisPassword)
// Go back to the main thread to update the UI
DispatchQueue.main.async {
if !result
{
self.displayFailureAlert()
}
}
}
}
Since the OP question has already been answered above I just want to add some speed considerations:
It makes a lot of difference what priority class you assign to your async function in DispatchQueue.global.
I don't recommend running tasks with the .background thread priority especially on the iPhone X where the task seems to be allocated on the low power cores.
Here is some real data from a computationally intensive function that reads from an XML file (with buffering) and performs data interpolation:
Device name / .background / .utility / .default / .userInitiated / .userInteractive
iPhone X: 18.7s / 6.3s / 1.8s / 1.8s / 1.8s
iPhone 7: 4.6s / 3.1s / 3.0s / 2.8s / 2.6s
iPhone 5s: 7.3s / 6.1s / 4.0s / 4.0s / 3.8s
Note that the data set is not the same for all devices. It's the biggest on the iPhone X and the smallest on the iPhone 5s.
Update for swift 5
Serial Queue
let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
// code to execute
}
Concurrent Queue
let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
concurrentQueue.async {
// code to execute
}
From Apple documentation:
Parameters
label
A string label to attach to the queue to uniquely identify it in debugging tools such as Instruments, sample, stackshots, and crash reports. Because applications, libraries, and frameworks can all create their own dispatch queues, a reverse-DNS naming style (com.example.myqueue) is recommended. This parameter is optional and can be NULL.
qos
The quality-of-service level to associate with the queue. This value determines the priority at which the system schedules tasks for execution. For a list of possible values, see DispatchQoS.QoSClass.
attributes
The attributes to associate with the queue. Include the concurrent attribute to create a dispatch queue that executes tasks concurrently. If you omit that attribute, the dispatch queue executes tasks serially.
autoreleaseFrequency
The frequency with which to autorelease objects created by the blocks that the queue schedules. For a list of possible values, see DispatchQueue.AutoreleaseFrequency.
target
The target queue on which to execute blocks. Specify DISPATCH_TARGET_QUEUE_DEFAULT if you want the system to provide a queue that is appropriate for the current object.
I did this and this is especially important if you want to refresh your UI to show new data without user noticing like in UITableView or UIPickerView.
DispatchQueue.main.async
{
/*Write your thread code here*/
}
DispatchQueue.main.async {
self.collectionView?.reloadData() // Depends if you were populating a collection view or table view
}
OperationQueue.main.addOperation {
self.lblGenre.text = self.movGenre
}
//use Operation Queue if you need to populate the objects(labels, imageview, textview) on your viewcontroller
let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT) //Swift 2 version
let concurrentQueue = DispatchQueue(label:"com.swift3.imageQueue", attributes: .concurrent) //Swift 3 version
I re-worked your code in Xcode 8, Swift 3 and the changes are marked in contrast to your Swift 2 version.
Swift 3
you want call some closure in swift code then you want to change in storyboard ya any type off change belong to view your application will crash
but you want to use dispatch method your application will not crash
async method
DispatchQueue.main.async
{
//Write code here
}
sync method
DispatchQueue.main.sync
{
//Write code here
}
DispatchQueue.main.async(execute: {
// write code
})
Serial Queue :
let serial = DispatchQueue(label: "Queuename")
serial.sync {
//Code Here
}
Concurrent queue :
let concurrent = DispatchQueue(label: "Queuename", attributes: .concurrent)
concurrent.sync {
//Code Here
}
For Swift 3
DispatchQueue.main.async {
// Write your code here
}
let newQueue = DispatchQueue(label: "newname")
newQueue.sync {
// your code
}
it is now simply:
let serialQueue = DispatchQueue(label: "my serial queue")
the default is serial, to get concurrent, you use the optional attributes argument .concurrent
DispatchQueue.main.async(execute: {
// code
})
You can create dispatch queue using this code in swift 3.0
DispatchQueue.main.async
{
/*Write your code here*/
}
/* or */
let delayTime = DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: delayTime)
{
/*Write your code here*/
}

Show thread label in Debug navigator or other tools

In my project a have a lot of background threads. I want to check if every thread works without crashes and disappear when needed. Because my program use 26% CPU. So i labeled every background thread:
let myQueue = DispatchQueue(label: "myQ", qos: .background, target: nil)
myQueue.async {
someFunc()
}
But in Xcode Debug navigator i see unnamed threads:
EDIT
Hm, i found a way:
DispatchQueue.global(qos: .background).async {
Thread.current.name = "my thread"
somefunc()
}
But why then we need label in DispatchQueue ?
Hm, i found a way:
DispatchQueue.global(qos: .background).async {
Thread.current.name = "my thread"
somefunc()
}
But why then we need label in DispatchQueue ?

How to create dispatch queue in Swift 3

In Swift 2, I was able to create queue with the following code:
let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)
But this doesn't compile in Swift 3.
What is the preferred way to write this in Swift 3?
Creating a concurrent queue
let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
concurrentQueue.sync {
}
Create a serial queue
let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync {
}
Get main queue asynchronously
DispatchQueue.main.async {
}
Get main queue synchronously
DispatchQueue.main.sync {
}
To get one of the background thread
DispatchQueue.global(qos: .background).async {
}
Xcode 8.2 beta 2:
To get one of the background thread
DispatchQueue.global(qos: .default).async {
}
DispatchQueue.global().async {
// qos' default value is ´DispatchQoS.QoSClass.default`
}
If you want to learn about using these queues .See this answer
Compiles under >=Swift 3. This example contains most of the syntax that we need.
QoS - new quality of service syntax
weak self - to disrupt retain cycles
if self is not available, do nothing
async global utility queue - for network query, does not wait for the result, it is a concurrent queue, the block (usually) does not wait when started. Exception for a concurrent queue could be, when its task limit has been previously reached, then the queue temporarily turns into a serial queue and waits until some previous task in that queue completes.
async main queue - for touching the UI, the block does not wait for the result, but waits for its slot at the start. The main queue is a serial queue.
Of course, you need to add some error checking to this...
DispatchQueue.global(qos: .utility).async { [weak self] () -> Void in
guard let strongSelf = self else { return }
strongSelf.flickrPhoto.loadLargeImage { loadedFlickrPhoto, error in
if error != nil {
print("error:\(error)")
} else {
DispatchQueue.main.async { () -> Void in
activityIndicator.removeFromSuperview()
strongSelf.imageView.image = strongSelf.flickrPhoto.largeImage
}
}
}
}
Compiled in XCode 8, Swift 3
https://github.com/rpthomas/Jedisware
#IBAction func tap(_ sender: AnyObject) {
let thisEmail = "emailaddress.com"
let thisPassword = "myPassword"
DispatchQueue.global(qos: .background).async {
// Validate user input
let result = self.validate(thisEmail, password: thisPassword)
// Go back to the main thread to update the UI
DispatchQueue.main.async {
if !result
{
self.displayFailureAlert()
}
}
}
}
Since the OP question has already been answered above I just want to add some speed considerations:
It makes a lot of difference what priority class you assign to your async function in DispatchQueue.global.
I don't recommend running tasks with the .background thread priority especially on the iPhone X where the task seems to be allocated on the low power cores.
Here is some real data from a computationally intensive function that reads from an XML file (with buffering) and performs data interpolation:
Device name / .background / .utility / .default / .userInitiated / .userInteractive
iPhone X: 18.7s / 6.3s / 1.8s / 1.8s / 1.8s
iPhone 7: 4.6s / 3.1s / 3.0s / 2.8s / 2.6s
iPhone 5s: 7.3s / 6.1s / 4.0s / 4.0s / 3.8s
Note that the data set is not the same for all devices. It's the biggest on the iPhone X and the smallest on the iPhone 5s.
Update for swift 5
Serial Queue
let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
// code to execute
}
Concurrent Queue
let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
concurrentQueue.async {
// code to execute
}
From Apple documentation:
Parameters
label
A string label to attach to the queue to uniquely identify it in debugging tools such as Instruments, sample, stackshots, and crash reports. Because applications, libraries, and frameworks can all create their own dispatch queues, a reverse-DNS naming style (com.example.myqueue) is recommended. This parameter is optional and can be NULL.
qos
The quality-of-service level to associate with the queue. This value determines the priority at which the system schedules tasks for execution. For a list of possible values, see DispatchQoS.QoSClass.
attributes
The attributes to associate with the queue. Include the concurrent attribute to create a dispatch queue that executes tasks concurrently. If you omit that attribute, the dispatch queue executes tasks serially.
autoreleaseFrequency
The frequency with which to autorelease objects created by the blocks that the queue schedules. For a list of possible values, see DispatchQueue.AutoreleaseFrequency.
target
The target queue on which to execute blocks. Specify DISPATCH_TARGET_QUEUE_DEFAULT if you want the system to provide a queue that is appropriate for the current object.
I did this and this is especially important if you want to refresh your UI to show new data without user noticing like in UITableView or UIPickerView.
DispatchQueue.main.async
{
/*Write your thread code here*/
}
DispatchQueue.main.async {
self.collectionView?.reloadData() // Depends if you were populating a collection view or table view
}
OperationQueue.main.addOperation {
self.lblGenre.text = self.movGenre
}
//use Operation Queue if you need to populate the objects(labels, imageview, textview) on your viewcontroller
let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT) //Swift 2 version
let concurrentQueue = DispatchQueue(label:"com.swift3.imageQueue", attributes: .concurrent) //Swift 3 version
I re-worked your code in Xcode 8, Swift 3 and the changes are marked in contrast to your Swift 2 version.
Swift 3
you want call some closure in swift code then you want to change in storyboard ya any type off change belong to view your application will crash
but you want to use dispatch method your application will not crash
async method
DispatchQueue.main.async
{
//Write code here
}
sync method
DispatchQueue.main.sync
{
//Write code here
}
DispatchQueue.main.async(execute: {
// write code
})
Serial Queue :
let serial = DispatchQueue(label: "Queuename")
serial.sync {
//Code Here
}
Concurrent queue :
let concurrent = DispatchQueue(label: "Queuename", attributes: .concurrent)
concurrent.sync {
//Code Here
}
For Swift 3
DispatchQueue.main.async {
// Write your code here
}
let newQueue = DispatchQueue(label: "newname")
newQueue.sync {
// your code
}
it is now simply:
let serialQueue = DispatchQueue(label: "my serial queue")
the default is serial, to get concurrent, you use the optional attributes argument .concurrent
DispatchQueue.main.async(execute: {
// code
})
You can create dispatch queue using this code in swift 3.0
DispatchQueue.main.async
{
/*Write your code here*/
}
/* or */
let delayTime = DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: delayTime)
{
/*Write your code here*/
}

Serializable dispatch queue create

I need to create a serializable Dispatch queue.
I'm using AudioUnit to register from the microphone, and then encoding the frame on the created queue.
I have one object encoding, so I need always the same thread accessing it.
However, when I create my queue :
queue = dispatch_queue_create("com.myapp.queue", DISPATCH_QUEUE_SERIAL);
If I dispatch to this queue with :
NSLog(#"recording callback Thread Info: %#", [NSThread currentThread]);
dispatch_async(queue, ^{
[self processAudio];
});
- (void) processAudio
{
NSLog(#"processAudio Thread Info: %#", [NSThread currentThread]);
...
}
It is mostly using the same thread until one point where I get this :
recording callback Thread Info: <NSThread: 0x7fb0ab331b90>{number = 12, name = (null)}
processAudio Thread Info: <NSThread: 0x7fb0ab210140>{number = 7, name = (null)}
recording callback Thread Info: <NSThread: 0x7fb0ab331b90>{number = 12, name = (null)}
processAudio Thread Info: <NSThread: 0x7fb0a8e33950>{number = 8, name = (null)}
recording callback Thread Info: <NSThread: 0x7fb0ab331b90>{number = 12, name = (null)}
processAudio Thread Info: <NSThread: 0x7fb0ab212bf0>{number = 13, name = (null)}
The dispatch_async will switch thread, and then stick a while with thread number 13, until it will switch again.
Is that a normal behavior although I specified that I wanted a SERIAL queue ?
Should I be worried about switching thread, when using only one instance of an object, or is it really serialized ?
This is expected behavior and you should not worry about it. From Apple's docs (https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html):
Serial queues (also known as private dispatch queues) execute one task at a time in the order in which they are added to the queue. The currently executing task runs on a distinct thread (which can vary from task to task) that is managed by the dispatch queue.

Resources