計測が不十分だったかな
前回の計測は、- bytes.Buffer を使用するにしても事前にバイト数を算出したほうがいいのか?
- append()で結合したらどうなん?
コード
package main import ( "bytes" "fmt" "time" ) var tests = []string{ "Lorem ipsum dolor sit amet", "consectetur adipisicing elit", "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua", "Ut enim ad minim veniam", "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat", } func concat(times int) string { c := len(tests) s := "" for n := 0; n < times; n++ { s += tests[n%c] } return s } func useBuffer256(times int) string { c := len(tests) // 結合後の byte 数を得る size := 0 for n := 0; n < times; n++ { size += len(tests[n%c]) } buffer := bytes.NewBuffer(make([]byte, 0, 256)) for n := 0; n < times; n++ { buffer.WriteString(tests[n%c]) } return buffer.String() } func useBuffer(times int) string { c := len(tests) // 結合後の byte 数を得る size := 0 for n := 0; n < times; n++ { size += len(tests[n%c]) } buffer := bytes.NewBuffer(make([]byte, 0, size)) for n := 0; n < times; n++ { buffer.WriteString(tests[n%c]) } return buffer.String() } func likeJoin(times int) string { c := len(tests) // 結合後の byte 数を得る size := 0 for n := 0; n < times; n++ { size += len(tests[n%c]) } // バッファを必要な分確保する buffer := make([]byte, size) // 文字列のコピー bp := 0 for n := 0; n < times; n++ { bp += copy(buffer[bp:], tests[n%c]) } return string(buffer) } func useAppend(times int) string { c := len(tests) // 結合後の byte 数を得る size := 0 for n := 0; n < times; n++ { size += len(tests[n%c]) } // バッファを必要な分確保する buffer := make([]byte, 0, size) // 文字列のコピー for n := 0; n < times; n++ { buffer = append(buffer, tests[n%c]...) } return string(buffer) } func measure(loop, times int) { fmt.Println("--- loop:", loop, "times:", times, "---") var ( start time.Time end time.Time ) start = time.Now() for n := 0; n < loop; n++ { concat(times) } end = time.Now() fmt.Println("concat()", end.Sub(start).Nanoseconds()/1000, "us") start = time.Now() for n := 0; n < loop; n++ { useBuffer256(times) } end = time.Now() fmt.Println("useBuffer256()", end.Sub(start).Nanoseconds()/1000, "us") start = time.Now() for n := 0; n < loop; n++ { useBuffer(times) } end = time.Now() fmt.Println("useBuffer()", end.Sub(start).Nanoseconds()/1000, "us") start = time.Now() for n := 0; n < loop; n++ { likeJoin(times) } end = time.Now() fmt.Println("likeJoin()", end.Sub(start).Nanoseconds()/1000, "us") start = time.Now() for n := 0; n < loop; n++ { useAppend(times) } end = time.Now() fmt.Println("useAppend()", end.Sub(start).Nanoseconds()/1000, "us") } func main() { measure(10, 10000) measure(10000, 10) }
結果
loop: 10 times: 10000
- concat()
- 5,288,925 us
- useBuffer256()
- 8,536 us
- useBuffer()
- 6,480 us
- likeJoin()
- 6,122 us
- useAppend()
- 5,664 us
loop: 10000 times: 10
- concat()
- 27,830 us
- useBuffer256()
- 17,895 us
- useBuffer()
- 12,487 us
- likeJoin()
- 10,746 us
- useAppend()
- 11,550 us
やっぱり、余計なコードが走らないコードが一番速い。
bytes.Buffer を使用するにしても、やはり事前にバイト数を計算したほうが速い likeJoin()とuseAppend()の差はもはや誤差の範囲かな。
あとは
- バッファから溢れたとき拡張して欲しければ append()
- バッファを拡張して欲しくないときは copy()
0 件のコメント:
コメントを投稿