lib/encoding: optimize UnmarshalUint* and UnmarshalInt*

This commit is contained in:
Aliaksandr Valialkin 2019-09-20 13:07:59 +03:00
parent a544f49c2b
commit 68722c3c74
2 changed files with 39 additions and 10 deletions

View file

@ -1,6 +1,7 @@
package encoding package encoding
import ( import (
"encoding/binary"
"fmt" "fmt"
"sync" "sync"
) )
@ -12,8 +13,8 @@ func MarshalUint16(dst []byte, u uint16) []byte {
// UnmarshalUint16 returns unmarshaled uint32 from src. // UnmarshalUint16 returns unmarshaled uint32 from src.
func UnmarshalUint16(src []byte) uint16 { func UnmarshalUint16(src []byte) uint16 {
_ = src[1] // This is faster than the manual conversion.
return uint16(src[0])<<8 | uint16(src[1]) return binary.BigEndian.Uint16(src)
} }
// MarshalUint32 appends marshaled v to dst and returns the result. // MarshalUint32 appends marshaled v to dst and returns the result.
@ -23,8 +24,8 @@ func MarshalUint32(dst []byte, u uint32) []byte {
// UnmarshalUint32 returns unmarshaled uint32 from src. // UnmarshalUint32 returns unmarshaled uint32 from src.
func UnmarshalUint32(src []byte) uint32 { func UnmarshalUint32(src []byte) uint32 {
_ = src[3] // This is faster than the manual conversion.
return uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) return binary.BigEndian.Uint32(src)
} }
// MarshalUint64 appends marshaled v to dst and returns the result. // MarshalUint64 appends marshaled v to dst and returns the result.
@ -34,8 +35,8 @@ func MarshalUint64(dst []byte, u uint64) []byte {
// UnmarshalUint64 returns unmarshaled uint64 from src. // UnmarshalUint64 returns unmarshaled uint64 from src.
func UnmarshalUint64(src []byte) uint64 { func UnmarshalUint64(src []byte) uint64 {
_ = src[7] // This is faster than the manual conversion.
return uint64(src[0])<<56 | uint64(src[1])<<48 | uint64(src[2])<<40 | uint64(src[3])<<32 | uint64(src[4])<<24 | uint64(src[5])<<16 | uint64(src[6])<<8 | uint64(src[7]) return binary.BigEndian.Uint64(src)
} }
// MarshalInt16 appends marshaled v to dst and returns the result. // MarshalInt16 appends marshaled v to dst and returns the result.
@ -48,8 +49,8 @@ func MarshalInt16(dst []byte, v int16) []byte {
// UnmarshalInt16 returns unmarshaled int16 from src. // UnmarshalInt16 returns unmarshaled int16 from src.
func UnmarshalInt16(src []byte) int16 { func UnmarshalInt16(src []byte) int16 {
_ = src[1] // This is faster than the manual conversion.
u := uint16(src[0])<<8 | uint16(src[1]) u := binary.BigEndian.Uint16(src)
v := int16(u>>1) ^ (int16(u<<15) >> 15) // zig-zag decoding without branching. v := int16(u>>1) ^ (int16(u<<15) >> 15) // zig-zag decoding without branching.
return v return v
} }
@ -64,8 +65,8 @@ func MarshalInt64(dst []byte, v int64) []byte {
// UnmarshalInt64 returns unmarshaled int64 from src. // UnmarshalInt64 returns unmarshaled int64 from src.
func UnmarshalInt64(src []byte) int64 { func UnmarshalInt64(src []byte) int64 {
_ = src[7] // This is faster than the manual conversion.
u := uint64(src[0])<<56 | uint64(src[1])<<48 | uint64(src[2])<<40 | uint64(src[3])<<32 | uint64(src[4])<<24 | uint64(src[5])<<16 | uint64(src[6])<<8 | uint64(src[7]) u := binary.BigEndian.Uint64(src)
v := int64(u>>1) ^ (int64(u<<63) >> 63) // zig-zag decoding without branching. v := int64(u>>1) ^ (int64(u<<63) >> 63) // zig-zag decoding without branching.
return v return v
} }

View file

@ -6,6 +6,33 @@ import (
"testing" "testing"
) )
func BenchmarkMarshalUint64(b *testing.B) {
b.ReportAllocs()
b.SetBytes(1)
b.RunParallel(func(pb *testing.PB) {
var dst []byte
var sink uint64
for pb.Next() {
dst = MarshalUint64(dst[:0], sink)
sink += uint64(len(dst))
}
atomic.AddUint64(&Sink, sink)
})
}
func BenchmarkUnmarshalUint64(b *testing.B) {
b.ReportAllocs()
b.SetBytes(1)
b.RunParallel(func(pb *testing.PB) {
var sink uint64
for pb.Next() {
v := UnmarshalUint64(testMarshaledUint64Data)
sink += v
}
atomic.AddUint64(&Sink, sink)
})
}
func BenchmarkMarshalInt64(b *testing.B) { func BenchmarkMarshalInt64(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
b.SetBytes(1) b.SetBytes(1)
@ -120,3 +147,4 @@ func benchmarkUnmarshalVarInt64s(b *testing.B, maxValue int64) {
} }
var testMarshaledInt64Data = MarshalInt64(nil, 1234567890) var testMarshaledInt64Data = MarshalInt64(nil, 1234567890)
var testMarshaledUint64Data = MarshalUint64(nil, 1234567890)