Skip to content

Commit

Permalink
Add validator option once at state creation (#128)
Browse files Browse the repository at this point in the history
Avoid appending validator in every call to tryOptions and
instead ensure that the state starts with one in the options list.
Doing so dramatically reduces the number of allocations.

benchmark                               old MB/s     new MB/s     speedup
BenchmarkBytes/4KiB/EqualFilter0-4      2.16         2.56         1.19x
BenchmarkBytes/4KiB/EqualFilter1-4      1.35         1.53         1.13x
BenchmarkBytes/4KiB/EqualFilter2-4      1.09         1.20         1.10x
BenchmarkBytes/4KiB/EqualFilter3-4      0.81         0.99         1.22x
BenchmarkBytes/4KiB/EqualFilter4-4      0.74         0.77         1.04x
BenchmarkBytes/4KiB/EqualFilter5-4      0.63         0.69         1.10x
BenchmarkBytes/4KiB/DiffFilter0-4       2.04         2.38         1.17x
BenchmarkBytes/4KiB/DiffFilter1-4       1.27         1.52         1.20x
BenchmarkBytes/4KiB/DiffFilter2-4       0.98         1.15         1.17x
BenchmarkBytes/4KiB/DiffFilter3-4       0.87         0.96         1.10x
BenchmarkBytes/4KiB/DiffFilter4-4       0.66         0.81         1.23x
BenchmarkBytes/4KiB/DiffFilter5-4       0.58         0.69         1.19x
BenchmarkBytes/64KiB/EqualFilter0-4     1.98         2.31         1.17x
BenchmarkBytes/64KiB/EqualFilter1-4     1.28         1.71         1.34x
BenchmarkBytes/64KiB/EqualFilter2-4     1.04         1.23         1.18x
BenchmarkBytes/64KiB/EqualFilter3-4     0.85         0.93         1.09x
BenchmarkBytes/64KiB/EqualFilter4-4     0.72         0.83         1.15x
BenchmarkBytes/64KiB/EqualFilter5-4     0.62         0.70         1.13x
BenchmarkBytes/64KiB/DiffFilter0-4      1.95         2.29         1.17x
BenchmarkBytes/64KiB/DiffFilter1-4      1.24         1.56         1.26x
BenchmarkBytes/64KiB/DiffFilter2-4      0.96         1.14         1.19x
BenchmarkBytes/64KiB/DiffFilter3-4      0.82         0.97         1.18x
BenchmarkBytes/64KiB/DiffFilter4-4      0.69         0.79         1.14x
BenchmarkBytes/64KiB/DiffFilter5-4      0.63         0.70         1.11x
BenchmarkBytes/1MiB/EqualFilter0-4      2.14         2.40         1.12x
BenchmarkBytes/1MiB/EqualFilter1-4      1.36         1.63         1.20x
BenchmarkBytes/1MiB/EqualFilter2-4      1.05         1.12         1.07x
BenchmarkBytes/1MiB/EqualFilter3-4      0.84         0.81         0.96x
BenchmarkBytes/1MiB/EqualFilter4-4      0.70         0.72         1.03x
BenchmarkBytes/1MiB/EqualFilter5-4      0.63         0.64         1.02x
BenchmarkBytes/1MiB/DiffFilter0-4       1.85         2.07         1.12x
BenchmarkBytes/1MiB/DiffFilter1-4       1.26         1.49         1.18x
BenchmarkBytes/1MiB/DiffFilter2-4       0.95         1.00         1.05x
BenchmarkBytes/1MiB/DiffFilter3-4       0.84         0.88         1.05x
BenchmarkBytes/1MiB/DiffFilter4-4       0.71         0.72         1.01x
BenchmarkBytes/1MiB/DiffFilter5-4       0.62         0.67         1.08x
BenchmarkBytes/16MiB/EqualFilter0-4     2.02         2.16         1.07x
BenchmarkBytes/16MiB/EqualFilter1-4     1.40         1.56         1.11x
BenchmarkBytes/16MiB/EqualFilter2-4     1.09         1.06         0.97x
BenchmarkBytes/16MiB/EqualFilter3-4     0.89         0.88         0.99x
BenchmarkBytes/16MiB/EqualFilter4-4     0.75         0.76         1.01x
BenchmarkBytes/16MiB/EqualFilter5-4     0.64         0.64         1.00x
BenchmarkBytes/16MiB/DiffFilter0-4      1.65         2.15         1.30x
BenchmarkBytes/16MiB/DiffFilter1-4      1.24         1.35         1.09x
BenchmarkBytes/16MiB/DiffFilter2-4      1.04         0.97         0.93x
BenchmarkBytes/16MiB/DiffFilter3-4      0.86         0.87         1.01x
BenchmarkBytes/16MiB/DiffFilter4-4      0.69         0.75         1.09x
BenchmarkBytes/16MiB/DiffFilter5-4      0.66         0.65         0.98x

benchmark                               old allocs     new allocs     delta
BenchmarkBytes/4KiB/EqualFilter0-4      8276           83             -99.00%
BenchmarkBytes/4KiB/EqualFilter1-4      16471          84             -99.49%
BenchmarkBytes/4KiB/EqualFilter2-4      16472          85             -99.48%
BenchmarkBytes/4KiB/EqualFilter3-4      16473          85             -99.48%
BenchmarkBytes/4KiB/EqualFilter4-4      16473          86             -99.48%
BenchmarkBytes/4KiB/EqualFilter5-4      16474          86             -99.48%
BenchmarkBytes/4KiB/DiffFilter0-4       8305           111            -98.66%
BenchmarkBytes/4KiB/DiffFilter1-4       16501          112            -99.32%
BenchmarkBytes/4KiB/DiffFilter2-4       16502          113            -99.32%
BenchmarkBytes/4KiB/DiffFilter3-4       16503          113            -99.32%
BenchmarkBytes/4KiB/DiffFilter4-4       16503          114            -99.31%
BenchmarkBytes/4KiB/DiffFilter5-4       16504          114            -99.31%
BenchmarkBytes/64KiB/EqualFilter0-4     131206         133            -99.90%
BenchmarkBytes/64KiB/EqualFilter1-4     262281         134            -99.95%
BenchmarkBytes/64KiB/EqualFilter2-4     262282         135            -99.95%
BenchmarkBytes/64KiB/EqualFilter3-4     262283         135            -99.95%
BenchmarkBytes/64KiB/EqualFilter4-4     262283         136            -99.95%
BenchmarkBytes/64KiB/EqualFilter5-4     262284         137            -99.95%
BenchmarkBytes/64KiB/DiffFilter0-4      131244         171            -99.87%
BenchmarkBytes/64KiB/DiffFilter1-4      262319         172            -99.93%
BenchmarkBytes/64KiB/DiffFilter2-4      262320         173            -99.93%
BenchmarkBytes/64KiB/DiffFilter3-4      262321         173            -99.93%
BenchmarkBytes/64KiB/DiffFilter4-4      262321         174            -99.93%
BenchmarkBytes/64KiB/DiffFilter5-4      262322         174            -99.93%
BenchmarkBytes/1MiB/EqualFilter0-4      2097346        192            -99.99%
BenchmarkBytes/1MiB/EqualFilter1-4      4194502        193            -100.00%
BenchmarkBytes/1MiB/EqualFilter2-4      4194504        196            -100.00%
BenchmarkBytes/1MiB/EqualFilter3-4      4194506        194            -100.00%
BenchmarkBytes/1MiB/EqualFilter4-4      4194502        198            -100.00%
BenchmarkBytes/1MiB/EqualFilter5-4      4194506        196            -100.00%
BenchmarkBytes/1MiB/DiffFilter0-4       2097384        229            -99.99%
BenchmarkBytes/1MiB/DiffFilter1-4       4194537        231            -99.99%
BenchmarkBytes/1MiB/DiffFilter2-4       4194539        233            -99.99%
BenchmarkBytes/1MiB/DiffFilter3-4       4194539        234            -99.99%
BenchmarkBytes/1MiB/DiffFilter4-4       4194544        233            -99.99%
BenchmarkBytes/1MiB/DiffFilter5-4       4194540        233            -99.99%
BenchmarkBytes/16MiB/EqualFilter0-4     33554689       256            -100.00%
BenchmarkBytes/16MiB/EqualFilter1-4     67109123       255            -100.00%
BenchmarkBytes/16MiB/EqualFilter2-4     67109124       257            -100.00%
BenchmarkBytes/16MiB/EqualFilter3-4     67109129       257            -100.00%
BenchmarkBytes/16MiB/EqualFilter4-4     67109124       258            -100.00%
BenchmarkBytes/16MiB/EqualFilter5-4     67109126       257            -100.00%
BenchmarkBytes/16MiB/DiffFilter0-4      33554724       292            -100.00%
BenchmarkBytes/16MiB/DiffFilter1-4      67109163       293            -100.00%
BenchmarkBytes/16MiB/DiffFilter2-4      67109160       294            -100.00%
BenchmarkBytes/16MiB/DiffFilter3-4      67109161       294            -100.00%
BenchmarkBytes/16MiB/DiffFilter4-4      67109163       295            -100.00%
BenchmarkBytes/16MiB/DiffFilter5-4      67109162       299            -100.00%

benchmark                               old bytes      new bytes      delta
BenchmarkBytes/4KiB/EqualFilter0-4      628702         366504         -41.70%
BenchmarkBytes/4KiB/EqualFilter1-4      890920         366536         -58.86%
BenchmarkBytes/4KiB/EqualFilter2-4      890952         366601         -58.85%
BenchmarkBytes/4KiB/EqualFilter3-4      891016         366602         -58.86%
BenchmarkBytes/4KiB/EqualFilter4-4      891016         366730         -58.84%
BenchmarkBytes/4KiB/EqualFilter5-4      891144         366728         -58.85%
BenchmarkBytes/4KiB/DiffFilter0-4       629425         367149         -41.67%
BenchmarkBytes/4KiB/DiffFilter1-4       891738         367180         -58.82%
BenchmarkBytes/4KiB/DiffFilter2-4       891770         367244         -58.82%
BenchmarkBytes/4KiB/DiffFilter3-4       891834         367245         -58.82%
BenchmarkBytes/4KiB/DiffFilter4-4       891835         367372         -58.81%
BenchmarkBytes/4KiB/DiffFilter5-4       891965         367372         -58.81%
BenchmarkBytes/64KiB/EqualFilter0-4     10826734       6632425        -38.74%
BenchmarkBytes/64KiB/EqualFilter1-4     15021123       6632443        -55.85%
BenchmarkBytes/64KiB/EqualFilter2-4     15021174       6632502        -55.85%
BenchmarkBytes/64KiB/EqualFilter3-4     15021219       6632540        -55.85%
BenchmarkBytes/64KiB/EqualFilter4-4     15021219       6632640        -55.84%
BenchmarkBytes/64KiB/EqualFilter5-4     15021340       6632707        -55.84%
BenchmarkBytes/64KiB/DiffFilter0-4      10828312       6633995        -38.73%
BenchmarkBytes/64KiB/DiffFilter1-4      15022724       6634049        -55.84%
BenchmarkBytes/64KiB/DiffFilter2-4      15022763       6634091        -55.84%
BenchmarkBytes/64KiB/DiffFilter3-4      15022820       6634081        -55.84%
BenchmarkBytes/64KiB/DiffFilter4-4      15022843       6634241        -55.84%
BenchmarkBytes/64KiB/DiffFilter5-4      15022996       6634222        -55.84%
BenchmarkBytes/1MiB/EqualFilter0-4      173184064      106075104      -38.75%
BenchmarkBytes/1MiB/EqualFilter1-4      240293104      106075088      -55.86%
BenchmarkBytes/1MiB/EqualFilter2-4      240293232      106075344      -55.86%
BenchmarkBytes/1MiB/EqualFilter3-4      240293328      106075152      -55.86%
BenchmarkBytes/1MiB/EqualFilter4-4      240293008      106075504      -55.86%
BenchmarkBytes/1MiB/EqualFilter5-4      240293424      106075376      -55.86%
BenchmarkBytes/1MiB/DiffFilter0-4       173185752      106076648      -38.75%
BenchmarkBytes/1MiB/DiffFilter1-4       240294504      106076776      -55.86%
BenchmarkBytes/1MiB/DiffFilter2-4       240294600      106076936      -55.86%
BenchmarkBytes/1MiB/DiffFilter3-4       240294600      106076936      -55.86%
BenchmarkBytes/1MiB/DiffFilter4-4       240295016      106076968      -55.86%
BenchmarkBytes/1MiB/DiffFilter5-4       240294728      106076968      -55.86%
BenchmarkBytes/16MiB/EqualFilter0-4     2967917664     1894175792     -36.18%
BenchmarkBytes/16MiB/EqualFilter1-4     4041659536     1894175696     -53.13%
BenchmarkBytes/16MiB/EqualFilter2-4     4041659568     1894175856     -53.13%
BenchmarkBytes/16MiB/EqualFilter3-4     4041660016     1894175856     -53.13%
BenchmarkBytes/16MiB/EqualFilter4-4     4041659536     1894175984     -53.13%
BenchmarkBytes/16MiB/EqualFilter5-4     4041659760     1894175888     -53.13%
BenchmarkBytes/16MiB/DiffFilter0-4      2967919128     1894177352     -36.18%
BenchmarkBytes/16MiB/DiffFilter1-4      4041661320     1894177352     -53.13%
BenchmarkBytes/16MiB/DiffFilter2-4      4041661064     1894177448     -53.13%
BenchmarkBytes/16MiB/DiffFilter3-4      4041661128     1894177448     -53.13%
BenchmarkBytes/16MiB/DiffFilter4-4      4041661256     1894177576     -53.13%
BenchmarkBytes/16MiB/DiffFilter5-4      4041661256     1894177832     -53.13%
  • Loading branch information
dsnet committed Feb 28, 2019
1 parent 64cb04e commit 2e500c5
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 16 deletions.
13 changes: 3 additions & 10 deletions cmp/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ type state struct {
}

func newState(opts []Option) *state {
s := new(state)
// Always ensure a validator option exists to validate the inputs.
s := &state{opts: Options{validator{}}}
for _, opt := range opts {
s.processOption(opt)
}
Expand Down Expand Up @@ -293,16 +294,8 @@ func (s *state) compareAny(step PathStep) {
}

func (s *state) tryOptions(t reflect.Type, vx, vy reflect.Value) bool {
// If there were no FilterValues, we will not detect invalid inputs,
// so manually check for them and append a validator if necessary.
// We still evaluate the options since an ignore can override invalid.
opts := s.opts
if !vx.IsValid() || !vx.CanInterface() || !vy.IsValid() || !vy.CanInterface() {
opts = Options{opts, validator{}}
}

// Evaluate all filters and apply the remaining options.
if opt := opts.filter(s, t, vx, vy); opt != nil {
if opt := s.opts.filter(s, t, vx, vy); opt != nil {
opt.apply(s, vx, vy)
return true
}
Expand Down
23 changes: 17 additions & 6 deletions cmp/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ type valuesFilter struct {

func (f valuesFilter) filter(s *state, t reflect.Type, vx, vy reflect.Value) applicableOption {
if !vx.IsValid() || !vx.CanInterface() || !vy.IsValid() || !vy.CanInterface() {
return validator{}
return nil
}
if (f.typ == nil || t.AssignableTo(f.typ)) && s.callTTBFunc(f.fnc, vx, vy) {
return f.opt.filter(s, t, vx, vy)
Expand Down Expand Up @@ -207,18 +207,29 @@ func (ignore) String() string
// missing map entries. Both values are validator only for unexported fields.
type validator struct{ core }

func (validator) filter(_ *state, _ reflect.Type, _, _ reflect.Value) applicableOption {
return validator{}
func (validator) filter(_ *state, _ reflect.Type, vx, vy reflect.Value) applicableOption {
if !vx.IsValid() || !vy.IsValid() {
return validator{}
}
if !vx.CanInterface() || !vy.CanInterface() {
return validator{}
}
return nil
}
func (validator) apply(s *state, vx, vy reflect.Value) {
// Implies missing slice element or map entry.
if !vx.IsValid() || !vy.IsValid() {
s.report(vx.IsValid() == vy.IsValid(), 0)
return
}

// Unable to Interface implies unexported field without visibility access.
if (vx.IsValid() && !vx.CanInterface()) || (vy.IsValid() && !vy.CanInterface()) {
if !vx.CanInterface() || !vy.CanInterface() {
const help = "consider using AllowUnexported or cmpopts.IgnoreUnexported"
panic(fmt.Sprintf("cannot handle unexported field: %#v\n%s", s.curPath, help))
}

// Implies missing slice element or map entry.
s.report(vx.IsValid() == vy.IsValid(), 0)
panic("not reachable")
}

// identRx represents a valid identifier according to the Go specification.
Expand Down

0 comments on commit 2e500c5

Please sign in to comment.