Async autoreleasepool

Viewed 387

I have a situation where I'm creating many Cocoa objects in a loop using async/await, and the memory spikes because the objects are only released when the loop is over (instead of every iteration).

The solution would be to use an autoreleasepool. However, I can't seem to get autoreleasepool to work with async/await.

Here is an example:

func getImage() async -> NSImage? {
    return NSImage(named: "imagename") // Do some work
}

Task {
    // This leaks
    for _ in 0 ..< 1000000 {
        let image = await getImage()
        print(image!.backgroundColor)
    }
}

The memory spikes all the way up to 220MB, which is a bit too much for me.

Normally, you could wrap the inner loop in a autoreleasepool, and it would fix the problem, but when I try it with an async function, I get this error:

Cannot pass function of type '() async -> ()' to parameter expecting synchronous function type

Is there any way around this? Or is there another method to accomplish the same goal of releasing the Cocoa objects inside of the loop?

1 Answers

@CouchDeveloper mentioned to wrap getImage in a Task, as it has its own autoreleasepool, and it seems to work!

Just change

func getImage() async -> NSImage? {
    return NSImage(named: "imagename") // Do some work
}

to

func getImage() async -> NSImage? {
    await Task {
        return NSImage(named: "imagename") // Do some work
    }.value
}
Related