blog
blog copied to clipboard
字符串拼接性能及原理 | Go 语言高性能编程 | 极客兔兔
https://geektutu.com/post/hpg-string-concat.html
Go 语言/golang 高性能编程,Go 语言进阶教程,Go 语言高性能编程(high performance go)。详细介绍了构造字符串/拼接字符串(string concatation) 的 5 种方式:+, strings.Builder, bytes.Buffer, []byte 和 fmt.Sprintf,比较了这 5 种方式的性能,并且深入解释了背后的原理。
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
源码里貌似写的是大于1024后不一致呀,博主的golang版本是什么呢?
@sh1luo ,假设 old.len == 1000
,此时 cap == 1024
,那么 newcap = doublecap
将会是 2048,所以 1024 到 2048 也是倍数增加的,和 benchmark 跑出来的数字对应。
写的不错,详略得当,有理有据。好好和大佬学习。
@l-xue-yu 笔芯~ 😸
使用strings.Builder的话,每箱拼接一个字符串都要调用一下builder.WriteString,感觉好麻烦啊
总结:
- 字符串最高效的拼接方式是结合预分配内存方式
Grow
使用string.Builder
- 当使用
+
拼接字符串时,生成新字符串,需要开辟新的空间 - 当使用
strings.Builder
,bytes.Buffer
或[]byte
的内存是按倍数申请的,在原基础上不断增加 -
strings.Builder
比bytes.Buffer
性能更快,一个重要区别在于bytes.Buffer
转化为字符串重新申请了一块空间存放生成的字符串变量;而strings.Builder
直接将底层的[]byte
转换成字符串类型返回
本质上 string.Builder 是以空间换时间,如果不进行字符串的拼接,那么 string.Builder 这种非紧凑型设计有内存碎片,而 string 本身是不会有内存碎片(不考虑 CPU 的内存对齐)。
@Spongecaptain string.Builder
是为了字符串的多次拼接设计的,这样的话,按照算法申请空间,可以尽量避免空间不够导致的拷贝。如果是一次拼接,甚至是不拼接,那用 string 就 OK 了。
BenchmarkPlusConcat 16801 71512 ns/op 0 B/op 0 allocs/op 为什么我的内存分配次数是零呢?我在Linux和mac上都分别跑了一下,-benchmem都是0.