zoukankan      html  css  js  c++  java
  • 【原】golang 中字符串拼接的方式性能对比

    背景

        开发过程中,常常会用到字符串拼接完成某种需求,我们能马上想到的解决办法有+,fmt.Sprintf,高级一点可能还会想到strings包的Join 方法,甚至想到bytes.buffer,再用writeString 方法完成,再而想到strings.builder。但究竟哪种效率高呢?我们在使用过程中如何选择?只有实测才知道

    结论

        测试结论 bytes.Buffer > + > strings.Join > strings.builder > fmt.Sprintf 。

        简单拼接用+,复杂,追求高效用bytes.Buffer

    实测

        以下测试在个人mac 系统下。go 版本1.15,不同版本可能略有不同,以自己实际输出为准。

    测试1

     

    package strings

    import (
    "bytes"
    "fmt"
    "strings"
    "testing"
    )

    func BenchmarkStringBuild(b *testing.B) {
    hello := "hello"
    world := "world"
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    var result strings.Builder
    result.WriteString(hello)
    result.WriteString(world)
    //result.WriteString("aaa")
    //result.WriteString(strconv.Itoa(10000))
    }
    }

    func BenchmarkStringJia(b *testing.B) {
    hello := "hello"
    world := "world"
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    //_ = hello + world + "aaa !" + strconv.Itoa(10000)
    _ = hello + world
    }
    }

    func BenchmarkStringSprintf(b *testing.B) {
    hello := "hello"
    world := "world"
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    //_ = fmt.Sprintf("%s,%s,%s,%d", hello, world, "aaa !", 1000)
    _ = fmt.Sprintf("%s,%s", hello, world)
    }
    }

    func BenchmarkAddStringWithJoin(b *testing.B) {
    hello := "hello"
    world := "world"
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    //_ = strings.Join([]string{hello, world, "aaa !", strconv.Itoa(10000)}, ",")
    _ = strings.Join([]string{hello, world}, ",")
    }
    }

    func BenchmarkAddStringWithBuffer(b *testing.B) {
    hello := "hello"
    world := "world"
    for i := 0; i < 1000; i++ {
    var buffer bytes.Buffer
    buffer.WriteString(hello)
    buffer.WriteString(",")
    buffer.WriteString(world)
    //buffer.WriteString("aaa !")
    //buffer.WriteString(strconv.Itoa(10000))
    _ = buffer.String()
    }
    }

     

     

    测试2

     

     

    package strings

    import (
    "bytes"
    "fmt"
    "strconv"
    "strings"
    "testing"
    )

    func BenchmarkStringBuild(b *testing.B) {
    hello := "hello"
    world := "world"
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    var result strings.Builder
    result.WriteString(hello)
    result.WriteString(world)
    result.WriteString("aaa")
    result.WriteString(strconv.Itoa(10000))
    }
    }

    func BenchmarkStringJia(b *testing.B) {
    hello := "hello"
    world := "world"
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    _ = hello + world + "aaa !" + strconv.Itoa(10000)
    //_ = hello + world
    }
    }

    func BenchmarkStringSprintf(b *testing.B) {
    hello := "hello"
    world := "world"
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    _ = fmt.Sprintf("%s,%s,%s,%d", hello, world, "aaa !", 1000)
    //_ = fmt.Sprintf("%s,%s", hello, world)
    }
    }

    func BenchmarkAddStringWithJoin(b *testing.B) {
    hello := "hello"
    world := "world"
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    _ = strings.Join([]string{hello, world, "aaa !", strconv.Itoa(10000)}, ",")
    //_ = strings.Join([]string{hello, world}, ",")
    }
    }

    func BenchmarkAddStringWithBuffer(b *testing.B) {
    hello := "hello"
    world := "world"
    for i := 0; i < 1000; i++ {
    var buffer bytes.Buffer
    buffer.WriteString(hello)
    buffer.WriteString(",")
    buffer.WriteString(world)
    buffer.WriteString("aaa !")
    buffer.WriteString(strconv.Itoa(10000))
    _ = buffer.String()
    }
    }

     

     

    执行:$ go test -bench=. -benchmem -run=none

    结果显而易见,即便我只拼接hello world,不同方式的对比差异也是显著的。

    可看到

    • string.Builder内存分配4次,分配字节数64字节
    • + 进行内存分配1次,分配字节数5字节
    • fmt.Sprintf 进行内存分配3次,分配字节数64字节
    • strings.Join 进行内存分配2次,分配字节数37字节
    • bytes.Buffer WriteString进行内存分配0次,分配字节数0

    结果一般没想到的是+ 在1.15版本性能是大于 strings.Join 和fmt.Sprintf的。所以在我们使用中优先选择bytes.Buffer WriteString、其次简单的,方便阅读和编写可用+。

  • 相关阅读:
    锁表
    vs2010宏的应用
    Oracle:sqlplus查询出的中文是乱码问题的解决(转)
    linux下查看端口和服务的一些命令
    netsh
    xpshutdown关机命令详解
    linux系统如何察看、修改系统时间
    delphi编程中调用其他执行程序?(转)
    如何修改Oracle用户密码的诀窍(转)
    转:用Delphi实现从Excel数据Update(Insert类似)到Oracle数据库表中
  • 原文地址:https://www.cnblogs.com/already/p/13686154.html
Copyright © 2011-2022 走看看