gccgo和原生go:判断字符串和byte切片是否相等的性能

使用go1.18版本进行对比。

首先创建 compare_test.go 文件:

package main

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

var result interface{}

func BenchmarkBytesToString(b *testing.B) {

	s1 := []byte("string bytes convert")

	b.ResetTimer()
	b.ReportAllocs()
	var r string
	for n := 0; n < b.N; n++ {
		r = string(s1)
	}
	result = r
}

func BenchmarkStringToBytes(b *testing.B) {

	s1 := "string bytes convert"

	b.ResetTimer()
	b.ReportAllocs()
	var r []byte
	for n := 0; n < b.N; n++ {
		r = []byte(s1)
	}
	result = r
}

func BenchmarkBytesCompareEq(b *testing.B) {

	s1 := []byte("string bytes compare a")
	s2 := []byte("string bytes compare a")

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = bytes.Compare(s1, s2)
	}
	result = r
}

func BenchmarkBytesCompareNeq(b *testing.B) {

	s1 := []byte("string bytes compare a")
	s2 := []byte("string bytes compare b")

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = bytes.Compare(s1, s2)
	}
	result = r
}

func Benchmark10KBytesCompareEq(b *testing.B) {

	var s1, s2 []byte
	for i:=0; i<1024; i++ {
		s1 = append(s1, []byte("abcdefghij")...)
		s2 = append(s2, []byte("abcdefghij")...)
	}

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = bytes.Compare(s1, s2)
	}
	result = r
}

func Benchmark10KBytesCompareNeq(b *testing.B) {

	var s1, s2 []byte
	for i:=0; i<1024; i++ {
		s1 = append(s1, []byte("bacdefghij")...)
		s2 = append(s2, []byte("badcfehgji")...)
	}

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = bytes.Compare(s1, s2)
	}
	result = r
}

func Benchmark10KBytesCompareNeqTail(b *testing.B) {

	var s1, s2 []byte
	for i:=0; i<1024; i++ {
		s1 = append(s1, []byte("abcdefghij")...)
		s2 = append(s2, []byte("abcdefghij")...)
	}
	s2 = append(s2[0:1023], 'k')

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = bytes.Compare(s1, s2)
	}
	result = r
}


func BenchmarkStringCompareEq(b *testing.B) {

	s1 := "string bytes compare a"
	s2 := "string bytes compare a"

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = strings.Compare(s1, s2)
	}
	result = r
}

func BenchmarkStringCompareNeq(b *testing.B) {

	s1 := "string bytes compare a"
	s2 := "string bytes compare b"

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = strings.Compare(s1, s2)
	}
	result = r
}

func Benchmark10KStringCompareEq(b *testing.B) {

	var s1, s2 string
	for i:=0; i<1024; i++ {
		s1 += "abcdefghij"
		s2 += "abcdefghij"
	}

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = strings.Compare(s1, s2)
	}
	result = r
}

func Benchmark10KStringCompareNeq(b *testing.B) {

	var s1, s2 string
	for i:=0; i<1024; i++ {
		s1 += "bacdefghij"
		s2 += "badcfehgji"
	}

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = strings.Compare(s1, s2)
	}
	result = r
}

func Benchmark10KStringCompareNeqTail(b *testing.B) {

	var s1, s2 string
	for i:=0; i<1024; i++ {
		s1 += "abcdefghij"
		s2 += "abcdefghij"
	}
	s2 = s2[0:1023] + "k"

	b.ResetTimer()
	b.ReportAllocs()
	var r int
	for n := 0; n < b.N; n++ {
		r = strings.Compare(s1, s2)
	}
	result = r
}

然后用原生go进行测试:

[xxxx tmp]$ go test -bench=. compare_test.go
goos: linux
goarch: amd64
cpu: Intel(R) Core(TM) i7-5820K CPU @ 3.30GHz
BenchmarkBytesToString-4                50214578                24.18 ns/op           24 B/op          1 allocs/op
BenchmarkStringToBytes-4                38366035                30.74 ns/op           24 B/op          1 allocs/op
BenchmarkBytesCompareEq-4               236118513                5.013 ns/op           0 B/op          0 allocs/op
BenchmarkBytesCompareNeq-4              246910944                4.841 ns/op           0 B/op          0 allocs/op
Benchmark10KBytesCompareEq-4             5201443               229.9 ns/op             0 B/op          0 allocs/op
Benchmark10KBytesCompareNeq-4           258311394                4.555 ns/op           0 B/op          0 allocs/op
Benchmark10KBytesCompareNeqTail-4       47393660                25.12 ns/op            0 B/op          0 allocs/op
BenchmarkStringCompareEq-4              651114916                1.831 ns/op           0 B/op          0 allocs/op
BenchmarkStringCompareNeq-4             100000000               10.06 ns/op            0 B/op          0 allocs/op
Benchmark10KStringCompareEq-4            6436839               186.3 ns/op             0 B/op          0 allocs/op
Benchmark10KStringCompareNeq-4          146472643                8.295 ns/op           0 B/op          0 allocs/op
Benchmark10KStringCompareNeqTail-4      47167117                25.12 ns/op            0 B/op          0 allocs/op
PASS
ok      command-line-arguments  17.252s
[xxxx tmp]$

再用gccgo进行测试:

[xxxx tmp]$ /opt/gcc-14.0.0-20230621-el7-x86_64-go1.18-output/bin/go test -bench=. compare_test.go
goos: linux
goarch: amd64
cpu: Intel(R) Core(TM) i7-5820K CPU @ 3.30GHz
BenchmarkBytesToString-4                19341158                62.55 ns/op           24 B/op          1 allocs/op
BenchmarkStringToBytes-4                14889639                81.64 ns/op           24 B/op          1 allocs/op
BenchmarkBytesCompareEq-4               29715772                39.86 ns/op            0 B/op          0 allocs/op
BenchmarkBytesCompareNeq-4              29307763                38.69 ns/op            0 B/op          0 allocs/op
Benchmark10KBytesCompareEq-4              187540              6304 ns/op               0 B/op          0 allocs/op
Benchmark10KBytesCompareNeq-4           44679166                27.13 ns/op            0 B/op          0 allocs/op
Benchmark10KBytesCompareNeqTail-4        1838538               649.7 ns/op             0 B/op          0 allocs/op
BenchmarkStringCompareEq-4              1000000000               0.0000017 ns/op               0 B/op          0 allocs/op
BenchmarkStringCompareNeq-4             37796344                31.55 ns/op            0 B/op          0 allocs/op
Benchmark10KStringCompareEq-4            4962115               242.0 ns/op             0 B/op          0 allocs/op
Benchmark10KStringCompareNeq-4          49536991                24.06 ns/op            0 B/op          0 allocs/op
Benchmark10KStringCompareNeqTail-4       1842632               643.9 ns/op             0 B/op          0 allocs/op
PASS
ok      command-line-arguments  15.254s
[xxxx tmp]$

结论:

除了对相等的短字符串进行比较gccgo明显快出指数级(怀疑gccgo进行了编译阶段的优化),其他的操作原生go都快于gccgo几倍。

两种go对于byte切片转字符串都快于字符串转byte切片。

对于比较长的内存序列都是不相等的比较快于相等的比较,不相等的位置越靠前越快。

原生go不相等的比较:byte切片快于字符串,gccgo相反:不相等的比较字符串快于byte切片。

综上,如果预判两个内存序列相等就用字符串,如果预判不相等gccgo用字符串、原生go用byte切片。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值