Go bytes.Buffer 和 strings.Builder 性能比较
Go 语言里字符拼接是常用到的,而且只是进行少量的字符串拼接,这次专门根据这个场景进行做基准测试,具体代码如下,如果测试方法有什么欠妥的地方,还请读者提出来。本次测试力求测试的公平性。
测试目标方法代码:
/** strbyt.go
基准测试代码:
/** strbyt_test.go
执行测试:
cd /usr/local/GOPATH/src/folder/
go test -test.bench=.* -count=5
测试结果打印如下:
从测试结果来看,性能从高到低排序如下:
bytes.Buffer > strings.Builder > string + string > fmt.Sprintf
这次测试的背景是 Go 1.9 版本后,strings 包刚刚增加了 strings.Builder,本人特意看了源码的实现,发现它是非线程安全的,并好奇它和 bytes.Buffer 的性能,特别测试一番,结果两者的性能很接近,在一个水平上。
另外本人针对大量字符串拼接的情况也做了测试,发现 strings.Builder 以微弱的优势胜出了,不过日常我们很少用到大量的字符串拼接的情况。
大量字符串拼接测试结果:
测试目标方法代码:
/** strbyt.go
package src import("bytes""fmt""strings") func AppendWithAdd() { var s string for i: =0; i < 10; i++{ s = s + "string" } } func AppendWithSprintf() { var s string for i: =0; i < 10; i++{ s = fmt.Sprintf("%s%s", s, "string") } } func AppendWithBytesBuffer() { var byt bytes.Buffer for i: =0; i < 10; i++{ byt.WriteString("string") } byt.String() } func AppendWithStringBuilder() { var sbuilder strings.Builder for i: =0; i < 10; i++{ sbuilder.WriteString("string") } sbuilder.String() }**/
基准测试代码:
/** strbyt_test.go
package src import("testing") func Benchmark_AppendWithAdd(b * testing.B) { for i: =0; i < b.N; i++{ AppendWithAdd() } } func Benchmark_AppendWithSprintf(b * testing.B) { for i: =0; i < b.N; i++{ AppendWithSprintf() } } func Benchmark_AppendWithBytesBuffer(b * testing.B) { for i: =0; i < b.N; i++{ AppendWithBytesBuffer() } } func Benchmark_AppendWithStringBuilder(b * testing.B) { for i: =0; i < b.N; i++{ AppendWithStringBuilder() } }**/
执行测试:
cd /usr/local/GOPATH/src/folder/
go test -test.bench=.* -count=5
测试结果打印如下:
goos: linux goarch: amd64 pkg: folder Benchmark_AppendWithAdd-2 3000000 490 ns/op Benchmark_AppendWithAdd-2 3000000 489 ns/op Benchmark_AppendWithAdd-2 3000000 673 ns/op Benchmark_AppendWithAdd-2 2000000 754 ns/op Benchmark_AppendWithAdd-2 3000000 491 ns/op Benchmark_AppendWithSprintf-2 1000000 1443 ns/op Benchmark_AppendWithSprintf-2 1000000 1451 ns/op Benchmark_AppendWithSprintf-2 1000000 1451 ns/op Benchmark_AppendWithSprintf-2 1000000 1445 ns/op Benchmark_AppendWithSprintf-2 1000000 1445 ns/op Benchmark_AppendWithBytesBuffer-2 10000000 184 ns/op Benchmark_AppendWithBytesBuffer-2 10000000 184 ns/op Benchmark_AppendWithBytesBuffer-2 10000000 184 ns/op Benchmark_AppendWithBytesBuffer-2 10000000 184 ns/op Benchmark_AppendWithBytesBuffer-2 10000000 184 ns/op Benchmark_AppendWithStringBuilder-2 10000000 231 ns/op Benchmark_AppendWithStringBuilder-2 10000000 232 ns/op Benchmark_AppendWithStringBuilder-2 10000000 232 ns/op Benchmark_AppendWithStringBuilder-2 10000000 232 ns/op Benchmark_AppendWithStringBuilder-2 10000000 231 ns/op PASS ok folder 41.089s
从测试结果来看,性能从高到低排序如下:
bytes.Buffer > strings.Builder > string + string > fmt.Sprintf
这次测试的背景是 Go 1.9 版本后,strings 包刚刚增加了 strings.Builder,本人特意看了源码的实现,发现它是非线程安全的,并好奇它和 bytes.Buffer 的性能,特别测试一番,结果两者的性能很接近,在一个水平上。
另外本人针对大量字符串拼接的情况也做了测试,发现 strings.Builder 以微弱的优势胜出了,不过日常我们很少用到大量的字符串拼接的情况。
大量字符串拼接测试结果:
goos: linux goarch: amd64 pkg: folder Benchmark_AppendWithAdd-2 1 4557618695 ns/op Benchmark_AppendWithAdd-2 1 4545522179 ns/op Benchmark_AppendWithAdd-2 1 4547196905 ns/op Benchmark_AppendWithAdd-2 1 4570965126 ns/op Benchmark_AppendWithAdd-2 1 4561951695 ns/op Benchmark_AppendWithSprintf-2 1 7634729506 ns/op Benchmark_AppendWithSprintf-2 1 6052255032 ns/op Benchmark_AppendWithSprintf-2 1 5795376326 ns/op Benchmark_AppendWithSprintf-2 1 5823858295 ns/op Benchmark_AppendWithSprintf-2 1 5829590737 ns/op Benchmark_AppendWithBytesBuffer-2 1000 1515946 ns/op Benchmark_AppendWithBytesBuffer-2 1000 1513585 ns/op Benchmark_AppendWithBytesBuffer-2 1000 1513932 ns/op Benchmark_AppendWithBytesBuffer-2 1000 1515592 ns/op Benchmark_AppendWithBytesBuffer-2 1000 1519741 ns/op Benchmark_AppendWithStringBuilder-2 1000 1395933 ns/op Benchmark_AppendWithStringBuilder-2 1000 1390083 ns/op Benchmark_AppendWithStringBuilder-2 1000 1391791 ns/op Benchmark_AppendWithStringBuilder-2 1000 1388121 ns/op Benchmark_AppendWithStringBuilder-2 1000 1388763 ns/op PASS ok folder 69.930s
哇~~~ 竟然还没有评论!