Add some string check optimizations

* was using len(string) for some blank checks instead of string == ""
pull/228/head
joeybloggs 9 years ago
parent 0b533f264c
commit 0862513fbf
  1. 56
      README.md
  2. 2
      baked_in.go
  3. 11
      util.go
  4. 30
      validator.go

@ -312,34 +312,34 @@ Benchmarks
```go ```go
go test -cpu=4 -bench=. -benchmem=true go test -cpu=4 -bench=. -benchmem=true
PASS PASS
BenchmarkFieldSuccess-4 10000000 173 ns/op 0 B/op 0 allocs/op BenchmarkFieldSuccess-4 10000000 176 ns/op 0 B/op 0 allocs/op
BenchmarkFieldFailure-4 2000000 730 ns/op 432 B/op 4 allocs/op BenchmarkFieldFailure-4 2000000 727 ns/op 432 B/op 4 allocs/op
BenchmarkFieldDiveSuccess-4 500000 3180 ns/op 480 B/op 27 allocs/op BenchmarkFieldDiveSuccess-4 500000 3220 ns/op 480 B/op 27 allocs/op
BenchmarkFieldDiveFailure-4 500000 3844 ns/op 912 B/op 31 allocs/op BenchmarkFieldDiveFailure-4 500000 3823 ns/op 912 B/op 31 allocs/op
BenchmarkFieldCustomTypeSuccess-4 5000000 365 ns/op 32 B/op 2 allocs/op BenchmarkFieldCustomTypeSuccess-4 5000000 368 ns/op 32 B/op 2 allocs/op
BenchmarkFieldCustomTypeFailure-4 2000000 705 ns/op 432 B/op 4 allocs/op BenchmarkFieldCustomTypeFailure-4 2000000 699 ns/op 432 B/op 4 allocs/op
BenchmarkFieldOrTagSuccess-4 1000000 1275 ns/op 16 B/op 1 allocs/op BenchmarkFieldOrTagSuccess-4 1000000 1265 ns/op 16 B/op 1 allocs/op
BenchmarkFieldOrTagFailure-4 1000000 1174 ns/op 464 B/op 6 allocs/op BenchmarkFieldOrTagFailure-4 1000000 1182 ns/op 464 B/op 6 allocs/op
BenchmarkStructLevelValidationSuccess-4 2000000 800 ns/op 192 B/op 7 allocs/op BenchmarkStructLevelValidationSuccess-4 2000000 739 ns/op 176 B/op 6 allocs/op
BenchmarkStructLevelValidationFailure-4 1000000 1495 ns/op 688 B/op 13 allocs/op BenchmarkStructLevelValidationFailure-4 1000000 1368 ns/op 640 B/op 11 allocs/op
BenchmarkStructSimpleCustomTypeSuccess-4 1000000 1048 ns/op 96 B/op 6 allocs/op BenchmarkStructSimpleCustomTypeSuccess-4 2000000 965 ns/op 80 B/op 5 allocs/op
BenchmarkStructSimpleCustomTypeFailure-4 1000000 1730 ns/op 736 B/op 14 allocs/op BenchmarkStructSimpleCustomTypeFailure-4 1000000 1561 ns/op 688 B/op 11 allocs/op
BenchmarkStructPartialSuccess-4 1000000 1362 ns/op 400 B/op 11 allocs/op BenchmarkStructPartialSuccess-4 1000000 1285 ns/op 384 B/op 10 allocs/op
BenchmarkStructPartialFailure-4 1000000 1993 ns/op 864 B/op 17 allocs/op BenchmarkStructPartialFailure-4 1000000 1879 ns/op 832 B/op 15 allocs/op
BenchmarkStructExceptSuccess-4 1000000 1067 ns/op 352 B/op 8 allocs/op BenchmarkStructExceptSuccess-4 2000000 1038 ns/op 336 B/op 7 allocs/op
BenchmarkStructExceptFailure-4 1000000 1352 ns/op 400 B/op 11 allocs/op BenchmarkStructExceptFailure-4 1000000 1330 ns/op 384 B/op 10 allocs/op
BenchmarkStructSimpleCrossFieldSuccess-4 1000000 1147 ns/op 144 B/op 7 allocs/op BenchmarkStructSimpleCrossFieldSuccess-4 1000000 1081 ns/op 128 B/op 6 allocs/op
BenchmarkStructSimpleCrossFieldFailure-4 1000000 1815 ns/op 624 B/op 13 allocs/op BenchmarkStructSimpleCrossFieldFailure-4 1000000 1737 ns/op 592 B/op 11 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldSuccess-4 1000000 1779 ns/op 208 B/op 11 allocs/op BenchmarkStructSimpleCrossStructCrossFieldSuccess-4 1000000 1790 ns/op 192 B/op 10 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldFailure-4 500000 2465 ns/op 688 B/op 17 allocs/op BenchmarkStructSimpleCrossStructCrossFieldFailure-4 500000 2431 ns/op 656 B/op 15 allocs/op
BenchmarkStructSimpleSuccess-4 2000000 980 ns/op 64 B/op 4 allocs/op BenchmarkStructSimpleSuccess-4 2000000 950 ns/op 48 B/op 3 allocs/op
BenchmarkStructSimpleFailure-4 1000000 1778 ns/op 736 B/op 14 allocs/op BenchmarkStructSimpleFailure-4 1000000 1672 ns/op 688 B/op 11 allocs/op
BenchmarkStructSimpleSuccessParallel-4 5000000 313 ns/op 64 B/op 4 allocs/op BenchmarkStructSimpleSuccessParallel-4 5000000 271 ns/op 48 B/op 3 allocs/op
BenchmarkStructSimpleFailureParallel-4 2000000 859 ns/op 736 B/op 14 allocs/op BenchmarkStructSimpleFailureParallel-4 2000000 670 ns/op 688 B/op 11 allocs/op
BenchmarkStructComplexSuccess-4 200000 5781 ns/op 592 B/op 33 allocs/op BenchmarkStructComplexSuccess-4 300000 5828 ns/op 544 B/op 32 allocs/op
BenchmarkStructComplexFailure-4 200000 11816 ns/op 4216 B/op 88 allocs/op BenchmarkStructComplexFailure-4 200000 11382 ns/op 3912 B/op 77 allocs/op
BenchmarkStructComplexSuccessParallel-4 1000000 2003 ns/op 592 B/op 33 allocs/op BenchmarkStructComplexSuccessParallel-4 1000000 1739 ns/op 544 B/op 32 allocs/op
BenchmarkStructComplexFailureParallel-4 300000 5628 ns/op 4216 B/op 88 allocs/op BenchmarkStructComplexFailureParallel-4 300000 4682 ns/op 3912 B/op 77 allocs/op
``` ```
How to Contribute How to Contribute

@ -756,7 +756,7 @@ func IsURL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
return false return false
} }
if len(url.Scheme) == 0 { if url.Scheme == blank {
return false return false
} }

@ -8,6 +8,7 @@ import (
) )
const ( const (
dash = "-"
blank = "" blank = ""
namespaceSeparator = "." namespaceSeparator = "."
leftBracket = "[" leftBracket = "["
@ -86,7 +87,7 @@ func (v *Validate) GetStructFieldOK(current reflect.Value, namespace string) (re
return current, kind, false return current, kind, false
} }
if len(namespace) == 0 { if namespace == blank {
return current, kind, true return current, kind, true
} }
@ -262,7 +263,7 @@ func (v *Validate) parseStruct(current reflect.Value, sName string) *cachedStruc
fld = typ.Field(i) fld = typ.Field(i)
if len(fld.PkgPath) != 0 { if fld.PkgPath != blank {
continue continue
} }
@ -273,7 +274,7 @@ func (v *Validate) parseStruct(current reflect.Value, sName string) *cachedStruc
} }
customName = fld.Name customName = fld.Name
if len(v.fieldNameTag) != 0 { if v.fieldNameTag != blank {
name := strings.SplitN(fld.Tag.Get(v.fieldNameTag), ",", 2)[0] name := strings.SplitN(fld.Tag.Get(v.fieldNameTag), ",", 2)[0]
@ -309,7 +310,7 @@ func (v *Validate) parseTags(tag, fieldName string) *cachedTag {
func (v *Validate) parseTagsRecursive(cTag *cachedTag, tag, fieldName, alias string, isAlias bool) bool { func (v *Validate) parseTagsRecursive(cTag *cachedTag, tag, fieldName, alias string, isAlias bool) bool {
if len(tag) == 0 { if tag == blank {
return true return true
} }
@ -365,7 +366,7 @@ func (v *Validate) parseTagsRecursive(cTag *cachedTag, tag, fieldName, alias str
tagVal.tag = alias tagVal.tag = alias
} }
if len(key) == 0 { if key == blank {
panic(strings.TrimSpace(fmt.Sprintf(invalidValidation, fieldName))) panic(strings.TrimSpace(fmt.Sprintf(invalidValidation, fieldName)))
} }

@ -94,15 +94,15 @@ func (sl *StructLevel) ReportError(field reflect.Value, fieldName string, custom
field, kind := sl.v.ExtractType(field) field, kind := sl.v.ExtractType(field)
if len(fieldName) == 0 { if fieldName == blank {
panic(fieldNameRequired) panic(fieldNameRequired)
} }
if len(customName) == 0 { if customName == blank {
customName = fieldName customName = fieldName
} }
if len(tag) == 0 { if tag == blank {
panic(tagRequired) panic(tagRequired)
} }
@ -270,7 +270,7 @@ func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interfa
func (v *Validate) RegisterValidation(key string, fn Func) error { func (v *Validate) RegisterValidation(key string, fn Func) error {
v.initCheck() v.initCheck()
if len(key) == 0 { if key == blank {
return errors.New("Function Key cannot be empty") return errors.New("Function Key cannot be empty")
} }
@ -435,7 +435,7 @@ func (v *Validate) StructExcept(current interface{}, fields ...string) error {
m := map[string]*struct{}{} m := map[string]*struct{}{}
for _, key := range fields { for _, key := range fields {
m[name+"."+key] = emptyStructPtr m[name+namespaceSeparator+key] = emptyStructPtr
} }
errs := v.errsPool.Get().(ValidationErrors) errs := v.errsPool.Get().(ValidationErrors)
@ -486,10 +486,10 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
sName := typ.Name() sName := typ.Name()
if useStructName { if useStructName {
errPrefix += sName + "." errPrefix += sName + namespaceSeparator
if v.fieldNameTag != "" { if v.fieldNameTag != blank {
nsPrefix += sName + "." nsPrefix += sName + namespaceSeparator
} }
} }
@ -502,7 +502,7 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
// is anonymous struct, cannot parse or cache as // is anonymous struct, cannot parse or cache as
// it has no name to index by // it has no name to index by
if len(sName) == 0 { if sName == blank {
var customName string var customName string
var ok bool var ok bool
@ -512,7 +512,7 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
fld = typ.Field(i) fld = typ.Field(i)
if len(fld.PkgPath) != 0 { if fld.PkgPath != blank {
continue continue
} }
@ -527,12 +527,12 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
customName = fld.Name customName = fld.Name
if v.fieldNameTag != "" { if v.fieldNameTag != blank {
name := strings.SplitN(fld.Tag.Get(v.fieldNameTag), ",", 2)[0] name := strings.SplitN(fld.Tag.Get(v.fieldNameTag), ",", 2)[0]
// dash check is for json "-" means don't output in json // dash check is for json "-" means don't output in json
if name != "" && name != "-" { if name != blank && name != dash {
customName = name customName = name
} }
} }
@ -595,7 +595,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
return return
} }
if len(tag) > 0 { if tag != blank {
ns := errPrefix + name ns := errPrefix + name
@ -643,12 +643,12 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
return return
} }
v.tranverseStruct(topStruct, current, current, errPrefix+name+".", nsPrefix+customName+".", errs, false, partial, exclude, includeExclude, cTag.isStructOnly) v.tranverseStruct(topStruct, current, current, errPrefix+name+namespaceSeparator, nsPrefix+customName+namespaceSeparator, errs, false, partial, exclude, includeExclude, cTag.isStructOnly)
return return
} }
} }
if len(tag) == 0 { if tag == blank {
return return
} }

Loading…
Cancel
Save