zoukankan      html  css  js  c++  java
  • golang 字符串拼接性能比较

    背景
    最近在做一个服务发现/注册的agent, 各个服务需要通过这个agent来注册自己的服务,在完成
    开发后,测试性能时发现性能达不到要求,通过pprof 来确认cpu主要耗费在gc上,分析结果主要是由于字符串拼接导致,故需要测试一下字符串拼接的几种方法的性能;
    1
    2
    字符串拼接的几种方法
    直接使用加号进行拼接
    strings.Join()
    fmt.Sprintf()
    bytes.Buffer
    大量字符串拼接性能测试
    我们使用的场景主要是大量字符串拼接,所以需要的场景是不断在字符串上拼接所以测试函数如下:

    // fmt.Printf
    func BenchmarkFmtSprintfMore(b *testing.B) {
    var s string
    for i := 0; i < b.N; i++ {
    s += fmt.Sprintf("%s%s", "hello", "world")
    }
    fmt.Errorf(s)
    }
    // 加号 拼接
    func BenchmarkAddMore(b *testing.B) {
    var s string
    for i := 0; i < b.N; i++ {
    s += "hello" + "world"
    }
    fmt.Errorf(s)
    }

    // strings.Join
    func BenchmarkStringsJoinMore(b *testing.B) {

    var s string
    for i := 0; i < b.N; i++ {
    s += strings.Join([]string{"hello", "world"}, "")

    }
    fmt.Errorf(s)
    }

    // bytes.Buffer
    func BenchmarkBufferMore(b *testing.B) {

    buffer := bytes.Buffer{}
    for i := 0; i < b.N; i++ {
    buffer.WriteString("hello")
    buffer.WriteString("world")

    }
    fmt.Errorf(buffer.String())
    }
    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
    执行测试函数

    ~/gopath/src/test/string � go test -bench="."
    goos: darwin
    goarch: amd64
    pkg: test/string
    BenchmarkFmtSprintfMore-4 300000 118493 ns/op
    BenchmarkAddMore-4 300000 124940 ns/op
    BenchmarkStringsJoinMore-4 300000 117050 ns/op
    BenchmarkBufferMore-4 100000000 37.2 ns/op
    PASS
    ok test/string 112.294s
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    从上可以看出使用bytes.buffer的性能是非常高的,如果涉及到大量数据拼接推荐
    bytes.buffer{}

    单次字符串拼接性能测试

    func BenchmarkFmtSprintf(b *testing.B) {
    for i := 0; i < b.N; i++ {
    s := fmt.Sprintf("%s%s", "hello", "world")
    fmt.Errorf(s)
    }

    }

    func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
    s := "hello" + "world"
    fmt.Errorf(s)
    }
    }
    func BenchmarkStringsJoin(b *testing.B) {
    for i := 0; i < b.N; i++ {
    s := strings.Join([]string{"hello", "world"}, "")
    fmt.Errorf(s)
    }
    }
    func BenchmarkBuffer(b *testing.B) {

    for i := 0; i < b.N; i++ {
    b := bytes.Buffer{}
    b.WriteString("hello")
    b.WriteString("world")
    fmt.Errorf(b.String())
    }
    }
    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
    执行测试函数

    ~/gopath/src/test/string � go test -bench="."
    goos: darwin
    goarch: amd64
    pkg: test/string
    BenchmarkFmtSprintf-4 10000000 200 ns/op
    BenchmarkAdd-4 20000000 93.6 ns/op
    BenchmarkStringsJoin-4 10000000 152 ns/op
    BenchmarkBuffer-4 10000000 175 ns/op
    PASS
    ok test/string 7.818s
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    从上可以看出单词调用字符串拼接性能 + > strings.Join > bytes.Buffer > fmt.Sprintf

    总结
    如果涉及到大量数据拼接推荐 bytes.buffer{}

    后记
    当然只是通过bytes.buffer{} 性能还是不够的,针对这个问题我们通过添加缓存进一步接口qps.
    cpu 耗费在gc 上的原因,需要分析golang gc 回收机制, 这是另外一个topic, 之后总结。
    ————————————————
    版权声明:本文为CSDN博主「BigSimle」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/BeSimpleBeGood/article/details/80399882

  • 相关阅读:
    LeetCode Power of Three
    LeetCode Nim Game
    LeetCode,ugly number
    LeetCode Binary Tree Paths
    LeetCode Word Pattern
    LeetCode Bulls and Cows
    LeeCode Odd Even Linked List
    LeetCode twoSum
    549. Binary Tree Longest Consecutive Sequence II
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/ExMan/p/15067546.html
Copyright © 2011-2022 走看看