Skip to content

Commit

Permalink
Cache model struct for less GC
Browse files Browse the repository at this point in the history
  • Loading branch information
jinzhu committed Nov 17, 2013
1 parent 9a1c0d9 commit 88917aa
Showing 1 changed file with 49 additions and 30 deletions.
79 changes: 49 additions & 30 deletions model.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import (
"time"
)

var modelFieldMap map[string][]reflect.StructField

func init() {
modelFieldMap = map[string][]reflect.StructField{}
}

type Model struct {
data interface{}
do *Do
Expand Down Expand Up @@ -39,45 +45,58 @@ func (m *Model) primaryKeyDb() string {
return toSnake(m.primaryKey())
}

func (m *Model) fields(operation string) (fields []*Field) {
indirect_value := m.reflectData()
if !indirect_value.IsValid() {
func getStructs(typ reflect.Type) (fs []reflect.StructField) {
name := typ.Name()
if fs = modelFieldMap[name]; fs != nil {
return
}

typ := indirect_value.Type()
for i := 0; i < typ.NumField(); i++ {
p := typ.Field(i)
if !p.Anonymous && ast.IsExported(p.Name) {
var field Field
field.Name = p.Name
field.dbName = toSnake(p.Name)
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 {
field.autoCreateTime = "created_at" == field.dbName
field.autoUpdateTime = "updated_at" == field.dbName

switch operation {
case "create":
if (field.autoCreateTime || field.autoUpdateTime) && time_value.IsZero() {
value.Set(reflect.ValueOf(time.Now()))
}
case "update":
if field.autoUpdateTime {
value.Set(reflect.ValueOf(time.Now()))
}
fs = append(fs, p)
}
}

modelFieldMap[name] = fs
return
}

func (m *Model) fields(operation string) (fields []*Field) {
indirect_value := m.reflectData()
if !indirect_value.IsValid() {
return
}

for _, filed_struct := range getStructs(indirect_value.Type()) {
var field Field
field.Name = filed_struct.Name
field.dbName = toSnake(filed_struct.Name)
field.isPrimaryKey = m.primaryKeyDb() == field.dbName
value := indirect_value.FieldByName(filed_struct.Name)
field.model = m

if time_value, is_time := value.Interface().(time.Time); is_time {
field.autoCreateTime = "created_at" == field.dbName
field.autoUpdateTime = "updated_at" == field.dbName

switch operation {
case "create":
if (field.autoCreateTime || field.autoUpdateTime) && time_value.IsZero() {
value.Set(reflect.ValueOf(time.Now()))
}
case "update":
if field.autoUpdateTime {
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
}
Expand Down

0 comments on commit 88917aa

Please sign in to comment.