我一直在做一些基准测试以尝试理解Linux上的写入性能,而且我不理解我得到的结果(我在Ubuntu 17.04上使用ext4,尽管我'如果有的话,我更感兴趣的是了解ext4,而不是比较文件系统。)
具体来说,我了解一些数据库/文件系统的工作方式是保留数据的陈旧副本,然后将更新写入修改日志。定期地,在陈旧数据上重放日志以获得新数据,然后将其保留。这只对我有意义,如果附加到文件比覆盖整个文件更快(否则为什么要写日志更新?为什么不覆盖磁盘上的数据?)。我很好奇附加速度比覆盖更快,所以我在go(https://gist.github.com/msteffen/08267045be42eb40900758c419c3bd38)中写了一个小基准并得到了这些结果:
$ go test ./write_test.go -bench='.*'
BenchmarkWrite/Write_10_Bytes_10_times-8 30 46189788 ns/op
BenchmarkWrite/Write_100_Bytes_10_times-8 30 46477540 ns/op
BenchmarkWrite/Write_1000_Bytes_10_times-8 30 46214996 ns/op
BenchmarkWrite/Write_10_Bytes_100_times-8 3 458081572 ns/op
BenchmarkWrite/Write_100_Bytes_100_times-8 3 678916489 ns/op
BenchmarkWrite/Write_1000_Bytes_100_times-8 3 448888734 ns/op
BenchmarkWrite/Write_10_Bytes_1000_times-8 1 4579554906 ns/op
BenchmarkWrite/Write_100_Bytes_1000_times-8 1 4436367852 ns/op
BenchmarkWrite/Write_1000_Bytes_1000_times-8 1 4515641735 ns/op
BenchmarkAppend/Append_10_Bytes_10_times-8 30 43790244 ns/op
BenchmarkAppend/Append_100_Bytes_10_times-8 30 44581063 ns/op
BenchmarkAppend/Append_1000_Bytes_10_times-8 30 46399849 ns/op
BenchmarkAppend/Append_10_Bytes_100_times-8 3 452417883 ns/op
BenchmarkAppend/Append_100_Bytes_100_times-8 3 458258083 ns/op
BenchmarkAppend/Append_1000_Bytes_100_times-8 3 452616573 ns/op
BenchmarkAppend/Append_10_Bytes_1000_times-8 1 4504030390 ns/op
BenchmarkAppend/Append_100_Bytes_1000_times-8 1 4591249445 ns/op
BenchmarkAppend/Append_1000_Bytes_1000_times-8 1 4522205630 ns/op
PASS
ok command-line-arguments 52.681s
这给我留下了两个我无法想到答案的问题:
1)当我从100次写入到1000次时,为什么每次操作的时间会增加很多? (我知道Go会为我重复基准测试,所以自己做多次写操作可能很傻,但是因为我得到了一个奇怪的答案,我想了解原因)这是由于Go测试中的一个错误(现已修复)
2)为什么不写入文件比写入文件更快?我认为更新日志的重点是利用附加的比较速度? (请注意,当前的工作台在每次写入后都会调用Sync()
,但即使我不这样做,也不会比写入更快,尽管两者总体上要快得多)
如果这里的任何专家能够启发我,我真的很感激!谢谢!
答案 0 :(得分:2)
关于(1),我认为这个问题与你的基准没有做Go工具期望他们做的事情有关。
从文档(https://golang.org/pkg/testing/#hdr-Benchmarks):
基准函数必须运行目标代码b.N次。在基准执行期间,调整b.N直到基准函数持续足够长的时间以便可靠地计时。
我没有看到您的代码使用b.N
,因此当基准工具认为您运行代码b.N
次时,您自己管理重复。根据工具实际用于b.N
的值,结果会出乎意料地变化。
您实际上可以执行10次,100次和1,000次,但在所有情况下执行b.N
次{使b.N * 10
,b.N * 100
等等,以便报告的基准是调整得当。
关于(2),当某些系统使用顺序日志来存储重放它们的操作时,并不是因为附加到文件比覆盖单个文件更快。
在数据库系统中,如果需要更新特定记录,则必须首先找到需要更新的实际文件(以及文件中的位置)。
这可能需要多次索引查找,一旦更新记录,您可能需要更新这些索引以反映新值。
因此,正确的比较是附加到单个日志与进行多次读取再加上几次写入。