【发布时间】:2021-10-28 05:20:13
【问题描述】:
我有一种情况,我使用 async/await 在循环中创建了许多 Cocoa 对象,并且内存激增,因为这些对象仅在循环结束时才被释放(而不是每次迭代)。
解决方案是使用autoreleasepool。但是,我似乎无法让 autoreleasepool 与 async/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我还没有看到任何关于自动释放池和参与者如何交互的讨论。这可能是一个被忽视的细节。值得提出来!
-
我无法重现该难度。
autoreleasepool在async方法中编译并为我工作得很好。
标签: swift macos cocoa async-await swift-concurrency