Skip to content

Commit

Permalink
Optimize focus to avoid allocations
Browse files Browse the repository at this point in the history
Both regex creation and ConcatenatedString() are expensive. Memoize
them within the spec iterator so we don't recalculate them later.
  • Loading branch information
smarterclayton authored and williammartin committed Jan 30, 2019
1 parent 505cc35 commit f493786
Showing 1 changed file with 33 additions and 12 deletions.
45 changes: 33 additions & 12 deletions internal/spec/specs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ import (
)

type Specs struct {
specs []*Spec
specs []*Spec
names []string

hasProgrammaticFocus bool
RegexScansFilePath bool
}

func NewSpecs(specs []*Spec) *Specs {
names := make([]string, len(specs))
for i, spec := range specs {
names[i] = spec.ConcatenatedString()
}
return &Specs{
specs: specs,
names: names,
}
}

Expand All @@ -30,10 +37,13 @@ func (e *Specs) Shuffle(r *rand.Rand) {
sort.Sort(e)
permutation := r.Perm(len(e.specs))
shuffledSpecs := make([]*Spec, len(e.specs))
names := make([]string, len(e.specs))
for i, j := range permutation {
shuffledSpecs[i] = e.specs[j]
names[i] = e.names[j]
}
e.specs = shuffledSpecs
e.names = names
}

func (e *Specs) ApplyFocus(description string, focusString string, skipString string) {
Expand Down Expand Up @@ -64,33 +74,43 @@ func (e *Specs) applyProgrammaticFocus() {

// toMatch returns a byte[] to be used by regex matchers. When adding new behaviours to the matching function,
// this is the place which we append to.
func (e *Specs) toMatch(description string, spec *Spec) []byte {
func (e *Specs) toMatch(description string, i int) []byte {
if i > len(e.names) {
return nil
}
if e.RegexScansFilePath {
return []byte(
description + " " +
spec.ConcatenatedString() + " " +
spec.subject.CodeLocation().FileName)
e.names[i] + " " +
e.specs[i].subject.CodeLocation().FileName)
} else {
return []byte(
description + " " +
spec.ConcatenatedString())
e.names[i])
}
}

func (e *Specs) applyRegExpFocusAndSkip(description string, focusString string, skipString string) {
for _, spec := range e.specs {
var focusFilter *regexp.Regexp
if focusString != "" {
focusFilter = regexp.MustCompile(focusString)
}
var skipFilter *regexp.Regexp
if skipString != "" {
skipFilter = regexp.MustCompile(skipString)
}

for i, spec := range e.specs {
matchesFocus := true
matchesSkip := false

toMatch := e.toMatch(description, spec)
toMatch := e.toMatch(description, i)

if focusString != "" {
focusFilter := regexp.MustCompile(focusString)
if focusFilter != nil {
matchesFocus = focusFilter.Match([]byte(toMatch))
}

if skipString != "" {
skipFilter := regexp.MustCompile(skipString)
if skipFilter != nil {
matchesSkip = skipFilter.Match([]byte(toMatch))
}

Expand All @@ -115,9 +135,10 @@ func (e *Specs) Len() int {
}

func (e *Specs) Less(i, j int) bool {
return e.specs[i].ConcatenatedString() < e.specs[j].ConcatenatedString()
return e.names[i] < e.names[j]
}

func (e *Specs) Swap(i, j int) {
e.names[i], e.names[j] = e.names[j], e.names[i]
e.specs[i], e.specs[j] = e.specs[j], e.specs[i]
}

0 comments on commit f493786

Please sign in to comment.