字符串拼接性能对比

字符串拼接性能对比

笔者在日常工作中经常会遇到将数据进行批处理,即接收多个数据源发送的数据后合并批量操作。在一次针对字符串拼接时出现处理耗时达到 1s(偶发情况),在排查问题时发现在高并发的情况下由于使用了 + 直接对字符串进行拼接导致系统处理时间很慢,因此进行优化。

下面基于常用的字符串拼接进行性能对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
func BenchmarkSprintf(b *testing.B) {
for i := 0; i < b.N; i++ {
var values string
for _, s := range bufData {
if s != "" {
values += fmt.Sprintf("(%s),", s)
}
}
_ = strings.TrimRight(values, ",")
}
}

func BenchmarkBuilder(b *testing.B) {
for i := 0; i < b.N; i++ {
var buf strings.Builder
for _, s := range bufData {
if s != "" {
buf.WriteString("(")
buf.WriteString(s)
buf.WriteString(")")
buf.WriteString(",")
}
}
_ = strings.TrimRight(buf.String(), ",")
}
}

func BenchmarkBufferWriteString(b *testing.B) {
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
for _, s := range bufData {
if s != "" {
buf.WriteString("(")
buf.WriteString(s)
buf.WriteString("),")
}
}
_ = strings.TrimRight(buf.String(), ",")
}
}

func BenchmarkBufferWriteByte(b *testing.B) {
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
for _, s := range bufData {
if s != "" {
buf.Write([]byte("("))
buf.Write([]byte(s))
buf.Write([]byte("),"))
}
}
_ = strings.TrimRight(buf.String(), ",")
}
}

总结

在高并发情况下,使用 bytes.Buffer 进行字符串拼接的效率要比使用 + 或者 Sprintf 的效率高出好几倍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ go test -benchmem -run=^$ -count=3  -bench "^Benchmar.*$"
goos: windows
goarch: amd64
pkg: example/str
cpu: Intel(R) Core(TM) i5-9400 CPU @ 2.90GHz
BenchmarkSprintf-6 7252 156178 ns/op 1243382 B/op 105 allocs/op
BenchmarkSprintf-6 8191 160537 ns/op 1243474 B/op 105 allocs/op
BenchmarkSprintf-6 8370 151687 ns/op 1243526 B/op 105 allocs/op
BenchmarkBuilder-6 35635 33629 ns/op 273802 B/op 12 allocs/op
BenchmarkBuilder-6 33496 35294 ns/op 273802 B/op 12 allocs/op
BenchmarkBuilder-6 35260 35085 ns/op 273801 B/op 12 allocs/op
BenchmarkBufferWriteString-6 47410 26383 ns/op 194368 B/op 8 allocs/op
BenchmarkBufferWriteString-6 46074 26450 ns/op 194368 B/op 8 allocs/op
BenchmarkBufferWriteString-6 44607 25640 ns/op 194368 B/op 8 allocs/op
BenchmarkBufferWriteByte-6 35469 34121 ns/op 257089 B/op 43 allocs/op
BenchmarkBufferWriteByte-6 37026 36862 ns/op 257089 B/op 43 allocs/op
BenchmarkBufferWriteByte-6 34782 35819 ns/op 257089 B/op 43 allocs/op
PASS
ok example/str 18.770s