ファイルに文字列を書き込む際に、書き込むたびにcloseするのって直感的に遅いような気がするけどどれくらい遅いのか軽く計測してみた。
package main_test
import (
"os"
"testing"
)
func BenchmarkWriteEveryOpenFile(b *testing.B) {
for i := 0; i < b.N; i++ {
WriteEveryOpenFile("testtest\n")
}
}
func WriteEveryOpenFile(s string) {
file, err := os.OpenFile("tmp", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
panic(err)
}
defer file.Close()
file.WriteString(s)
}
func BenchmarkWriteOpeningFile(b *testing.B) {
b.StopTimer()
file, err := os.OpenFile("tmptmp", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
panic(err)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
WriteOpeningFile(file, "testtest\n")
}
file.Close()
}
func WriteOpeningFile(f *os.File, s string) {
f.WriteString(s)
}
Macbook Pro
BenchmarkWriteEveryOpenFile-4 30000 48164 ns/op 72 B/op 3 allocs/op
BenchmarkWriteOpeningFile-4 1000000 1365 ns/op 0 B/op 0 allocs/op
ok github.com/catatsuy/bench_write 4.502s
Debian8(on VirtualBox)
BenchmarkWriteEveryOpenFile 500000 3053 ns/op 72 B/op 3 allocs/op
BenchmarkWriteOpeningFile 1000000 1382 ns/op 0 B/op 0 allocs/op
ok _/home/vagrant/bench_write 2.969s
軽く計っただけだけど、MacとLinuxでかなり差があることに驚いた。Linuxであればパフォーマンスが重要なところでない限り、無理してファイルディスクリプタの使い回しをしなくてもよさそう。
パフォーマンスが必要な部分ではファイルディスクリプタの使い回しをしなければならないことは間違いない。しかしパフォーマンスが致命的な部分ではないのに無理にファイルディスクリプタを使い回そうとすると、ファイルが肥大化したときのログローテートができなくなるなど運用面で問題が出る。うまく使い分けていきたい。
あと手軽にパフォーマンスを計測すると最初はMacでやってしまいがちだけど、ちゃんとLinuxでも動かさないと正確な結果が出ないので(当たり前だけど)気をつけたい。