Cache model struct for less GC

This commit is contained in:
Jinzhu 2013-11-17 08:55:37 +08:00
parent 9a1c0d956d
commit 88917aa2ef
1 changed files with 47 additions and 28 deletions

View File

@ -8,6 +8,12 @@ import (
"time" "time"
) )
var modelFieldMap map[string][]reflect.StructField
func init() {
modelFieldMap = map[string][]reflect.StructField{}
}
type Model struct { type Model struct {
data interface{} data interface{}
do *Do do *Do
@ -39,45 +45,58 @@ func (m *Model) primaryKeyDb() string {
return toSnake(m.primaryKey()) return toSnake(m.primaryKey())
} }
func getStructs(typ reflect.Type) (fs []reflect.StructField) {
name := typ.Name()
if fs = modelFieldMap[name]; fs != nil {
return
}
for i := 0; i < typ.NumField(); i++ {
p := typ.Field(i)
if !p.Anonymous && ast.IsExported(p.Name) {
fs = append(fs, p)
}
}
modelFieldMap[name] = fs
return
}
func (m *Model) fields(operation string) (fields []*Field) { func (m *Model) fields(operation string) (fields []*Field) {
indirect_value := m.reflectData() indirect_value := m.reflectData()
if !indirect_value.IsValid() { if !indirect_value.IsValid() {
return return
} }
typ := indirect_value.Type() for _, filed_struct := range getStructs(indirect_value.Type()) {
for i := 0; i < typ.NumField(); i++ { var field Field
p := typ.Field(i) field.Name = filed_struct.Name
if !p.Anonymous && ast.IsExported(p.Name) { field.dbName = toSnake(filed_struct.Name)
var field Field field.isPrimaryKey = m.primaryKeyDb() == field.dbName
field.Name = p.Name value := indirect_value.FieldByName(filed_struct.Name)
field.dbName = toSnake(p.Name) field.model = m
field.isPrimaryKey = m.primaryKeyDb() == field.dbName
value := indirect_value.FieldByName(p.Name)
field.model = m
if time_value, is_time := value.Interface().(time.Time); is_time { if time_value, is_time := value.Interface().(time.Time); is_time {
field.autoCreateTime = "created_at" == field.dbName field.autoCreateTime = "created_at" == field.dbName
field.autoUpdateTime = "updated_at" == field.dbName field.autoUpdateTime = "updated_at" == field.dbName
switch operation { switch operation {
case "create": case "create":
if (field.autoCreateTime || field.autoUpdateTime) && time_value.IsZero() { if (field.autoCreateTime || field.autoUpdateTime) && time_value.IsZero() {
value.Set(reflect.ValueOf(time.Now())) value.Set(reflect.ValueOf(time.Now()))
} }
case "update": case "update":
if field.autoUpdateTime { if field.autoUpdateTime {
value.Set(reflect.ValueOf(time.Now())) value.Set(reflect.ValueOf(time.Now()))
}
} }
} }
field.structField = p
field.reflectValue = value
field.Value = value.Interface()
field.parseAssociation()
fields = append(fields, &field)
} }
field.structField = filed_struct
field.reflectValue = value
field.Value = value.Interface()
field.parseAssociation()
fields = append(fields, &field)
} }
return return
} }