为什么FileManager.enumerator使用荒谬的内存量?

时间:2017-09-23 18:48:38

标签: swift macos memory-leaks nsfilemanager

有没有人知道为什么以下代码使用荒谬的4.75 GB内存?

有没有更好的方法来循环文件系统中的所有文件? (我试图找到驱动器上最大的文件)

let filemanager:FileManager = FileManager()
let root = "/"
let files = filemanager.enumerator(atPath: root)
while let element = files?.nextObject() {
    // do nothing
}

注意:我的文件系统上有400k文件(没什么特别的)。代码是顺序的,所以理论上它甚至不应该依赖于文件的数量。

1 个答案:

答案 0 :(得分:4)

我用内存图暂停了它,它显示了从fileSystemRepresentation(withPath:)分配的荒谬数量的NSConcreteData实例。

该文档页面指出它是一个仅对当前自动释放池有用的指针。这表明了一个解决方案:我们只需要将nextObject()调用放入自己的自动释放池中。

例如,该程序保持稳定在11.0 MB:

var done = false
while !done {
    autoreleasepool {
        let element = files?.nextObject()
        done = (element == nil)

        // do nothing
    }
}

看起来Swift的while let语法将绑定放在while循环上下文的自动释放池中,因此每个元素都会保留,直到整个循环完成。

通过强制枚举器对象进入我们自己的自动释放池,我们可以确保在后续迭代期间不会保留它。

编辑:由于autoreleasepool只是一个功能,我本可以更简洁地写出来:

while let element = autoreleasepool(invoking: { files?.nextObject() }) {
    // do nothing
}