Using
LittleEndian.PutUint64
function fromencoding/binary
package is much faster than bit shifting.
0.3468n/op
vs3.905n/op
import "encoding/binary"
// Uint64ToBytes converts the given uint64 value to slice of bytes.
func Uint64ToBytes(val uint64) []byte {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, val)
return b
}
// Ordinary way using bit shifting
func convA(val uint64) []byte {
r := make([]byte, 8)
for i := uint64(0); i < 8; i++ {
r[i] = byte((val >> (i * 8)) & 0xff)
}
return r
}
// Use `encoding/binary` package
func convB(val uint64) []byte {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, val)
return b
}
func Test_is_equal(t *testing.T) {
val := uint64(1234567890)
byteValA := convA(val)
byteValB := convB(val)
require.Equal(t, byteValA, byteValB)
}
func Benchmark_conv(b *testing.B) {
const val = uint64(1234567890)
b.Run("convA", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = convA(val)
}
})
b.Run("convB", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = convB(val)
}
})
}
$ go test -run=^$ -benchmem -bench ^Benchmark_conv$ -count 10 ./... > bench.txt
$ benchstat bench.txt
goos: darwin
goarch: amd64
pkg: example/uint64tobytes
cpu: Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
│ bench.txt │
│ sec/op │
_conv/convA-4 3.905n ± 6%
_conv/convB-4 0.3468n ± 1%
geomean 1.164n
│ bench.txt │
│ B/op │
_conv/convA-4 0.000 ± 0%
_conv/convB-4 0.000 ± 0%
geomean ¹
¹ summaries must be >0 to compute geomean
│ bench.txt │
│ allocs/op │
_conv/convA-4 0.000 ± 0%
_conv/convB-4 0.000 ± 0%
geomean ¹
¹ summaries must be >0 to compute geomean
- Env info:
- macOS Monterey (12.6.5, darwin/amd64)
- Go v1.20.3