2

I tried to increase the priority of the block executed in the concurrent queue. I suggested that the flag enforceQoS is suitable for this purpose. As Apple docs said:

This flag prioritizes the block's quality-of-service class over the one associated with the current execution context, as long as doing so does not lower the quality of service.

Suppose there is a queue:

/// Lowest priority queue
let concurrentQueue = DispatchQueue(label: "queue.conc.test", qos: .background, attributes: .concurrent)

We also have several DispatchWorkItem tasks, some of which are:

let item1 = DispatchWorkItem(qos: .userInitiated) { /* execute block */ }
let item2 = DispatchWorkItem(qos: .utility, flags: .enforceQoS) { /* execute block */ }

My question is simple: does Apple guarantee that item2 execute early?

I played in the playground a little bit and unfortunately didn't reveal any advantages of this flag, the results were absolutely chaotic. The official documentation also didn't help in this matter.

Thanks a lot.

V.V.V
  • 235
  • 1
  • 13

1 Answers1

2

"Prioritize" here doesn't mean "run sooner." It means "when deciding which QoS to assign for this block, prefer the one given here you rather than the one that the current execution context suggests (if the one given here is higher than what this block would otherwise receive)."

If you require that item2 run before item1, then use notify to order them:

item2.notify(queue: concurrentQueue, execute: item1)

In no case should you try to use QoS to order work items. QoS is a complex system that includes more than just priority; it also includes things like whether the device is in an energy-saving mode. Assign items the QoS that matches their intent, based on the descriptions of each service level. If you require things to run in a certain order, then use dependencies (like notify) to order them.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thanks for your answer! If I understand correctly, in my example **item1** in fact won't have **. userInitiated** QoS, am I right? – V.V.V Nov 02 '19 at 06:38
  • Actually, it will. That initializer promises "the queue never executes the block with a quality-of-service level lower than the one in the qos parameter." `concurrentQueue` will be temporarily promoted to `userInitiated` in order to run it at the higher QoS. But if you submitted item2 to a UI queue, then it would keep its UT (utility) level rather than being promoted to UI. – Rob Napier Nov 02 '19 at 21:17
  • See https://developer.apple.com/videos/play/wwdc2017/706 for more discussion. It's a fairly complicated system, and in general you should avoid being clever with it. If you mark things according to their intent, for most systems you'll be fine, particularly general app development. Unless you're building high performance systems that have extensive and non-trivial concurrency, I wouldn't even bother learning more than the simple QoS levels. Trying to outthink the defaults more often leads to bad performance than good. – Rob Napier Nov 02 '19 at 21:20
  • Well, now the work of this mechanism has become much clearer, thanks for the answer! – V.V.V Nov 05 '19 at 20:01