From 07f0438435cce85465dc0da0a6d870a6e3daf08d Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Mon, 14 Feb 2022 19:31:32 +0800 Subject: [PATCH] Add sync.Pool --- scan.go | 8 +++++--- schema/field.go | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/scan.go b/scan.go index e8ab805e..fa1b4caa 100644 --- a/scan.go +++ b/scan.go @@ -55,11 +55,13 @@ func (db *DB) scanIntoStruct(sch *schema.Schema, rows *sql.Rows, reflectValue re if sch == nil { values[idx] = reflectValue.Interface() } else if field := sch.LookUpField(column); field != nil && field.Readable { - values[idx] = reflect.New(reflect.PtrTo(field.IndirectFieldType)).Interface() - } else if names := strings.Split(column, "__"); len(names) > 1 { + values[idx] = field.NewScanValue() + defer field.ReleaseScanValue(values[idx]) + } else if names := strings.Split(column, "__"); len(names) > 2 { if rel, ok := sch.Relationships.Relations[names[0]]; ok { if field := rel.FieldSchema.LookUpField(strings.Join(names[1:], "__")); field != nil && field.Readable { - values[idx] = reflect.New(reflect.PtrTo(field.IndirectFieldType)).Interface() + values[idx] = field.NewScanValue() + defer field.ReleaseScanValue(values[idx]) continue } } diff --git a/schema/field.go b/schema/field.go index 85f737b5..7ecf0761 100644 --- a/schema/field.go +++ b/schema/field.go @@ -84,6 +84,8 @@ type Field struct { ReflectValueOf func(context.Context, reflect.Value) reflect.Value ValueOf func(context.Context, reflect.Value) (value interface{}, zero bool) Set func(context.Context, reflect.Value, interface{}) error + NewScanValue func() interface{} + ReleaseScanValue func(interface{}) } // ParseField parses reflect.StructField to Field @@ -412,13 +414,39 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { return field } +var ( + bytesPool = sync.Pool{ + New: func() interface{} { + bs := make([]byte, 0, 10) + return &bs + }, + } + bytesPoolReleaser = func(v interface{}) { + bs := v.(*[]byte) + *bs = (*bs)[:0] + if string(*bs) != "" { + fmt.Println(string(*bs)) + } + bytesPool.Put(bs) + } +) + // create valuer, setter when parse struct func (field *Field) setupValuerAndSetter() { - // ValueOf returns field's value and if it is zero + // Setup NewScanValue + switch field.DataType { + case Bytes, String: + field.NewScanValue = bytesPool.Get + field.ReleaseScanValue = bytesPoolReleaser + default: + field.NewScanValue = func() interface{} { + return reflect.New(reflect.PtrTo(field.IndirectFieldType)).Interface() + } + field.ReleaseScanValue = func(interface{}) { + } + } - // if vr, ok := fv.(GormFieldValuer); ok { - // fv, zero = vr.GormFieldValue(ctx, field) - // } + // ValueOf returns field's value and if it is zero field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) { v = reflect.Indirect(v) for _, fieldIdx := range field.StructField.Index {