1 回答
TA贡献1876条经验 获得超7个赞
没有什么神秘之处。优化!
package blah
import (
"bytes"
"encoding/binary"
"testing"
)
func BenchmarkByteConversionLeast(t *testing.B) {
var i uint32 = 3419234848
buf := new(bytes.Buffer)
_ = binary.Write(buf, binary.BigEndian, i)
b := buf.Bytes()
for n := 0; n < t.N; n++ {
// Start with least significant bit: 0.27 nanos
value := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[2])<<16 | uint32(b[0])<<24
_ = value
}
}
func BenchmarkByteConversionMost(t *testing.B) {
var i uint32 = 3419234848
buf := new(bytes.Buffer)
_ = binary.Write(buf, binary.BigEndian, i)
b := buf.Bytes()
for n := 0; n < t.N; n++ {
// Start with most significant bit: 0.68 nanos
value := uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
_ = value
}
}
输出:
go test silly_test.go -bench=.
goos: linux
goarch: amd64
BenchmarkByteConversionLeast-4 2000000000 0.72 ns/op
BenchmarkByteConversionMost-4 2000000000 1.80 ns/op
这应该是显而易见的。边界检查消除。
只需使用常识。如果检查索引 3、2、1 和 0 的数组边界,则可以在 3 处停止检查,因为显然 2、1 和 0 也是有效的。如果检查索引 0、1、2 和 3 的数组边界,则必须检查所有索引的边界。一次边界检查与四次边界检查。
您还应该阅读好的代码,例如 Go 标准库。例如,
func (littleEndian) PutUint64(b []byte, v uint64) {
_ = b[7] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
}
- 1 回答
- 0 关注
- 68 浏览
添加回答
举报