3 回答
TA贡献1893条经验 获得超10个赞
bufio包正是为这种任务而创建的。在进行系统调用之前,不是为每个 Write 调用进行系统调用,而是bufio.Writer在内部存储器中缓冲最多固定数量的字节。在系统调用之后,内部缓冲区被重用于下一部分数据
与您的第二种方法相比 bufio.Writer
进行更多系统调用(N/S而不是1)
使用更少的内存(S字节而不是N字节)
其中S- 是缓冲区大小(可以通过 指定bufio.NewWriterSize),N- 需要写入的数据的总大小。
示例用法(https://play.golang.org/p/AvBE1d6wpT):
f, err := os.Create("file.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
w := bufio.NewWriter(f)
fmt.Fprint(w, "Hello, ")
fmt.Fprint(w, "world!")
err = w.Flush() // Don't forget to flush!
if err != nil {
log.Fatal(err)
}
TA贡献1836条经验 获得超3个赞
写入文件时需要时间的操作是系统调用和磁盘 I/O。文件指针打开这一事实不会花费您任何费用。太天真了,我们可以说第二种方法是最好的。
现在,您可能知道,您的操作系统不会直接写入文件,它使用内部内存缓存来保存已写入的文件并稍后执行真正的 I/O。我不知道那的确切细节,一般来说我不需要。
我的建议是一个中间的解决方案:为每次循环迭代做一个缓冲区,然后写 N 次。这种方式可以减少系统调用和(可能)磁盘写入的大部分数量,但不会消耗过多的缓冲区内存(取决于字符串的大小,这是一个需要考虑的点)。
我建议对最佳解决方案进行基准测试,但由于系统进行了缓存,因此对磁盘 I/O 进行基准测试是一场真正的噩梦。
TA贡献1824条经验 获得超6个赞
系统调用并不便宜,所以第二种方法更好。
您可以使用lmbench 中的 lat_syscall工具来测量调用 single 所需的时间write
:
$ ./lat_syscall write Simple write: 0.1522 microseconds
因此,在我的系统上,仅调用write
每个字符串需要大约 20000 * 0.15μs = 3ms 的额外时间。
- 3 回答
- 0 关注
- 218 浏览
添加回答
举报