Jelajahi Sumber

Optimize 0-length array case

Instead of checking the array length in encode, this can be checked up
front in `encoderOfArray` since the array type has a fixed length
determined at compile time. So return an `emptyArrayEncoder` that simply
writes an empty array to the stream.
Matt Good 7 tahun lalu
induk
melakukan
807e4a8b20
1 mengubah file dengan 17 tambahan dan 4 penghapusan
  1. 17 4
      feature_reflect_array.go

+ 17 - 4
feature_reflect_array.go

@@ -13,6 +13,9 @@ func decoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecod
 }
 
 func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
+	if typ.Len() == 0 {
+		return emptyArrayEncoder{}
+	}
 	encoder := encoderOfType(cfg, prefix+"[array]->", typ.Elem())
 	if typ.Elem().Kind() == reflect.Map {
 		encoder = &OptionalEncoder{encoder}
@@ -20,6 +23,20 @@ func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncod
 	return &arrayEncoder{typ, typ.Elem(), encoder}
 }
 
+type emptyArrayEncoder struct{}
+
+func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
+	stream.WriteEmptyArray()
+}
+
+func (encoder emptyArrayEncoder) EncodeInterface(val interface{}, stream *Stream) {
+	stream.WriteEmptyArray()
+}
+
+func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
+	return true
+}
+
 type arrayEncoder struct {
 	arrayType   reflect.Type
 	elemType    reflect.Type
@@ -27,10 +44,6 @@ type arrayEncoder struct {
 }
 
 func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
-	if encoder.arrayType.Len() == 0 {
-		stream.WriteEmptyArray()
-		return
-	}
 	stream.WriteArrayStart()
 	elemPtr := unsafe.Pointer(ptr)
 	encoder.elemEncoder.Encode(elemPtr, stream)