1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 19:17:38 +08:00

jce: speed up write

name                           old time/op    new time/op    delta
JceWriter_WriteMap-8             2.46µs ± 1%    2.37µs ± 1%   -3.88%  (p=0.000 n=9+9)
JceWriter_WriteJceStructRaw-8    1.78µs ± 1%    1.29µs ± 1%  -27.38%  (p=0.000 n=9+10)

name                           old speed      new speed      delta
JceWriter_WriteMap-8           37.7MB/s ± 1%  39.3MB/s ± 1%   +4.04%  (p=0.000 n=9+9)
JceWriter_WriteJceStructRaw-8  59.0MB/s ± 1%  81.3MB/s ± 1%  +37.70%  (p=0.000 n=9+10)

name                           old alloc/op   new alloc/op   delta
JceWriter_WriteMap-8             1.30kB ± 0%    1.30kB ± 0%     ~     (all equal)
JceWriter_WriteJceStructRaw-8      724B ± 0%      640B ± 0%  -11.60%  (p=0.000 n=10+10)

name                           old allocs/op  new allocs/op  delta
JceWriter_WriteMap-8               30.0 ± 0%      30.0 ± 0%     ~     (all equal)
JceWriter_WriteJceStructRaw-8      29.0 ± 0%      15.0 ± 0%  -48.28%  (p=0.000 n=10+10)
This commit is contained in:
wdvxdr 2021-11-20 11:34:42 +08:00
parent 3216c69d46
commit 43b23f4e6f
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
2 changed files with 124 additions and 28 deletions

16
binary/jce/reflectx.go Normal file
View File

@ -0,0 +1,16 @@
package jce
import (
"reflect"
"unsafe"
)
type value struct {
typ unsafe.Pointer
data unsafe.Pointer
flag uintptr
}
func pointerOf(v reflect.Value) unsafe.Pointer {
return (*value)(unsafe.Pointer(&v)).data
}

View File

@ -46,33 +46,64 @@ func (w *JceWriter) WriteBool(b bool, tag int) {
} }
func (w *JceWriter) WriteInt16(n int16, tag int) { func (w *JceWriter) WriteInt16(n int16, tag int) {
if n >= -128 && n <= 127 { switch {
case n >= -128 && n <= 127:
w.WriteByte(byte(n), tag) w.WriteByte(byte(n), tag)
return default:
w.putInt16(n, tag)
} }
}
//go:nosplit
func (w *JceWriter) putInt16(n int16, tag int) {
w.writeHead(1, tag) w.writeHead(1, tag)
_ = goBinary.Write(w.buf, goBinary.BigEndian, n) var buf [2]byte
goBinary.BigEndian.PutUint16(buf[:], uint16(n))
w.buf.Write(buf[:])
} }
func (w *JceWriter) WriteInt32(n int32, tag int) *JceWriter { func (w *JceWriter) WriteInt32(n int32, tag int) *JceWriter {
if n >= -32768 && n <= 32767 { // ? if ((n >= 32768) && (n <= 32767)) switch {
w.WriteInt16(int16(n), tag) case n >= -128 && n <= 127:
return w w.WriteByte(byte(n), tag)
case n >= -32768 && n <= 32767:
w.putInt16(int16(n), tag)
default:
w.putInt32(n, tag)
} }
w.writeHead(2, tag)
_ = goBinary.Write(w.buf, goBinary.BigEndian, n)
return w return w
} }
//go:nosplit
func (w *JceWriter) putInt32(n int32, tag int) {
w.writeHead(2, tag)
var buf [4]byte
goBinary.BigEndian.PutUint32(buf[:], uint32(n))
w.buf.Write(buf[:])
}
func (w *JceWriter) WriteInt64(n int64, tag int) *JceWriter { func (w *JceWriter) WriteInt64(n int64, tag int) *JceWriter {
if n >= -2147483648 && n <= 2147483647 { switch {
return w.WriteInt32(int32(n), tag) case n >= -128 && n <= 127:
w.WriteByte(byte(n), tag)
case n >= -32768 && n <= 32767:
w.putInt16(int16(n), tag)
case n >= -2147483648 && n <= 2147483647:
w.putInt32(int32(n), tag)
default:
w.putInt64(n, tag)
} }
w.writeHead(3, tag)
_ = goBinary.Write(w.buf, goBinary.BigEndian, n)
return w return w
} }
//go:nosplit
func (w *JceWriter) putInt64(n int64, tag int) {
w.writeHead(3, tag)
var buf [8]byte
goBinary.BigEndian.PutUint64(buf[:], uint64(n))
w.buf.Write(buf[:])
}
func (w *JceWriter) WriteFloat32(n float32, tag int) { func (w *JceWriter) WriteFloat32(n float32, tag int) {
w.writeHead(4, tag) w.writeHead(4, tag)
_ = goBinary.Write(w.buf, goBinary.BigEndian, n) _ = goBinary.Write(w.buf, goBinary.BigEndian, n)
@ -120,17 +151,24 @@ func (w *JceWriter) WriteInt64Slice(l []int64, tag int) {
func (w *JceWriter) WriteSlice(i interface{}, tag int) { func (w *JceWriter) WriteSlice(i interface{}, tag int) {
va := reflect.ValueOf(i) va := reflect.ValueOf(i)
if va.Kind() != reflect.Slice { if va.Kind() != reflect.Slice {
panic("JceWriter.WriteSlice: not a slice")
}
w.writeSlice(va, tag)
}
func (w *JceWriter) writeSlice(slice reflect.Value, tag int) {
if slice.Kind() != reflect.Slice {
return return
} }
w.writeHead(9, tag) w.writeHead(9, tag)
if va.Len() == 0 { if slice.Len() == 0 {
w.WriteInt32(0, 0) w.WriteInt32(0, 0)
return return
} }
w.WriteInt32(int32(va.Len()), 0) w.WriteInt32(int32(slice.Len()), 0)
for i := 0; i < va.Len(); i++ { for i := 0; i < slice.Len(); i++ {
v := va.Index(i) v := slice.Index(i)
w.WriteObject(v.Interface(), 0) w.writeObject(v, 0)
} }
} }
@ -147,21 +185,28 @@ func (w *JceWriter) WriteJceStructSlice(l []IJceStruct, tag int) {
} }
func (w *JceWriter) WriteMap(m interface{}, tag int) { func (w *JceWriter) WriteMap(m interface{}, tag int) {
if m == nil { va := reflect.ValueOf(m)
if va.Kind() != reflect.Map {
panic("JceWriter.WriteMap: not a map")
}
w.writeMap(va, tag)
}
func (w *JceWriter) writeMap(m reflect.Value, tag int) {
if m.IsNil() {
w.writeHead(8, tag) w.writeHead(8, tag)
w.WriteInt32(0, 0) w.WriteInt32(0, 0)
return return
} }
va := reflect.ValueOf(m) if m.Kind() != reflect.Map {
if va.Kind() != reflect.Map {
return return
} }
w.writeHead(8, tag) w.writeHead(8, tag)
w.WriteInt32(int32(va.Len()), 0) w.WriteInt32(int32(m.Len()), 0)
iter := va.MapRange() iter := m.MapRange()
for iter.Next() { for iter.Next() {
w.WriteObject(iter.Key().Interface(), 0) w.writeObject(iter.Key(), 0)
w.WriteObject(iter.Value().Interface(), 1) w.writeObject(iter.Value(), 1)
} }
} }
@ -201,6 +246,43 @@ func (w *JceWriter) WriteObject(i interface{}, tag int) {
} }
} }
func (w *JceWriter) writeObject(v reflect.Value, tag int) {
k := v.Kind()
if k == reflect.Map {
w.writeMap(v, tag)
return
}
if k == reflect.Slice {
if v.Type().Elem().Kind() == reflect.Uint8 {
w.WriteBytes(v.Bytes(), tag)
return
}
w.writeSlice(v, tag)
return
}
switch k {
case reflect.Uint8, reflect.Int8:
w.WriteByte(*(*byte)(pointerOf(v)), tag)
case reflect.Uint16, reflect.Int16:
w.WriteInt16(*(*int16)(pointerOf(v)), tag)
case reflect.Uint32, reflect.Int32:
w.WriteInt32(*(*int32)(pointerOf(v)), tag)
case reflect.Uint64, reflect.Int64:
w.WriteInt64(*(*int64)(pointerOf(v)), tag)
case reflect.String:
w.WriteString(v.String(), tag)
default:
switch o := v.Interface().(type) {
case IJceStruct:
w.WriteJceStruct(o, tag)
case float32:
w.WriteFloat32(o, tag)
case float64:
w.WriteFloat64(o, tag)
}
}
}
type decoder struct { type decoder struct {
index int index int
id int id int
@ -241,10 +323,8 @@ func (w *JceWriter) WriteJceStructRaw(s interface{}) {
decoderCache.Store(t, jceDec) // 存入缓存 decoderCache.Store(t, jceDec) // 存入缓存
} }
for _, dec := range jceDec { for _, dec := range jceDec {
obj := v.Field(dec.index).Interface() obj := v.Field(dec.index)
if obj != nil { w.writeObject(obj, dec.id)
w.WriteObject(obj, dec.id)
}
} }
} }