mirror of
https://github.com/golang/go
synced 2024-11-13 19:10:22 -07:00
encoding/binary: add a non-reflect fast path for Read
before/after: binary.BenchmarkRead 200000 10860 ns/op binary.BenchmarkRead 500000 2846 ns/op R=rsc CC=golang-dev https://golang.org/cl/4547062
This commit is contained in:
parent
c0decc35ae
commit
3648a03b3a
@ -125,6 +125,54 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
|
||||
// Bytes read from r are decoded using the specified byte order
|
||||
// and written to successive fields of the data.
|
||||
func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
||||
// Fast path for basic types
|
||||
var n int
|
||||
switch data.(type) {
|
||||
case *int8:
|
||||
n = 1
|
||||
case *uint8:
|
||||
n = 1
|
||||
case *int16:
|
||||
n = 2
|
||||
case *uint16:
|
||||
n = 2
|
||||
case *int32:
|
||||
n = 4
|
||||
case *uint32:
|
||||
n = 4
|
||||
case *int64:
|
||||
n = 8
|
||||
case *uint64:
|
||||
n = 8
|
||||
}
|
||||
if n != 0 {
|
||||
var buf [8]byte
|
||||
bs := buf[:n]
|
||||
if _, err := io.ReadFull(r, bs); err != nil {
|
||||
return err
|
||||
}
|
||||
switch v := data.(type) {
|
||||
case *int8:
|
||||
*v = int8(buf[0])
|
||||
case *uint8:
|
||||
*v = buf[0]
|
||||
case *int16:
|
||||
*v = int16(order.Uint16(bs))
|
||||
case *uint16:
|
||||
*v = order.Uint16(bs)
|
||||
case *int32:
|
||||
*v = int32(order.Uint32(bs))
|
||||
case *uint32:
|
||||
*v = order.Uint32(bs)
|
||||
case *int64:
|
||||
*v = int64(order.Uint64(bs))
|
||||
case *uint64:
|
||||
*v = order.Uint64(bs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fallback to reflect-based.
|
||||
var v reflect.Value
|
||||
switch d := reflect.ValueOf(data); d.Kind() {
|
||||
case reflect.Ptr:
|
||||
|
@ -5,6 +5,7 @@
|
||||
package binary
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"bytes"
|
||||
"math"
|
||||
@ -160,3 +161,43 @@ func TestWriteT(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type byteSliceReader struct {
|
||||
remain []byte
|
||||
}
|
||||
|
||||
func (br *byteSliceReader) Read(p []byte) (int, os.Error) {
|
||||
n := copy(p, br.remain)
|
||||
br.remain = br.remain[n:]
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func BenchmarkRead(b *testing.B) {
|
||||
var ls Struct
|
||||
bsr := &byteSliceReader{}
|
||||
var r io.Reader = bsr
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
bsr.remain = big
|
||||
Read(r, BigEndian, &ls.Int8)
|
||||
Read(r, BigEndian, &ls.Int16)
|
||||
Read(r, BigEndian, &ls.Int32)
|
||||
Read(r, BigEndian, &ls.Int64)
|
||||
Read(r, BigEndian, &ls.Uint8)
|
||||
Read(r, BigEndian, &ls.Uint16)
|
||||
Read(r, BigEndian, &ls.Uint32)
|
||||
Read(r, BigEndian, &ls.Uint64)
|
||||
}
|
||||
|
||||
want := s
|
||||
want.Float32 = 0
|
||||
want.Float64 = 0
|
||||
want.Complex64 = 0
|
||||
want.Complex128 = 0
|
||||
for i := range want.Array {
|
||||
want.Array[i] = 0
|
||||
}
|
||||
if !reflect.DeepEqual(ls, want) {
|
||||
panic("no match")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user