Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async autoreleasepool

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?

like image 369
recaptcha Avatar asked Sep 07 '26 16:09

recaptcha


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
}
like image 149
recaptcha Avatar answered Sep 10 '26 07:09

recaptcha