侧边栏壁纸
  • 累计撰写 71 篇文章
  • 累计创建 87 个标签
  • 累计收到 5 条评论

目 录CONTENT

文章目录

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

KunkkaWu
2023-05-09 / 0 评论 / 1 点赞 / 6,365 阅读 / 1,540 字 / 正在检测是否收录...

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

对比较短字符串拼接

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

结论

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

对比长字符串拼接

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,其他的性能差不多

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

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,其他的性能差不多

对动态字符串拼接

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次测试

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次呢?


结果:
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一种方式性能比较好

结论

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

1

评论区