gain another 5% on average by changing tag type from bool's to enum

```

benchmark                                               old ns/op     new ns/op     delta
BenchmarkFieldSuccess-4                                 117           116           -0.85%
BenchmarkFieldFailure-4                                 675           651           -3.56%
BenchmarkFieldDiveSuccess-4                             2518          2418          -3.97%
BenchmarkFieldDiveFailure-4                             3096          3011          -2.75%
BenchmarkFieldCustomTypeSuccess-4                       319           297           -6.90%
BenchmarkFieldCustomTypeFailure-4                       688           680           -1.16%
BenchmarkFieldOrTagSuccess-4                            1251          1176          -6.00%
BenchmarkFieldOrTagFailure-4                            1090          1073          -1.56%
BenchmarkStructLevelValidationSuccess-4                 558           567           +1.61%
BenchmarkStructLevelValidationFailure-4                 608           562           -7.57%
BenchmarkStructSimpleCustomTypeSuccess-4                702           636           -9.40%
BenchmarkStructSimpleCustomTypeFailure-4                1380          1295          -6.16%
BenchmarkStructPartialSuccess-4                         1139          1058          -7.11%
BenchmarkStructPartialFailure-4                         1760          1648          -6.36%
BenchmarkStructExceptSuccess-4                          951           917           -3.58%
BenchmarkStructExceptFailure-4                          1147          1085          -5.41%
BenchmarkStructSimpleCrossFieldSuccess-4                873           783           -10.31%
BenchmarkStructSimpleCrossFieldFailure-4                1478          1384          -6.36%
BenchmarkStructSimpleCrossStructCrossFieldSuccess-4     1328          1273          -4.14%
BenchmarkStructSimpleCrossStructCrossFieldFailure-4     1949          1896          -2.72%
BenchmarkStructSimpleSuccess-4                          559           523           -6.44%
BenchmarkStructSimpleFailure-4                          1334          1311          -1.72%
BenchmarkStructSimpleSuccessParallel-4                  148           137           -7.43%
BenchmarkStructSimpleFailureParallel-4                  631           591           -6.34%
BenchmarkStructComplexSuccess-4                         3476          3500          +0.69%
BenchmarkStructComplexFailure-4                         8467          8406          -0.72%
BenchmarkStructComplexSuccessParallel-4                 1098          1012          -7.83%
BenchmarkStructComplexFailureParallel-4                 3113          3121          +0.26%

benchmark                                               old allocs     new allocs     delta
BenchmarkFieldSuccess-4                                 0              0              +0.00%
BenchmarkFieldFailure-4                                 4              4              +0.00%
BenchmarkFieldDiveSuccess-4                             28             28             +0.00%
BenchmarkFieldDiveFailure-4                             32             32             +0.00%
BenchmarkFieldCustomTypeSuccess-4                       2              2              +0.00%
BenchmarkFieldCustomTypeFailure-4                       4              4              +0.00%
BenchmarkFieldOrTagSuccess-4                            1              1              +0.00%
BenchmarkFieldOrTagFailure-4                            6              6              +0.00%
BenchmarkStructLevelValidationSuccess-4                 5              5              +0.00%
BenchmarkStructLevelValidationFailure-4                 5              5              +0.00%
BenchmarkStructSimpleCustomTypeSuccess-4                3              3              +0.00%
BenchmarkStructSimpleCustomTypeFailure-4                9              9              +0.00%
BenchmarkStructPartialSuccess-4                         9              9              +0.00%
BenchmarkStructPartialFailure-4                         14             14             +0.00%
BenchmarkStructExceptSuccess-4                          7              7              +0.00%
BenchmarkStructExceptFailure-4                          9              9              +0.00%
BenchmarkStructSimpleCrossFieldSuccess-4                4              4              +0.00%
BenchmarkStructSimpleCrossFieldFailure-4                9              9              +0.00%
BenchmarkStructSimpleCrossStructCrossFieldSuccess-4     7              7              +0.00%
BenchmarkStructSimpleCrossStructCrossFieldFailure-4     12             12             +0.00%
BenchmarkStructSimpleSuccess-4                          1              1              +0.00%
BenchmarkStructSimpleFailure-4                          9              9              +0.00%
BenchmarkStructSimpleSuccessParallel-4                  1              1              +0.00%
BenchmarkStructSimpleFailureParallel-4                  9              9              +0.00%
BenchmarkStructComplexSuccess-4                         15             15             +0.00%
BenchmarkStructComplexFailure-4                         60             60             +0.00%
BenchmarkStructComplexSuccessParallel-4                 15             15             +0.00%
BenchmarkStructComplexFailureParallel-4                 60             60             +0.00%

benchmark                                               old bytes     new bytes     delta
BenchmarkFieldSuccess-4                                 0             0             +0.00%
BenchmarkFieldFailure-4                                 432           432           +0.00%
BenchmarkFieldDiveSuccess-4                             464           464           +0.00%
BenchmarkFieldDiveFailure-4                             896           896           +0.00%
BenchmarkFieldCustomTypeSuccess-4                       32            32            +0.00%
BenchmarkFieldCustomTypeFailure-4                       432           432           +0.00%
BenchmarkFieldOrTagSuccess-4                            4             4             +0.00%
BenchmarkFieldOrTagFailure-4                            448           448           +0.00%
BenchmarkStructLevelValidationSuccess-4                 160           160           +0.00%
BenchmarkStructLevelValidationFailure-4                 160           160           +0.00%
BenchmarkStructSimpleCustomTypeSuccess-4                36            36            +0.00%
BenchmarkStructSimpleCustomTypeFailure-4                640           640           +0.00%
BenchmarkStructPartialSuccess-4                         336           336           +0.00%
BenchmarkStructPartialFailure-4                         794           794           +0.00%
BenchmarkStructExceptSuccess-4                          314           314           +0.00%
BenchmarkStructExceptFailure-4                          336           336           +0.00%
BenchmarkStructSimpleCrossFieldSuccess-4                80            80            +0.00%
BenchmarkStructSimpleCrossFieldFailure-4                536           536           +0.00%
BenchmarkStructSimpleCrossStructCrossFieldSuccess-4     112           112           +0.00%
BenchmarkStructSimpleCrossStructCrossFieldFailure-4     576           576           +0.00%
BenchmarkStructSimpleSuccess-4                          4             4             +0.00%
BenchmarkStructSimpleFailure-4                          640           640           +0.00%
BenchmarkStructSimpleSuccessParallel-4                  4             4             +0.00%
BenchmarkStructSimpleFailureParallel-4                  640           640           +0.00%
BenchmarkStructComplexSuccess-4                         244           244           +0.00%
BenchmarkStructComplexFailure-4                         3608          3608          +0.00%
BenchmarkStructComplexSuccessParallel-4                 244           244           +0.00%
BenchmarkStructComplexFailureParallel-4                 3608          3608          +0.00%

```
pull/252/head
joeybloggs 8 years ago
parent 330b12dacd
commit 4ce4d1cd71
  1. 49
      cache.go
  2. 58
      validator.go

@ -8,6 +8,18 @@ import (
"sync/atomic" "sync/atomic"
) )
type tagType uint8
const (
typeDefault tagType = iota
typeOmitEmpty
typeNoStructLevel
typeStructOnly
typeDive
typeOr
typeExists
)
type structCache struct { type structCache struct {
lock sync.Mutex lock sync.Mutex
m atomic.Value // map[reflect.Type]*cStruct m atomic.Value // map[reflect.Type]*cStruct
@ -68,20 +80,15 @@ type cField struct {
// TODO: investigate using enum instead of so many booleans, may be faster // TODO: investigate using enum instead of so many booleans, may be faster
// but let's get the new cache system working first // but let's get the new cache system working first
type cTag struct { type cTag struct {
tag string tag string
aliasTag string aliasTag string
actualAliasTag string actualAliasTag string
param string param string
hasAlias bool hasAlias bool
isOmitEmpty bool typeof tagType
isNoStructLevel bool hasTag bool
isStructOnly bool fn Func
isDive bool next *cTag
isOrVal bool
exists bool
hasTag bool
fn Func
next *cTag
} }
// TODO: eliminate get and set functions from cache, they are pure overhead for nicer syntax. // TODO: eliminate get and set functions from cache, they are pure overhead for nicer syntax.
@ -198,23 +205,23 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
switch t { switch t {
case diveTag: case diveTag:
current.isDive = true current.typeof = typeDive
continue continue
case omitempty: case omitempty:
current.isOmitEmpty = true current.typeof = typeOmitEmpty
continue continue
case structOnlyTag: case structOnlyTag:
current.isStructOnly = true current.typeof = typeStructOnly
continue continue
case noStructLevelTag: case noStructLevelTag:
current.isNoStructLevel = true current.typeof = typeNoStructLevel
continue continue
case existsTag: case existsTag:
current.exists = true current.typeof = typeExists
continue continue
default: default:
@ -247,7 +254,9 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, fieldName))) panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, fieldName)))
} }
current.isOrVal = len(orVals) > 1 if len(orVals) > 1 {
current.typeof = typeOr
}
if len(vals) > 1 { if len(vals) > 1 {
current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1) current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1)

@ -548,7 +548,7 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
// structonly tag present don't tranverseFields // structonly tag present don't tranverseFields
// but must still check and run below struct level validation // but must still check and run below struct level validation
// if present // if present
if first || ct == nil || !ct.isStructOnly { if first || ct == nil || ct.typeof != typeStructOnly {
for _, f := range cs.fields { for _, f := range cs.fields {
@ -584,7 +584,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
return return
} }
if ct.isOmitEmpty { if ct.typeof == typeOmitEmpty {
return return
} }
@ -631,7 +631,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
ct = ct.next ct = ct.next
} }
if ct != nil && ct.isNoStructLevel { if ct != nil && ct.typeof == typeNoStructLevel {
return return
} }
@ -652,12 +652,13 @@ OUTER:
return return
} }
if ct.exists { switch ct.typeof {
case typeExists:
ct = ct.next ct = ct.next
continue continue
}
if ct.isOmitEmpty { case typeOmitEmpty:
if !HasValue(v, topStruct, currentStruct, current, typ, kind, blank) { if !HasValue(v, topStruct, currentStruct, current, typ, kind, blank) {
return return
@ -665,9 +666,8 @@ OUTER:
ct = ct.next ct = ct.next
continue continue
}
if ct.isDive { case typeDive:
ct = ct.next ct = ct.next
@ -692,9 +692,8 @@ OUTER:
} }
return return
}
if ct.isOrVal { case typeOr:
errTag := blank errTag := blank
@ -711,7 +710,7 @@ OUTER:
return return
} }
if !ct.isOrVal { if ct.typeof != typeOr {
continue OUTER continue OUTER
} }
} }
@ -755,29 +754,30 @@ OUTER:
ct = ct.next ct = ct.next
} }
}
if !ct.fn(v, topStruct, currentStruct, current, typ, kind, ct.param) { default:
if !ct.fn(v, topStruct, currentStruct, current, typ, kind, ct.param) {
ns := errPrefix + cf.Name ns := errPrefix + cf.Name
errs[ns] = &FieldError{ errs[ns] = &FieldError{
FieldNamespace: ns, FieldNamespace: ns,
NameNamespace: nsPrefix + cf.AltName, NameNamespace: nsPrefix + cf.AltName,
Name: cf.AltName, Name: cf.AltName,
Field: cf.Name, Field: cf.Name,
Tag: ct.aliasTag, Tag: ct.aliasTag,
ActualTag: ct.tag, ActualTag: ct.tag,
Value: current.Interface(), Value: current.Interface(),
Param: ct.param, Param: ct.param,
Type: typ, Type: typ,
Kind: kind, Kind: kind,
} }
return return
} }
ct = ct.next ct = ct.next
}
} }
} }

Loading…
Cancel
Save