【小实验】golang的if比较中的string/[]byte转换会被编译器优化

之前做了实验,[]byte类型使用string()进行转换的时候,会产生拷贝。see: 【小测试】golang中使用string()来转换[]byte数组产生了拷贝

不过今天又有了新的认识。请先看下面的benchmark测试:

// goos: windows
// goarch: amd64
// pkg: git.woa.com/ahfuzhang/go_proxy/internal
// cpu: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
// BenchmarkStringCompare
// BenchmarkStringCompare-8        15305848                73.45 ns/op
func BenchmarkStringCompare(b *testing.B) {
	buf := make([]byte, 1024)
	for i := 0; i < cap(buf); i++ {
		buf[i] = byte(rand.Intn(125-32) + 32)
	}
	total := 0
	for n := 0; n < b.N; n++ {
		start1 := rand.Intn(len(buf))
		len1 := rand.Intn(len(buf) - start1)
		start2 := rand.Intn(len(buf))
		len2 := rand.Intn(len(buf) - start2)
		if bytes.Compare(buf[start1:start1+len1], buf[start2:start2+len2]) == 0 {
			total++
		}
	}
}

// goos: windows
// goarch: amd64
// pkg: git.woa.com/ahfuzhang/go_proxy/internal
// cpu: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
// BenchmarkStringCompare1
// BenchmarkStringCompare1-8       16340803                69.47 ns/op
func BenchmarkStringCompare1(b *testing.B) {
	buf := make([]byte, 1024)
	for i := 0; i < cap(buf); i++ {
		buf[i] = byte(rand.Intn(125-32) + 32)
	}
	total := 0
	for n := 0; n < b.N; n++ {
		start1 := rand.Intn(len(buf))
		len1 := rand.Intn(len(buf) - start1)
		start2 := rand.Intn(len(buf))
		len2 := rand.Intn(len(buf) - start2)
		if string(buf[start1:start1+len1]) == string(buf[start2:start2+len2]) {
			total++
		}
	}
}

// goos: windows
// goarch: amd64
// pkg: git.woa.com/ahfuzhang/go_proxy/internal
// cpu: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
// BenchmarkStringCompare2
// BenchmarkStringCompare2-8        4692843               263.5 ns/op
func BenchmarkStringCompare2(b *testing.B) {
	buf := make([]byte, 1024)
	for i := 0; i < cap(buf); i++ {
		buf[i] = byte(rand.Intn(125-32) + 32)
	}
	total := 0
	for n := 0; n < b.N; n++ {
		start1 := rand.Intn(len(buf))
		len1 := rand.Intn(len(buf) - start1)
		start2 := rand.Intn(len(buf))
		len2 := rand.Intn(len(buf) - start2)
		s1 := string(buf[start1 : start1+len1])
		s2 := string(buf[start2 : start2+len2])
		if s1 == s2 {
			total++
		}
	}
}

同样是字符串的==比较,在if中直接转换,对于转换赋值后再比较,性能相差几倍。

golang官方库的源码也看到了类似的注释:

//C:\Go\src\bytes\bytes.go
// Equal reports whether a and b
// are the same length and contain the same bytes.
// A nil argument is equivalent to an empty slice.
func Equal(a, b []byte) bool {
	// Neither cmd/compile nor gccgo allocates for these string conversions.
	return string(a) == string(b)
}

看来是编译器对if语句这里的比较做了特殊优化。

posted on 2022-02-10 15:44  ahfuzhang  阅读(305)  评论(0)    收藏  举报