Skip to content

Commit

Permalink
feat(perf): Precompile getPattern regexps
Browse files Browse the repository at this point in the history
This greatly improves the allocations:

    $ go test -benchmem -bench=.
    goos: darwin
    goarch: arm64
    pkg: github.com/hairyhenderson/go-codeowners
    BenchmarkParseCodeowners-10        70927             16857 ns/op           27211 B/op        242 allocs/op
    PASS
    ok      github.com/hairyhenderson/go-codeowners 5.297s

This reduces the allocations in 62%:

    $ benchstat main.log precompile.log
    goos: darwin
    goarch: arm64
    pkg: github.com/hairyhenderson/go-codeowners
                       │  main.log   │           precompile.log            │
                       │   sec/op    │   sec/op     vs base                │
    ParseCodeowners-10   38.72µ ± 2%   17.63µ ± 6%  -54.46% (p=0.000 n=10)

                       │   main.log   │            precompile.log            │
                       │     B/op     │     B/op      vs base                │
    ParseCodeowners-10   59.95Ki ± 0%   26.56Ki ± 0%  -55.70% (p=0.000 n=10)

                       │  main.log  │           precompile.log           │
                       │ allocs/op  │ allocs/op   vs base                │
    ParseCodeowners-10   641.0 ± 0%   242.0 ± 0%  -62.25% (p=0.000 n=10)
  • Loading branch information
inkel authored and hairyhenderson committed Sep 27, 2024
1 parent 43a0da6 commit 36a9095
Showing 1 changed file with 20 additions and 8 deletions.
28 changes: 20 additions & 8 deletions codeowners.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,35 +223,47 @@ func (c *Codeowners) Owners(path string) []string {
return nil
}

// precompile all regular expressions
var (
reCommentIgnore = regexp.MustCompile(`^(\\#|\\!)`)
rePrependSlash = regexp.MustCompile(`([^\/+])/.*\*\.`)
reEscapeDot = regexp.MustCompile(`\.`)
reDoubleStar1 = regexp.MustCompile(`/\*\*/`)
reDoubleStar2 = regexp.MustCompile(`\*\*/`)
reDoubleStar3 = regexp.MustCompile(`/\*\*`)
reEscapeStar1 = regexp.MustCompile(`\\\*`)
reEscapeStar2 = regexp.MustCompile(`\*`)
)

// based on github.com/sabhiram/go-gitignore
// but modified so that 'dir/*' only matches files in 'dir/'
func getPattern(line string) (*regexp.Regexp, error) {
// when # or ! is escaped with a \
if regexp.MustCompile(`^(\\#|\\!)`).MatchString(line) {
if reCommentIgnore.MatchString(line) {
line = line[1:]
}

// If we encounter a foo/*.blah in a folder, prepend the / char
if regexp.MustCompile(`([^\/+])/.*\*\.`).MatchString(line) && line[0] != '/' {
if rePrependSlash.MatchString(line) && line[0] != '/' {
line = "/" + line
}

// Handle escaping the "." char
line = regexp.MustCompile(`\.`).ReplaceAllString(line, `\.`)
line = reEscapeDot.ReplaceAllString(line, `\.`)

magicStar := "#$~"

// Handle "/**/" usage
if strings.HasPrefix(line, "/**/") {
line = line[1:]
}
line = regexp.MustCompile(`/\*\*/`).ReplaceAllString(line, `(/|/.+/)`)
line = regexp.MustCompile(`\*\*/`).ReplaceAllString(line, `(|.`+magicStar+`/)`)
line = regexp.MustCompile(`/\*\*`).ReplaceAllString(line, `(|/.`+magicStar+`)`)
line = reDoubleStar1.ReplaceAllString(line, `(/|/.+/)`)
line = reDoubleStar2.ReplaceAllString(line, `(|.`+magicStar+`/)`)
line = reDoubleStar3.ReplaceAllString(line, `(|/.`+magicStar+`)`)

// Handle escaping the "*" char
line = regexp.MustCompile(`\\\*`).ReplaceAllString(line, `\`+magicStar)
line = regexp.MustCompile(`\*`).ReplaceAllString(line, `([^/]*)`)
line = reEscapeStar1.ReplaceAllString(line, `\`+magicStar)
line = reEscapeStar2.ReplaceAllString(line, `([^/]*)`)

// Handle escaping the "?" char
line = strings.ReplaceAll(line, "?", `\?`)
Expand Down

0 comments on commit 36a9095

Please sign in to comment.