mirror of
https://github.com/golang/go
synced 2024-11-21 20:04:44 -07:00
encoding/binary: add a non-reflect fast path for Write
before/after: binary.BenchmarkWrite 100000 18312 ns/op binary.BenchmarkWrite 500000 4468 ns/op R=rsc, gri CC=golang-dev https://golang.org/cl/4515154
This commit is contained in:
parent
3b980579b4
commit
f7a266a5aa
@ -125,37 +125,18 @@ 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]
|
||||
// Fast path for basic types.
|
||||
if n := intDestSize(data); n != 0 {
|
||||
var b [8]byte
|
||||
bs := b[:n]
|
||||
if _, err := io.ReadFull(r, bs); err != nil {
|
||||
return err
|
||||
}
|
||||
switch v := data.(type) {
|
||||
case *int8:
|
||||
*v = int8(buf[0])
|
||||
*v = int8(b[0])
|
||||
case *uint8:
|
||||
*v = buf[0]
|
||||
*v = b[0]
|
||||
case *int16:
|
||||
*v = int16(order.Uint16(bs))
|
||||
case *uint16:
|
||||
@ -203,6 +184,63 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
||||
// Bytes written to w are encoded using the specified byte order
|
||||
// and read from successive fields of the data.
|
||||
func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
|
||||
// Fast path for basic types.
|
||||
var b [8]byte
|
||||
var bs []byte
|
||||
switch v := data.(type) {
|
||||
case *int8:
|
||||
bs = b[:1]
|
||||
b[0] = byte(*v)
|
||||
case int8:
|
||||
bs = b[:1]
|
||||
b[0] = byte(v)
|
||||
case *uint8:
|
||||
bs = b[:1]
|
||||
b[0] = *v
|
||||
case uint8:
|
||||
bs = b[:1]
|
||||
b[0] = byte(v)
|
||||
case *int16:
|
||||
bs = b[:2]
|
||||
order.PutUint16(bs, uint16(*v))
|
||||
case int16:
|
||||
bs = b[:2]
|
||||
order.PutUint16(bs, uint16(v))
|
||||
case *uint16:
|
||||
bs = b[:2]
|
||||
order.PutUint16(bs, *v)
|
||||
case uint16:
|
||||
bs = b[:2]
|
||||
order.PutUint16(bs, v)
|
||||
case *int32:
|
||||
bs = b[:4]
|
||||
order.PutUint32(bs, uint32(*v))
|
||||
case int32:
|
||||
bs = b[:4]
|
||||
order.PutUint32(bs, uint32(v))
|
||||
case *uint32:
|
||||
bs = b[:4]
|
||||
order.PutUint32(bs, *v)
|
||||
case uint32:
|
||||
bs = b[:4]
|
||||
order.PutUint32(bs, v)
|
||||
case *int64:
|
||||
bs = b[:8]
|
||||
order.PutUint64(bs, uint64(*v))
|
||||
case int64:
|
||||
bs = b[:8]
|
||||
order.PutUint64(bs, uint64(v))
|
||||
case *uint64:
|
||||
bs = b[:8]
|
||||
order.PutUint64(bs, *v)
|
||||
case uint64:
|
||||
bs = b[:8]
|
||||
order.PutUint64(bs, v)
|
||||
}
|
||||
if bs != nil {
|
||||
_, err := w.Write(bs)
|
||||
return err
|
||||
}
|
||||
v := reflect.Indirect(reflect.ValueOf(data))
|
||||
size := TotalSize(v)
|
||||
if size < 0 {
|
||||
@ -442,3 +480,19 @@ func (e *encoder) value(v reflect.Value) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// intDestSize returns the size of the integer that ptrType points to,
|
||||
// or 0 if the type is not supported.
|
||||
func intDestSize(ptrType interface{}) int {
|
||||
switch ptrType.(type) {
|
||||
case *int8, *uint8:
|
||||
return 1
|
||||
case *int16, *uint16:
|
||||
return 2
|
||||
case *int32, *uint32:
|
||||
return 4
|
||||
case *int64, *uint64:
|
||||
return 8
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
@ -201,3 +201,35 @@ func BenchmarkRead(b *testing.B) {
|
||||
panic("no match")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWrite(b *testing.B) {
|
||||
buf := new(bytes.Buffer)
|
||||
var w io.Writer = buf
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf.Reset()
|
||||
Write(w, BigEndian, &s.Int8)
|
||||
Write(w, BigEndian, &s.Int16)
|
||||
Write(w, BigEndian, &s.Int32)
|
||||
Write(w, BigEndian, &s.Int64)
|
||||
Write(w, BigEndian, &s.Uint8)
|
||||
Write(w, BigEndian, &s.Uint16)
|
||||
Write(w, BigEndian, &s.Uint32)
|
||||
Write(w, BigEndian, &s.Uint64)
|
||||
Write(w, BigEndian, s.Int8)
|
||||
Write(w, BigEndian, s.Int16)
|
||||
Write(w, BigEndian, s.Int32)
|
||||
Write(w, BigEndian, s.Int64)
|
||||
Write(w, BigEndian, s.Uint8)
|
||||
Write(w, BigEndian, s.Uint16)
|
||||
Write(w, BigEndian, s.Uint32)
|
||||
Write(w, BigEndian, s.Uint64)
|
||||
}
|
||||
|
||||
if !bytes.Equal(buf.Bytes()[:30], big[:30]) {
|
||||
panic("first half doesn't match")
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes()[30:], big[:30]) {
|
||||
panic("second half doesn't match")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user