我在macOS上运行了一个Swift应用程序。它批量处理图像。我不知道这些图片会有多大,以及我的应用程序将运行什么硬件 - 这些都取决于用户。
我使用GCD来并行处理图像,因为它可以真正加快吞吐量。
然而,在某些情况下,过多的并行化可能会造成伤害:如果用户处理高分辨率图像,并行化会产生太大的内存压力,系统的性能也会变差。
所以我想找到一种方法“以最大化并行化的速率”为“并行任务处理器”提供服务,同时将工作量保持在RAM中(因此没有任何触发器进行分页和交换:我想避免磁盘IO)。
关于如何做到这一点的任何想法?
答案 0 :(得分:0)
内存压力事件有GCD dispatch source。不确定你的代码是如何构建的,但是可以创建并行任务,直到你得到DISPATCH_MEMORYPRESSURE_WARN
事件,然后停止制作任务甚至杀死一些?
答案 1 :(得分:0)
我最终实现了一个TokenBucket类型的单例,它根据内存需求处理接纳控制。它被初始化,以便我的应用程序可以使用80%的RAM。
let memoryGate = MemoryGate(maxBytes: ProcessInfo.processInfo.physicalMemory*8/10)
当有人想要执行内存密集型操作时,它必须从中请求()内存。如果内存不足,则呼叫会阻塞,直到有。完成后,线程必须释放()内存。
代码:
class MemoryGate {
private let maxBytes : UInt64
private var availableBytes : Int64
private let cv = NSCondition()
init(maxBytes: UInt64) {
self.maxBytes = maxBytes
self.availableBytes = Int64(maxBytes)
Log.debug?.message("maxBytes=\(maxBytes)")
}
public func request(amount: UInt64) {
Log.debug?.message("Resquesting \(amount) bytes")
cv.lock()
// If the amount is bigger than the max allowed, no amount of waiting is going
// to help, so we go through and let the other smaller jobs be held back until
// memory is freed
if (amount <= maxBytes) {
while (availableBytes < Int64(amount)) {
cv.wait()
}
}
availableBytes -= Int64(amount)
Log.debug?.message("Got \(amount) bytes. availableBytes=\(availableBytes)")
cv.unlock()
}
public func release(amount: UInt64) {
cv.lock()
availableBytes += Int64(amount)
Log.debug?.message("Released \(amount) bytes. availableBytes=\(availableBytes)")
cv.broadcast()
cv.unlock()
}
}