前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >对比Golang不同方式拼接字符串性能

对比Golang不同方式拼接字符串性能

原创
作者头像
KunkkaWu
修改2023-05-10 11:34:59
6250
修改2023-05-10 11:34:59
举报
文章被收录于专栏:算法协议算法协议

toc

在Golang的代码开发中,我们经常会用到字符串的拼接。Golang提供了不同的字符串拼接方式,性能也不尽相同。有时候在做性能优化的时候,往往会看到有些同学想当然的选择一些自认为性能比较高的方法。但是实际情况是否真的能提升性能呢?我们一起来看一下。

对比较短字符串拼接

代码语言:go
复制
var (
    str1 = "my name is "
    str2 = "zhangSan"
)

func BenchmarkSprintf(b *testing.B) {
    b.ReportAllocs()
    for i := 0; i < b.N; i++ {
        _ = fmt.Sprintf("my name is %s", str2)
    }
}

func BenchmarkAddStr(b *testing.B) {
    b.ReportAllocs()
    for i := 0; i < b.N; i++ {
        _ = str1 + str2
    }
}

func BenchmarkJoin(b *testing.B) {
    b.ReportAllocs()
    slice := []string{str1, str2}
    for i := 0; i < b.N; i++ {
        strings.Join(slice, "")
    }
}

func BenchmarkWriteString(b *testing.B) {
    b.ReportAllocs()

    for i := 0; i < b.N; i++ {
        var bt bytes.Buffer
        bt.WriteString(str1)
        bt.WriteString(str2)
        bt.String()
    }
}

func BenchmarkBuilder(b *testing.B) {
    b.ReportAllocs()

    for i := 0; i < b.N; i++ {
        var builder strings.Builder
        builder.WriteString(str1)
        builder.WriteString(str2)
        builder.String()
    }
}



结果:

BenchmarkSprintf-12          9046708           115.7 ns/op        40 B/op          2 allocs/op
BenchmarkAddStr-12          65630836            18.38 ns/op        0 B/op          0 allocs/op
BenchmarkJoin-12            27375624            42.56 ns/op       24 B/op          1 allocs/op
BenchmarkWriteString-12     24698983            48.77 ns/op       64 B/op          1 allocs/op
BenchmarkBuilder-12         48307612            51.00 ns/op       94 B/op          0 allocs/op

结论

如果字符串很短的情况下,直接使用字符串拼接 比 其他方式 性能高很多。

对比长字符串拼接

代码语言:go
复制
var (
    str1 = "This is a test string This is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test string" +
        "This is a test string This is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test string" +
        "This is a test string This is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test string "
    str2 = "zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan" +
        "zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan" +
        "zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan"
)

结果:

BenchmarkSprintf-12          1848331           617.1 ns/op      1169 B/op          2 allocs/op
BenchmarkAddStr-12           4457694           245.4 ns/op      1152 B/op          1 allocs/op
BenchmarkJoin-12             4750164           233.3 ns/op      1152 B/op          1 allocs/op
BenchmarkWriteString-12      2055642           543.4 ns/op      3520 B/op          3 allocs/op
BenchmarkBuilder-12          3731229           310.9 ns/op      1984 B/op          2 allocs/op

结论

如果字符串较长的情况下,除了sprintf 和WriteString,其他的性能差不多

对比不那么长的字符串拼接

代码语言:go
复制
var (
    str1 = "This is a test string This is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test stringThis is a test string "
    str2 = "zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan zhangSan"
)

结果:

BenchmarkSprintf-12          4700313           270.5 ns/op       368 B/op          2 allocs/op
BenchmarkAddStr-12          14756258            77.44 ns/op      352 B/op          1 allocs/op
BenchmarkJoin-12            14365586            83.16 ns/op      352 B/op          1 allocs/op
BenchmarkWriteString-12      4964223           247.7 ns/op      1120 B/op          3 allocs/op
BenchmarkBuilder-12          9257761           136.3 ns/op       576 B/op          2 allocs/op

结论

不那么长的字符串拼接,除了sprintf 和WriteString,其他的性能差不多

对动态字符串拼接

代码语言:go
复制
var (
	str1 = "my name is "
	//str2 = "zhangSan"
)

func BenchmarkSprintf(b *testing.B) {
	b.ReportAllocs()
	for i := 10000; i < b.N; i++ {
		_ = fmt.Sprintf("my name is %s", strconv.Itoa(i))
	}
}

func BenchmarkAddStr(b *testing.B) {
	b.ReportAllocs()
	for i := 10000; i < b.N; i++ {
		_ = str1 + strconv.Itoa(i)
	}
}

func BenchmarkJoin(b *testing.B) {
	b.ReportAllocs()
	for i := 10000; i < b.N; i++ {
		slice := []string{str1, strconv.Itoa(i)}
		strings.Join(slice, "")
	}
}

func BenchmarkWriteString(b *testing.B) {
	b.ReportAllocs()

	for i := 10000; i < b.N; i++ {
		var bt bytes.Buffer
		bt.WriteString(str1)
		bt.WriteString(strconv.Itoa(i))
		bt.String()
	}
}

func BenchmarkBuilder(b *testing.B) {
	b.ReportAllocs()

	for i := 10000; i < b.N; i++ {
		var builder strings.Builder
		builder.WriteString(str1)
		builder.WriteString(strconv.Itoa(i))
		builder.String()
	}
}

结果:

BenchmarkSprintf-12          7725692           140.8 ns/op        47 B/op          2 allocs/op
BenchmarkAddStr-12          25583774            46.80 ns/op        7 B/op          0 allocs/op
BenchmarkJoin-12            18607413            85.10 ns/op       31 B/op          1 allocs/op
BenchmarkWriteString-12     12217564           108.2 ns/op        71 B/op          1 allocs/op
BenchmarkBuilder-12         12008508            97.00 ns/op       55 B/op          2 allocs/op

结论

依然是,除了sprintf 和WriteString,其他的性能差不多

多次连续拼接M次测试

代码语言:go
复制
var (
    m = 100
)

func BenchmarkSprintf(b *testing.B) {
    b.ReportAllocs()
    for i := 10000; i < b.N; i++ {
        s := ""
        str := strconv.Itoa(i)
        for j := 0; j < m; j++ {
            s = fmt.Sprintf("%s%s", s, str)
        }
    }
}

func BenchmarkAddStr(b *testing.B) {
    b.ReportAllocs()
    for i := 10000; i < b.N; i++ {
        s := ""
        str := strconv.Itoa(i)
        for j := 0; j < m; j++ {
            s += str
        }
    }
}

func BenchmarkJoin(b *testing.B) {
    b.ReportAllocs()
    for i := 10000; i < b.N; i++ {
        s := ""
        str := strconv.Itoa(i)
        for j := 0; j < m; j++ {
            slice := []string{s, str}
            s = strings.Join(slice, "")
        }
    }
}

func BenchmarkWriteString(b *testing.B) {
    b.ReportAllocs()

    for i := 10000; i < b.N; i++ {
        s := ""
        str := strconv.Itoa(i)
        var bt bytes.Buffer
        bt.WriteString(s)
        for j := 0; j < m; j++ {
            bt.WriteString(str)
            s = bt.String()
        }
    }
}

func BenchmarkBuilder(b *testing.B) {
    b.ReportAllocs()

    for i := 10000; i < b.N; i++ {
        s := ""
        str := strconv.Itoa(i)
        var builder strings.Builder
        builder.WriteString(s)
        for j := 0; j < m; j++ {
            builder.WriteString(str)
            s = builder.String()
        }
    }
}


结果:

BenchmarkSprintf-12          1000000         22329 ns/op       34126 B/op        297 allocs/op
BenchmarkAddStr-12           1000000          9804 ns/op       30936 B/op         99 allocs/op
BenchmarkJoin-12             1000000          9315 ns/op       30944 B/op         99 allocs/op
BenchmarkWriteString-12      1000000          7713 ns/op       33042 B/op        104 allocs/op
BenchmarkBuilder-12          1385815           835.4 ns/op      1847 B/op          8 allocs/op

如果我们将m提升到200次呢?

代码语言:go
复制
结果:
BenchmarkSprintf-12          1000000         54355 ns/op      130971 B/op        594 allocs/op
BenchmarkAddStr-12           1000000         32290 ns/op      124485 B/op        198 allocs/op
BenchmarkJoin-12             1000000         41579 ns/op      124492 B/op        198 allocs/op
BenchmarkWriteString-12      1000000         30737 ns/op      128768 B/op        204 allocs/op
BenchmarkBuilder-12          1000000          1635 ns/op        3294 B/op          9 allocs/op

结论

连续大量字符串拼接的时候,使用builder一种方式性能比较好

结论

在不同的使用场景下,每种字符串拼接的方式性能一不定和你想象中的一样。不要想当然的觉得 字符串拼接 性能很差,所以改用其他方式实现。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 对比较短字符串拼接
    • 结论
    • 对比长字符串拼接
      • 结论
      • 对比不那么长的字符串拼接
        • 结论
        • 对动态字符串拼接
          • 结论
          • 多次连续拼接M次测试
          • 结论
          • 结论
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
          http://www.vxiaotou.com