From 90a1f237f1b4dbc8f97d2ea363da3298c179cf51 Mon Sep 17 00:00:00 2001 From: PAN <1162953505@qq.com> Date: Sun, 14 Sep 2025 17:37:32 +0800 Subject: [PATCH 1/2] perf(go): fix xlang slice type --- go/fory/slice.go | 318 ++++++++++++++++++++++++++++++++++++++++++++++- go/fory/type.go | 53 +++++++- 2 files changed, 364 insertions(+), 7 deletions(-) diff --git a/go/fory/slice.go b/go/fory/slice.go index ccd9d4b11e..6a171cdc41 100644 --- a/go/fory/slice.go +++ b/go/fory/slice.go @@ -439,11 +439,327 @@ func (o *ByteSliceBufferObject) ToBuffer() *ByteBuffer { return NewByteBuffer(o.data) } +type boolArraySerializer struct { +} + +func (s boolArraySerializer) TypeId() TypeId { + return BOOL_ARRAY +} + +func (s boolArraySerializer) NeedWriteRef() bool { + return true +} + +func (s boolArraySerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) error { + v := value.Interface().([]bool) + size := len(v) + if size >= MaxInt32 { + return fmt.Errorf("too long slice: %d", len(v)) + } + buf.WriteLength(size) + for _, elem := range v { + buf.WriteBool(elem) + } + return nil +} + +func (s boolArraySerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error { + length := buf.ReadLength() + var r reflect.Value + switch type_.Kind() { + case reflect.Slice: + r = reflect.MakeSlice(type_, length, length) + case reflect.Array: + if length != type_.Len() { + return fmt.Errorf("length %d does not match array type %v", length, type_) + } + r = reflect.New(type_).Elem() + default: + return fmt.Errorf("unsupported kind %v, want slice/array", type_.Kind()) + } + for i := 0; i < length; i++ { + r.Index(i).SetBool(buf.ReadBool()) + } + value.Set(r) + return nil +} + +type int8ArraySerializer struct { +} + +func (s int8ArraySerializer) TypeId() TypeId { + return INT8_ARRAY +} + +func (s int8ArraySerializer) NeedWriteRef() bool { + return true +} + +func (s int8ArraySerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) error { + v := value.Interface().([]int8) + size := len(v) + if size >= MaxInt32 { + return fmt.Errorf("too long slice: %d", len(v)) + } + buf.WriteLength(size) + for _, elem := range v { + buf.WriteByte_(byte(elem)) + } + return nil +} + +func (s int8ArraySerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error { + length := buf.ReadLength() + var r reflect.Value + switch type_.Kind() { + case reflect.Slice: + r = reflect.MakeSlice(type_, length, length) + case reflect.Array: + if length != type_.Len() { + return fmt.Errorf("length %d does not match array type %v", length, type_) + } + r = reflect.New(type_).Elem() + default: + return fmt.Errorf("unsupported kind %v, want slice/array", type_.Kind()) + } + for i := 0; i < length; i++ { + r.Index(i).SetInt(int64(int8(buf.ReadByte_()))) + } + value.Set(r) + return nil +} + +type int16ArraySerializer struct { +} + +func (s int16ArraySerializer) TypeId() TypeId { + return INT16_ARRAY +} + +func (s int16ArraySerializer) NeedWriteRef() bool { + return true +} + +func (s int16ArraySerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) error { + v := value.Interface().([]int16) + size := len(v) * 2 + if size >= MaxInt32 { + return fmt.Errorf("too long slice: %d", len(v)) + } + buf.WriteLength(size) + for _, elem := range v { + buf.WriteInt16(elem) + } + return nil +} + +func (s int16ArraySerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error { + length := buf.ReadLength() / 2 + var r reflect.Value + switch type_.Kind() { + case reflect.Slice: + r = reflect.MakeSlice(type_, length, length) + case reflect.Array: + if length != type_.Len() { + return fmt.Errorf("length %d does not match array type %v", length, type_) + } + r = reflect.New(type_).Elem() + default: + return fmt.Errorf("unsupported kind %v, want slice/array", type_.Kind()) + } + for i := 0; i < length; i++ { + r.Index(i).SetInt(int64(buf.ReadInt16())) + } + value.Set(r) + return nil +} + +type int32ArraySerializer struct { +} + +func (s int32ArraySerializer) TypeId() TypeId { + return INT32_ARRAY +} + +func (s int32ArraySerializer) NeedWriteRef() bool { + return true +} + +func (s int32ArraySerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) error { + v := value.Interface().([]int32) + size := len(v) * 4 + if size >= MaxInt32 { + return fmt.Errorf("too long slice: %d", len(v)) + } + buf.WriteLength(size) + for _, elem := range v { + buf.WriteInt32(elem) + } + return nil +} + +func (s int32ArraySerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error { + length := buf.ReadLength() / 4 + var r reflect.Value + switch type_.Kind() { + case reflect.Slice: + r = reflect.MakeSlice(type_, length, length) + case reflect.Array: + if length != type_.Len() { + return fmt.Errorf("length %d does not match array type %v", length, type_) + } + r = reflect.New(type_).Elem() + default: + return fmt.Errorf("unsupported kind %v, want slice/array", type_.Kind()) + } + for i := 0; i < length; i++ { + r.Index(i).SetInt(int64(buf.ReadInt32())) + } + value.Set(r) + return nil +} + +type int64ArraySerializer struct { +} + +func (s int64ArraySerializer) TypeId() TypeId { + return INT64_ARRAY +} + +func (s int64ArraySerializer) NeedWriteRef() bool { + return true +} + +func (s int64ArraySerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) error { + v := value.Interface().([]int64) + size := len(v) * 8 + if size >= MaxInt32 { + return fmt.Errorf("too long slice: %d", len(v)) + } + buf.WriteLength(size) + for _, elem := range v { + buf.WriteInt64(elem) + } + return nil +} + +func (s int64ArraySerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error { + length := buf.ReadLength() / 8 + var r reflect.Value + switch type_.Kind() { + case reflect.Slice: + r = reflect.MakeSlice(type_, length, length) + case reflect.Array: + if length != type_.Len() { + return fmt.Errorf("length %d does not match array type %v", length, type_) + } + r = reflect.New(type_).Elem() + default: + return fmt.Errorf("unsupported kind %v, want slice/array", type_.Kind()) + } + for i := 0; i < length; i++ { + r.Index(i).SetInt(buf.ReadInt64()) + } + value.Set(r) + return nil +} + +type float32ArraySerializer struct { +} + +func (s float32ArraySerializer) TypeId() TypeId { + return FLOAT32_ARRAY +} + +func (s float32ArraySerializer) NeedWriteRef() bool { + return true +} + +func (s float32ArraySerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) error { + v := value.Interface().([]float32) + size := len(v) * 4 + if size >= MaxInt32 { + return fmt.Errorf("too long slice: %d", len(v)) + } + buf.WriteLength(size) + for _, elem := range v { + buf.WriteFloat32(elem) + } + return nil +} + +func (s float32ArraySerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error { + length := buf.ReadLength() / 4 + var r reflect.Value + switch type_.Kind() { + case reflect.Slice: + r = reflect.MakeSlice(type_, length, length) + case reflect.Array: + if length != type_.Len() { + return fmt.Errorf("length %d does not match array type %v", length, type_) + } + r = reflect.New(type_).Elem() + default: + return fmt.Errorf("unsupported kind %v, want slice/array", type_.Kind()) + } + for i := 0; i < length; i++ { + r.Index(i).SetFloat(float64(buf.ReadFloat32())) + } + value.Set(r) + return nil +} + +type float64ArraySerializer struct { +} + +func (s float64ArraySerializer) TypeId() TypeId { + return FLOAT64_ARRAY +} + +func (s float64ArraySerializer) NeedWriteRef() bool { + return true +} + +func (s float64ArraySerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) error { + v := value.Interface().([]float64) + size := len(v) * 8 + if size >= MaxInt32 { + return fmt.Errorf("too long slice: %d", len(v)) + } + buf.WriteLength(size) + for _, elem := range v { + buf.WriteFloat64(elem) + } + return nil +} + +func (s float64ArraySerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, value reflect.Value) error { + length := buf.ReadLength() / 8 + var r reflect.Value + switch type_.Kind() { + case reflect.Slice: + r = reflect.MakeSlice(type_, length, length) + case reflect.Array: + if length != type_.Len() { + return fmt.Errorf("length %d does not match array type %v", length, type_) + } + r = reflect.New(type_).Elem() + default: + return fmt.Errorf("unsupported kind %v, want slice/array", type_.Kind()) + } + for i := 0; i < length; i++ { + r.Index(i).SetFloat(buf.ReadFloat64()) + } + value.Set(r) + return nil +} + +// Legacy slice serializers - kept for backward compatibility but not used for xlang type boolSliceSerializer struct { } func (s boolSliceSerializer) TypeId() TypeId { - return BOOL_ARRAY + return BOOL_ARRAY // Use legacy type ID to avoid conflicts } func (s boolSliceSerializer) NeedWriteRef() bool { diff --git a/go/fory/type.go b/go/fory/type.go index 8ce94417e4..b9356fe4be 100644 --- a/go/fory/type.go +++ b/go/fory/type.go @@ -203,6 +203,7 @@ var ( stringSliceType = reflect.TypeOf((*[]string)(nil)).Elem() byteSliceType = reflect.TypeOf((*[]byte)(nil)).Elem() boolSliceType = reflect.TypeOf((*[]bool)(nil)).Elem() + int8SliceType = reflect.TypeOf((*[]int8)(nil)).Elem() int16SliceType = reflect.TypeOf((*[]int16)(nil)).Elem() int32SliceType = reflect.TypeOf((*[]int32)(nil)).Elem() int64SliceType = reflect.TypeOf((*[]int64)(nil)).Elem() @@ -421,12 +422,13 @@ func (r *typeResolver) initialize() { {stringPtrType, ptrToStringSerializer{}}, {stringSliceType, stringSliceSerializer{}}, {byteSliceType, byteSliceSerializer{}}, - {boolSliceType, boolSliceSerializer{}}, - {int16SliceType, int16SliceSerializer{}}, - {int32SliceType, int32SliceSerializer{}}, - {int64SliceType, int64SliceSerializer{}}, - {float32SliceType, float32SliceSerializer{}}, - {float64SliceType, float64SliceSerializer{}}, + // Map basic type slices to proper array types for xlang compatibility + {boolSliceType, boolArraySerializer{}}, + {int16SliceType, int16ArraySerializer{}}, + {int32SliceType, int32ArraySerializer{}}, + {int64SliceType, int64ArraySerializer{}}, + {float32SliceType, float32ArraySerializer{}}, + {float64SliceType, float64ArraySerializer{}}, {interfaceSliceType, sliceSerializer{}}, {interfaceMapType, mapSerializer{}}, {boolType, boolSerializer{}}, @@ -821,6 +823,45 @@ func (r *typeResolver) createSerializer(type_ reflect.Type, mapInStruct bool) (s return &ptrToValueSerializer{valueSerializer}, nil case reflect.Slice: elem := type_.Elem() + // Handle special slice types for xlang compatibility + if r.language == XLANG { + // Basic type slices should use array types for efficiency + switch elem.Kind() { + case reflect.Bool: + if type_ == boolSliceType { + return boolArraySerializer{}, nil + } + case reflect.Int8: + if type_ == int8SliceType { + return int8ArraySerializer{}, nil + } + case reflect.Int16: + if type_ == int16SliceType { + return int16ArraySerializer{}, nil + } + case reflect.Int32: + if type_ == int32SliceType { + return int32ArraySerializer{}, nil + } + case reflect.Int64: + if type_ == int64SliceType { + return int64ArraySerializer{}, nil + } + case reflect.Float32: + if type_ == float32SliceType { + return float32ArraySerializer{}, nil + } + case reflect.Float64: + if type_ == float64SliceType { + return float64ArraySerializer{}, nil + } + case reflect.Int, reflect.Uint: + // Platform-dependent types should use LIST for cross-platform compatibility + // We treat them as dynamic types to force LIST serialization + return sliceSerializer{}, nil + } + } + // For dynamic types or non-xlang mode, use generic slice serializer if isDynamicType(elem) { return sliceSerializer{}, nil } else { From c1586f80b75d593c426d5bb4434e88100c1af459 Mon Sep 17 00:00:00 2001 From: PAN <1162953505@qq.com> Date: Sun, 14 Sep 2025 17:38:35 +0800 Subject: [PATCH 2/2] perf(go): fix xlang slice type --- go/fory/type.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/fory/type.go b/go/fory/type.go index b9356fe4be..7817a4a337 100644 --- a/go/fory/type.go +++ b/go/fory/type.go @@ -424,7 +424,7 @@ func (r *typeResolver) initialize() { {byteSliceType, byteSliceSerializer{}}, // Map basic type slices to proper array types for xlang compatibility {boolSliceType, boolArraySerializer{}}, - {int16SliceType, int16ArraySerializer{}}, + {int16SliceType, int16ArraySerializer{}}, {int32SliceType, int32ArraySerializer{}}, {int64SliceType, int64ArraySerializer{}}, {float32SliceType, float32ArraySerializer{}},