异步自动释放池

Posted

技术标签:

【中文标题】异步自动释放池【英文标题】:Async autoreleasepool 【发布时间】:2021-10-28 05:20:13 【问题描述】:

我有一种情况,我使用 async/await 在循环中创建了许多 Cocoa 对象,并且内存激增,因为这些对象仅在循环结束时才被释放(而不是每次迭代)。

解决方案是使用autoreleasepool。但是,我似乎无法让 autoreleasepoolasync/await 合作。

这是一个例子:

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)
    

内存一直飙升到 220MB,这对我来说有点太多了。

通常,您可以将内部循环包装在 autoreleasepool 中,这样可以解决问题,但是当我使用 async 函数尝试它时,会出现以下错误:

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

有没有办法解决这个问题?或者是否有另一种方法可以实现在循环内释放 Cocoa 对象的相同目标?

【问题讨论】:

但这不是“泄漏”。内存在循环期间使用,但在循环结束时释放,对吗? @matt 是的,你是对的。我的错。然而,循环内的内存峰值很多 调度队列和 NSThreads 管理它们自己的自动释放池。那么,maybe Task 也一样吗?如果是这样,只需将您的内部异步函数包装到一个任务中。不过,我自己并没有检查这一点。但知道会很有趣! ;) 你应该在 Swift 论坛上发帖。 forums.swift.org我还没有看到任何关于自动释放池和参与者如何交互的讨论。这可能是一个被忽视的细节。值得提出来! 我无法重现该难度。 autoreleasepoolasync 方法中编译并为我工作得很好。 【参考方案1】:

@CouchDeveloper 提到将getImage 包装在Task 中,因为它有自己的autoreleasepool,而且它似乎可以工作!

只是改变

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

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

【讨论】:

以上是关于异步自动释放池的主要内容,如果未能解决你的问题,请参考以下文章

自动释放池

29-oc自动释放池

在自动释放池 内释放创建的自动释放对象 [关闭]

0c-35-自动释放池使用注意

iOS自动释放池_原理_如何工作

iOS自动释放池_原理_如何工作