性能调优之三十六计 —— 「优中取优」字符串拼接 篇
Posted 魏小言
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了性能调优之三十六计 —— 「优中取优」字符串拼接 篇相关的知识,希望对你有一定的参考价值。
性能调优之三十六计 —— 「优中取优」字符串拼接 篇
性能调优是每一个程序员进阶的毕竟之路,掌握各种调优技巧,对自身实力、价值的提升至关重要!继上篇 “ 原生 Echo 框架 JSON 优化 ” 之后,我们把目光转向 “ 字符串拼接 ”。
在生产开发中,“ 字符串拼接 ” 出镜率极高,像日志落地、URI 参数构造、等等众多场景。开发语言也为我们提供了各种拼接姿势,如:
- Java 中 “ + ”操作符 、StringBuilder、StringBuffer、Concat 、Join 、等等…
- Go 中 “ + ” 操作符、fmt.Sprintf、Join、bytes.Buffer、strings.Builder、等等…
那么你最常用的是哪一种呢?性能如何呢?
+ 操作符
“ + ” 操作符是比较受喜欢的一种方式,它更便于阅读,符合人们运算范式的认知。
举个例子:
s1 := "字符串"
s2 := "拼接"
s3 := s1 + s2
fmt.Print(s3) //s3 = "打印字符串"
大家可以看到,其拼接过程中会产生新的变量,因为 String 类型为不可变类型。正是变量的产生中,内存的分配、GC 的回收,整体性能在某些场景会拉垮。
fmt.Sprintf
fmt.Sprintf 是 fmt 包内置的一种拼接方式,经常在构造 URI 参数时使用。
举个例子:
s1 := "字符串"
s2 := "拼接"
s3 := fmt.Sprintf("%s%s", s1, s2) //s3 = "打印字符串"
大家可以看到,其在使用的过程中,需要进行格式定义 %s 、%d、等等,为兼容更多的格式类型,Sprintf 会统一以 Interface 为基准,分别对每种类型进行设计实现,性能问题就是在这里。
Sprintf 性能往往不如 “ + ” 操作符。
Join
Join 是指数组类型行为方式,数组通过 JOIN 将元素以某种形式进行拼接。
举个例子:
s1 := "字符串"
s2 := "拼接"
var str []string = []string{s1, s2}
s3 := strings.Join(str, "")
fmt.Print(s3)
Join 会先根据字符串数组的内容,计算出一个拼接之后的长度,然后申请对应大小的内存,一个一个字符串填入。
Join 的性能与数组对象的创建息息相关,与 “ + “ 操作符相差无几,但更适合数组原生场景。
buffer.WriteString
buffer.WriteString 故名思义,往字节缓冲区中写 String。
举个例子:
s1 := "字符串"
s2 := "拼接"
var bt bytes.Buffer
bt.WriteString(s1)
bt.WriteString(s2)
s3 := bt.String()
type Buffer struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
lastRead readOp // last read operation, so that Unread* can work correctly.
}
先是建立一字节缓冲区,向其中写入字节数组「string」,最后将其转化为 String 。
WriteString 由于没有多余的变量参与,性能具有最大优势。
buffer.Builder
buffer.Builder 是 Go 1.10 之后,官方提供的另一种方式,也是官方所提倡的。
举个例子
s1 := "字符串"
s2 := "拼接"
var build strings.Builder
build.WriteString(s1)
build.WriteString(s2)
s3 := build.String()
*(*string)(unsafe.Pointer(&bytes))
buffer.Builder 与 buffer.WriteString 内部都是通过 slice 来保存和管理内容。不同的是,buffer.Builder 在 String() 时,使用了指针,节省时间和空间,所以其性能最优!
Q&A
1、既然性能有差别,为啥还提供那么多不同的姿势呢?
这个问题忽略了事物发展演化过程。举个例子,随着工业的不断革新,交通业推出速度更快,更安全的交通工具。但之前诸如,马车、自行车、摩托车、依旧出现在不同的道路。
2、文中的性能具体是指速度吗?
是的。
3、文中貌似是 Go 为基准,可否介绍下其它语言?
文中以 Go 为基准讲解,其它语言可私信博主交流
附录
编程工作适宜乐观主义人群。
以上是关于性能调优之三十六计 —— 「优中取优」字符串拼接 篇的主要内容,如果未能解决你的问题,请参考以下文章
性能调优之三十六计 —— 「取而代之」Echo/Json 篇