mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 11:07:40 +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:
parent
3216c69d46
commit
43b23f4e6f
16
binary/jce/reflectx.go
Normal file
16
binary/jce/reflectx.go
Normal 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
|
||||
}
|
@ -46,33 +46,64 @@ func (w *JceWriter) WriteBool(b bool, 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)
|
||||
return
|
||||
default:
|
||||
w.putInt16(n, tag)
|
||||
}
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func (w *JceWriter) putInt16(n int16, tag int) {
|
||||
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 {
|
||||
if n >= -32768 && n <= 32767 { // ? if ((n >= 32768) && (n <= 32767))
|
||||
w.WriteInt16(int16(n), tag)
|
||||
return w
|
||||
switch {
|
||||
case n >= -128 && n <= 127:
|
||||
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
|
||||
}
|
||||
|
||||
func (w *JceWriter) WriteInt64(n int64, tag int) *JceWriter {
|
||||
if n >= -2147483648 && n <= 2147483647 {
|
||||
return w.WriteInt32(int32(n), tag)
|
||||
//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 {
|
||||
switch {
|
||||
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
|
||||
}
|
||||
|
||||
//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) {
|
||||
w.writeHead(4, tag)
|
||||
_ = 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) {
|
||||
va := reflect.ValueOf(i)
|
||||
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
|
||||
}
|
||||
w.writeHead(9, tag)
|
||||
if va.Len() == 0 {
|
||||
if slice.Len() == 0 {
|
||||
w.WriteInt32(0, 0)
|
||||
return
|
||||
}
|
||||
w.WriteInt32(int32(va.Len()), 0)
|
||||
for i := 0; i < va.Len(); i++ {
|
||||
v := va.Index(i)
|
||||
w.WriteObject(v.Interface(), 0)
|
||||
w.WriteInt32(int32(slice.Len()), 0)
|
||||
for i := 0; i < slice.Len(); i++ {
|
||||
v := slice.Index(i)
|
||||
w.writeObject(v, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,21 +185,28 @@ func (w *JceWriter) WriteJceStructSlice(l []IJceStruct, 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.WriteInt32(0, 0)
|
||||
return
|
||||
}
|
||||
va := reflect.ValueOf(m)
|
||||
if va.Kind() != reflect.Map {
|
||||
if m.Kind() != reflect.Map {
|
||||
return
|
||||
}
|
||||
w.writeHead(8, tag)
|
||||
w.WriteInt32(int32(va.Len()), 0)
|
||||
iter := va.MapRange()
|
||||
w.WriteInt32(int32(m.Len()), 0)
|
||||
iter := m.MapRange()
|
||||
for iter.Next() {
|
||||
w.WriteObject(iter.Key().Interface(), 0)
|
||||
w.WriteObject(iter.Value().Interface(), 1)
|
||||
w.writeObject(iter.Key(), 0)
|
||||
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 {
|
||||
index int
|
||||
id int
|
||||
@ -241,10 +323,8 @@ func (w *JceWriter) WriteJceStructRaw(s interface{}) {
|
||||
decoderCache.Store(t, jceDec) // 存入缓存
|
||||
}
|
||||
for _, dec := range jceDec {
|
||||
obj := v.Field(dec.index).Interface()
|
||||
if obj != nil {
|
||||
w.WriteObject(obj, dec.id)
|
||||
}
|
||||
obj := v.Field(dec.index)
|
||||
w.writeObject(obj, dec.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user