Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoreleaseFrequency on DispatchQueue in Swift 3

Tags:

In Xcode 8 beta 5, the initializer for DispatchQueue has changed to accept separate arguments for qos (quality of service), attributes, and autorelease frequency. While I did not have any problems converting my code to work with the new initializer, I am uncertain on the meaning of some of the attributes, particularly autorelease frequency.

For example, in Xcode 8 beta 3 and Swift 3, I was able to create a serial DispatchQueue as such:

let serialQueue = DispatchQueue(label: "Concurrent Map", attributes: [.serial, .qosBackground], target: nil) 

In Xcode 8 beta 5 and Swift 3:

let serialQueue = DispatchQueue(label: "Concurrent Map", qos: .background, attributes: [], autoreleaseFrequency: .inherit, target: nil) 

My questions are:

  • In the new DispatchQueue.Attributes, .serial is no longer a member. Does this mean that the absence of .concurrent creates a serial queue. An initial test I did in Swift Playgrounds seems to confirm this. Can anyone else confirm?
  • I see that DispatchQueue.AutoreleaseFrequency is a new type with .inherit, .never, and .workItem. What do these mean? I did some research on GCD and autoreleasing but I'm not very familiar with the concept of autorelease pools.
like image 699
Matthew Seaman Avatar asked Aug 10 '16 22:08

Matthew Seaman


2 Answers

I find the answer given by Mark "subjective", as he said, no official documentation is out in the docs yet. However, you can find official documentation in code, so I am giving what I believe should be the correct answer since it's purely based on what is found in the code documentation and not on opinion. Here it is:

DISPATCH_AUTORELEASE_FREQUENCY_INHERIT Dispatch queues with this autorelease frequency inherit the behavior from their target queue. This is the default behavior for manually created queues.

DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM Dispatch queues with this autorelease frequency push and pop an autorelease pool around the execution of every block that was submitted to it asynchronously.

DISPATCH_AUTORELEASE_FREQUENCY_NEVER Dispatch queues with this autorelease frequency never set up an individual autorelease pool around the execution of a block that is submitted to it asynchronously. This is the behavior of the global concurrent queues.

like image 118
zumzum Avatar answered Oct 20 '22 14:10

zumzum


I couldn't find any official documentation of those new attributes (it's probably being worked on), but given the existing GCD documentation, and reading between the lines, it's pretty easy to intuit what's intended here.

In the new DispatchQueue.Attributes, .serial is no longer a member. Does this mean that the absence of .concurrent creates a serial queue. An initial test I did in Swift Playgrounds seems to confirm this. Can anyone else confirm?

Yes. A queue is either serial or concurrent. Most queues you create will be serial, so you only need to set them to be concurrent if you don't want the default behavior.

I see that DispatchQueue.AutoreleaseFrequency is a new type with .inherit, .never, and .workItem. What do these mean? I did some research on GCD and autoreleasing but I'm not very familiar with the concept of autorelease pools.

Previously, DispatchQueues would pop their autorelease pools at unspecified times (when the thread became inactive). In practice, this meant that you either created an autorelease pool for each dispatch item you submitted, or your autoreleased objects would hang around for an unpredictable amount of time.

Non-determinism is not a great thing to have (particularly in a concurrency library!), so they now allow you to specify one of three behaviors:

.inherit: Not sure, probably the previously-default behavior

.workItem: Create and drain an autorelease pool for each item that gets executed

.never: GCD doesn't manage autorelease pools for you

Out of all of these, you're likely only going to want to use .workItem, because it'll clean up your temporary objects when the item completes. The other options are presumably for either buggy code that depends on the old behavior, or for that rare user that actually wants to manage this stuff themselves.


Actually, thinking about it a bit more, if you're submitting work items that are Swift-only (they don't call into any Objective-C code), then .never is probably safe & correct. Given that any/all Swift standard library classes might call some Objective-C code, you'd probably want to limit this to computations which reside entirely within your own Swift code.

like image 35
Mark Bessey Avatar answered Oct 20 '22 14:10

Mark Bessey