我正在编写一个相当大的文本文件(它实际上更像是ASCII编码的数据),而且它是...非常慢.并且使用了大量的内存.
下面是我用来测试如何更快地编写文件的简约版本的代码.writeFileIncrementally
在for循环中一次写入一行,而writeFileFromBigData
创建一个大字符串,然后将其转储到磁盘.我完全预计writeFileFromBigData
会更快,但20 times faster!比我预期的要快一点.对于size=10_000_000
,递增写入需要20-25秒,一次写入需要1-1.5秒.此外,增量版本实际上在运行过程中分配了越来越多的内存.到最后,它很好地进入GiB范围.我不明白这是怎么回事.
func writeFileIncrementally(toUrl url: URL, size: Int) {
// ensure file exists and is empty
try? "".write(to: url, atomically: true, encoding: .ascii)
guard let handle = try? FileHandle(forWritingTo: url) else {return}
defer {
handle.closeFile()
}
for i in 0..<size {
let s = "\(i)\n"
handle.write(s.data(using: .ascii)!)
}
}
func writeFileFromBigData(toUrl url: URL, size: Int) {
let s = (0..<size).map{String($0)}.joined(separator: "\n")
try? s.write(to: url, atomically: true, encoding: .ascii)
}
将其与Python中的相同内容进行比较.在Python语言中,创建-字符串-然后-写-它也更快.这是合理的,但在Python中的不同之处在于,递增编写它大约需要2.7秒(大约98%的用户时间),而一次性编写它大约需要1秒(包括创建字符串).此外,增量版本具有恒定的内存使用量.在写入文件时,它不会上升.
def writeFileIncrementally(path, size):
with open(path, "w+") as f:
for i in range(size):
f.write(f"{i}\n")
def writeFileFromBigData(path, size):
with open(path, "w+") as f:
f.write("\n".join(str(i) for i in range(size)))
所以我的问题有两个:
- 为什么我的
writeFileIncrementally
函数这么慢,为什么它占用这么多内存?我希望能够以增量方式写入以减少内存使用. - 在SWIFT中,有没有更好的增量编写大型文本文件的方法?