```
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful

feat(config): 添加超时空地图配置和时间地图查询功能

新增IsTimeSpace字段用于标识地图是否为超时空地图,
添加TimeMap API接口支持查询超时空地图配置

perf(socket): 优化XORDecryptU解密函数减少内存分配

基于bytebufferpool实现缓冲区池化,大幅降低高频调用下的
内存分配和GC压力,提升性能表现

refactor(utils): 优化packVal序列化函数提升性能和稳定性

减少反射开销,
This commit is contained in:
昔念
2026-02-21 16:48:42 +08:00
parent b536f0974e
commit 31d9eb3f9e
6 changed files with 154 additions and 29 deletions

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"math"
"reflect"
"unsafe"
)
type Field struct {
@@ -76,40 +77,60 @@ func (f *Field) Size(val reflect.Value, options *Options) int {
return size
}
// 预定义常用的order避免重复判断
var defaultOrder = binary.BigEndian
// packVal 优化版:减少反射开销+优化内存拷贝+优雅错误处理
func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Options) (size int, err error) {
// 1. 预缓存order避免重复判断
order := f.Order
if options.Order != nil {
if options != nil && options.Order != nil {
order = options.Order
}
if f.Ptr {
val = val.Elem()
if order == nil {
order = defaultOrder
}
// 2. 处理指针类型:提前解引用,避免后续重复操作
if f.Ptr {
if !val.IsNil() {
val = val.Elem()
} else {
return 0, fmt.Errorf("field %s is nil pointer", f.Name)
}
}
// 3. 预解析类型避免重复Resolve
typ := f.Type.Resolve(options)
kind := val.Kind()
// 4. 扁平化分支逻辑,减少嵌套
switch typ {
case Struct:
return f.Fields.Pack(buf, val, options)
case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
size = typ.Size()
if len(buf) < size {
return 0, fmt.Errorf("buf size %d < required %d", len(buf), size)
}
var n uint64
switch f.kind {
switch kind {
case reflect.Bool:
if val.Bool() {
n = 1
} else {
n = 0
}
n = boolToUint64(val.Bool())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n = uint64(val.Int())
default:
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
n = val.Uint()
default:
return 0, fmt.Errorf("unsupported kind %s for numeric type %s", kind, typ)
}
// 扁平化数值写入逻辑
switch typ {
case Bool:
if n != 0 {
buf[0] = 1
} else {
buf[0] = 0
}
buf[0] = byte(n)
case Int8, Uint8:
buf[0] = byte(n)
case Int16, Uint16:
@@ -117,33 +138,90 @@ func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Opti
case Int32, Uint32:
order.PutUint32(buf, uint32(n))
case Int64, Uint64:
order.PutUint64(buf, uint64(n))
order.PutUint64(buf, n)
}
case Float32, Float64:
size = typ.Size()
if len(buf) < size {
return 0, fmt.Errorf("buf size %d < required %d", len(buf), size)
}
if kind != reflect.Float32 && kind != reflect.Float64 {
return 0, fmt.Errorf("unsupported kind %s for float type %s", kind, typ)
}
n := val.Float()
switch typ {
case Float32:
order.PutUint32(buf, math.Float32bits(float32(n)))
case Float64:
order.PutUint64(buf, math.Float64bits(n))
}
case String:
switch f.kind {
// 优化String类型减少内存拷贝
switch kind {
case reflect.String:
s := val.String()
size = len(s)
if len(buf) < size {
return 0, fmt.Errorf("buf size %d < string length %d", len(buf), size)
}
// 用unsafe直接拷贝字符串到buf避免[]byte(s)的内存分配
copyStringToBuf(buf, s)
case reflect.Slice:
if val.Type().Elem().Kind() != reflect.Uint8 {
return 0, fmt.Errorf("unsupported slice type %s for String field", val.Type())
}
size = val.Len()
copy(buf, []byte(val.String()))
default:
// TODO: handle kind != bytes here
size = val.Len()
if len(buf) < size {
return 0, fmt.Errorf("buf size %d < bytes length %d", len(buf), size)
}
// 直接拷贝字节切片,避免冗余操作
copy(buf, val.Bytes())
default:
return 0, fmt.Errorf("unsupported kind %s for String type", kind)
}
case CustomType:
return val.Addr().Interface().(Custom).Pack(buf, options)
// 优化反射断言提前检查类型避免panic
if !val.CanAddr() {
return 0, fmt.Errorf("custom type %s cannot take address", val.Type())
}
custom, ok := val.Addr().Interface().(Custom)
if !ok {
return 0, fmt.Errorf("type %s does not implement Custom interface", val.Type())
}
return custom.Pack(buf, options)
default:
panic(fmt.Sprintf("no pack handler for type: %s", typ))
// 替换panic为error避免程序崩溃
return 0, fmt.Errorf("no pack handler for type: %s", typ)
}
return
return size, nil
}
// 辅助函数bool转uint64减少inline重复代码
func boolToUint64(b bool) uint64 {
if b {
return 1
}
return 0
}
// 辅助函数unsafe拷贝字符串到buf避免[]byte(s)的内存分配
// 注意仅在确定buf长度足够时使用
func copyStringToBuf(buf []byte, s string) {
// unsafe转换字符串转字节切片无内存分配
src := *(*[]byte)(unsafe.Pointer(&struct {
string
cap int
}{s, len(s)}))
copy(buf, src)
}
func (f *Field) Pack(buf []byte, val reflect.Value, length int, options *Options) (int, error) {