为什么 FileManager.enumerator 使用了荒谬的内存量?
Why does FileManager.enumerator use an absurd amount of memory?
有人知道为什么以下代码使用了荒谬的 4.75 GB 内存吗?
有没有更好的方法来循环遍历文件系统中的所有文件? (我正在尝试查找驱动器上最大的文件)
let filemanager:FileManager = FileManager()
let root = "/"
let files = filemanager.enumerator(atPath: root)
while let element = files?.nextObject() {
// do nothing
}
注意:我的文件系统上有 400k 个文件(没什么特别的)。代码是顺序的,所以理论上它甚至不应该依赖于文件的数量。
我用内存图暂停了它,它显示了荒谬数量的 NSConcreteData 实例,分配自 fileSystemRepresentation(withPath:)。
该文档页面指出它是一个仅适用于当前自动释放池的指针。这提出了一个解决方案:我们只需要让 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
}
有人知道为什么以下代码使用了荒谬的 4.75 GB 内存吗?
有没有更好的方法来循环遍历文件系统中的所有文件? (我正在尝试查找驱动器上最大的文件)
let filemanager:FileManager = FileManager()
let root = "/"
let files = filemanager.enumerator(atPath: root)
while let element = files?.nextObject() {
// do nothing
}
注意:我的文件系统上有 400k 个文件(没什么特别的)。代码是顺序的,所以理论上它甚至不应该依赖于文件的数量。
我用内存图暂停了它,它显示了荒谬数量的 NSConcreteData 实例,分配自 fileSystemRepresentation(withPath:)。
该文档页面指出它是一个仅适用于当前自动释放池的指针。这提出了一个解决方案:我们只需要让 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
}