mirror of https://github.com/go-gorm/gorm.git
Use channel to make gorm faster
This commit is contained in:
parent
88917aa2ef
commit
bf1db1534e
5
field.go
5
field.go
|
@ -13,6 +13,7 @@ type Field struct {
|
||||||
Value interface{}
|
Value interface{}
|
||||||
model *Model
|
model *Model
|
||||||
dbName string
|
dbName string
|
||||||
|
isBlank bool
|
||||||
isPrimaryKey bool
|
isPrimaryKey bool
|
||||||
autoCreateTime bool
|
autoCreateTime bool
|
||||||
autoUpdateTime bool
|
autoUpdateTime bool
|
||||||
|
@ -23,8 +24,8 @@ type Field struct {
|
||||||
structField reflect.StructField
|
structField reflect.StructField
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Field) isBlank() bool {
|
func (f *Field) parseBlank() {
|
||||||
return isBlank(f.reflectValue)
|
f.isBlank = isBlank(f.reflectValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Field) isScanner() bool {
|
func (f *Field) isScanner() bool {
|
||||||
|
|
|
@ -1365,7 +1365,7 @@ func TestQueryChain(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkGorm(b *testing.B) {
|
func BenchmarkGorm(b *testing.B) {
|
||||||
b.N = 5000
|
b.N = 2000
|
||||||
for x := 0; x < b.N; x++ {
|
for x := 0; x < b.N; x++ {
|
||||||
e := strconv.Itoa(x) + "benchmark@example.org"
|
e := strconv.Itoa(x) + "benchmark@example.org"
|
||||||
email := BigEmail{Email: e, UserAgent: "pc", RegisteredAt: time.Now()}
|
email := BigEmail{Email: e, UserAgent: "pc", RegisteredAt: time.Now()}
|
||||||
|
@ -1388,7 +1388,7 @@ func BenchmarkRawSql(b *testing.B) {
|
||||||
update_sql := "UPDATE emails SET email = $1, updated_at = $2 WHERE id = $3"
|
update_sql := "UPDATE emails SET email = $1, updated_at = $2 WHERE id = $3"
|
||||||
delete_sql := "DELETE FROM orders WHERE id = $1"
|
delete_sql := "DELETE FROM orders WHERE id = $1"
|
||||||
|
|
||||||
b.N = 5000
|
b.N = 2000
|
||||||
for x := 0; x < b.N; x++ {
|
for x := 0; x < b.N; x++ {
|
||||||
var id int64
|
var id int64
|
||||||
e := strconv.Itoa(x) + "benchmark@example.org"
|
e := strconv.Itoa(x) + "benchmark@example.org"
|
||||||
|
|
3
main.go
3
main.go
|
@ -2,7 +2,6 @@ package gorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
"github.com/jinzhu/gorm/dialect"
|
"github.com/jinzhu/gorm/dialect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -139,7 +138,7 @@ func (s *DB) Delete(value interface{}) *DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DB) Exec(sql string) *DB {
|
func (s *DB) Exec(sql string) *DB {
|
||||||
return s.do(nil).exec(sql).db
|
return s.clone().do(nil).exec(sql).db
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DB) Model(value interface{}) *DB {
|
func (s *DB) Model(value interface{}) *DB {
|
||||||
|
|
74
model.go
74
model.go
|
@ -63,47 +63,65 @@ func getStructs(typ reflect.Type) (fs []reflect.StructField) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) fields(operation string) (fields []*Field) {
|
func (m *Model) fields(operation string) (fields []*Field) {
|
||||||
|
if len(m._cache_fields[operation]) > 0 {
|
||||||
|
return m._cache_fields[operation]
|
||||||
|
}
|
||||||
|
|
||||||
indirect_value := m.reflectData()
|
indirect_value := m.reflectData()
|
||||||
if !indirect_value.IsValid() {
|
if !indirect_value.IsValid() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, filed_struct := range getStructs(indirect_value.Type()) {
|
structs := getStructs(indirect_value.Type())
|
||||||
var field Field
|
c := make(chan *Field, len(structs))
|
||||||
field.Name = filed_struct.Name
|
for _, field_struct := range structs {
|
||||||
field.dbName = toSnake(filed_struct.Name)
|
go func(field_struct reflect.StructField, c chan *Field) {
|
||||||
field.isPrimaryKey = m.primaryKeyDb() == field.dbName
|
var field Field
|
||||||
value := indirect_value.FieldByName(filed_struct.Name)
|
field.Name = field_struct.Name
|
||||||
field.model = m
|
field.dbName = toSnake(field_struct.Name)
|
||||||
|
field.isPrimaryKey = m.primaryKeyDb() == field.dbName
|
||||||
|
value := indirect_value.FieldByName(field_struct.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 = field_struct
|
||||||
|
field.reflectValue = value
|
||||||
field.structField = filed_struct
|
field.Value = value.Interface()
|
||||||
field.reflectValue = value
|
field.parseAssociation()
|
||||||
field.Value = value.Interface()
|
field.parseBlank()
|
||||||
field.parseAssociation()
|
c <- &field
|
||||||
fields = append(fields, &field)
|
}(field_struct, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(structs); i++ {
|
||||||
|
fields = append(fields, <-c)
|
||||||
|
}
|
||||||
|
close(c)
|
||||||
|
|
||||||
|
if len(m._cache_fields) == 0 {
|
||||||
|
m._cache_fields = map[string][]*Field{}
|
||||||
|
}
|
||||||
|
m._cache_fields[operation] = fields
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) columnsHasValue(operation string) (fields []*Field) {
|
func (m *Model) columnsHasValue(operation string) (fields []*Field) {
|
||||||
for _, field := range m.fields(operation) {
|
for _, field := range m.fields(operation) {
|
||||||
if !field.isBlank() {
|
if !field.isBlank {
|
||||||
fields = append(fields, field)
|
fields = append(fields, field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +254,7 @@ func (m *Model) setValueByColumn(name string, value interface{}, out interface{}
|
||||||
|
|
||||||
func (m *Model) beforeAssociations() (fields []*Field) {
|
func (m *Model) beforeAssociations() (fields []*Field) {
|
||||||
for _, field := range m.fields("null") {
|
for _, field := range m.fields("null") {
|
||||||
if field.beforeAssociation && !field.isBlank() {
|
if field.beforeAssociation && !field.isBlank {
|
||||||
fields = append(fields, field)
|
fields = append(fields, field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,7 +263,7 @@ func (m *Model) beforeAssociations() (fields []*Field) {
|
||||||
|
|
||||||
func (m *Model) afterAssociations() (fields []*Field) {
|
func (m *Model) afterAssociations() (fields []*Field) {
|
||||||
for _, field := range m.fields("null") {
|
for _, field := range m.fields("null") {
|
||||||
if field.afterAssociation && !field.isBlank() {
|
if field.afterAssociation && !field.isBlank {
|
||||||
fields = append(fields, field)
|
fields = append(fields, field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue