Skip to content

Commit

Permalink
go/doc: compile regexps lazily
Browse files Browse the repository at this point in the history
Compile go/doc's 4 regexps lazily, on demand.

Also, add a test for the one that had no test coverage.

This reduces init-time CPU as well as heap by ~20KB when they're not
used, which seems to be common enough. As an example, cmd/doc only
seems to use 1 of them. (as noted by temporary print statements)

Updates #26775

Change-Id: I85df89b836327a53fb8e1ace3f92480374270368
Reviewed-on: https://go-review.googlesource.com/127875
Run-TryBot: Brad Fitzpatrick <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
  • Loading branch information
bradfitz committed Aug 21, 2018
1 parent c544e0f commit fc5107c
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/go/build/deps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ var pkgDeps = map[string][]string{

// Go parser.
"go/ast": {"L4", "OS", "go/scanner", "go/token"},
"go/doc": {"L4", "go/ast", "go/token", "regexp", "text/template"},
"go/doc": {"L4", "OS", "go/ast", "go/token", "regexp", "text/template"},
"go/parser": {"L4", "OS", "go/ast", "go/scanner", "go/token"},
"go/printer": {"L4", "OS", "go/ast", "go/scanner", "go/token", "text/tabwriter"},
"go/scanner": {"L4", "OS", "go/token"},
Expand Down
5 changes: 2 additions & 3 deletions src/go/doc/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package doc

import (
"io"
"regexp"
"strings"
"text/template" // for HTMLEscape
"unicode"
Expand Down Expand Up @@ -63,7 +62,7 @@ const (
urlRx = protoPart + `://` + hostPart + pathPart
)

var matchRx = regexp.MustCompile(`(` + urlRx + `)|(` + identRx + `)`)
var matchRx = newLazyRE(`(` + urlRx + `)|(` + identRx + `)`)

var (
html_a = []byte(`<a href="`)
Expand Down Expand Up @@ -276,7 +275,7 @@ type block struct {
lines []string
}

var nonAlphaNumRx = regexp.MustCompile(`[^a-zA-Z0-9]`)
var nonAlphaNumRx = newLazyRE(`[^a-zA-Z0-9]`)

func anchorID(line string) string {
// Add a "hdr-" prefix to avoid conflicting with IDs used for package symbols.
Expand Down
9 changes: 9 additions & 0 deletions src/go/doc/doc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,12 @@ func Test(t *testing.T) {
test(t, AllDecls)
test(t, AllMethods)
}

func TestAnchorID(t *testing.T) {
const in = "Important Things 2 Know & Stuff"
const want = "hdr-Important_Things_2_Know___Stuff"
got := anchorID(in)
if got != want {
t.Errorf("anchorID(%q) = %q; want %q", in, got, want)
}
}
51 changes: 51 additions & 0 deletions src/go/doc/lazyre.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package doc

import (
"os"
"regexp"
"strings"
"sync"
)

type lazyRE struct {
str string
once sync.Once
rx *regexp.Regexp
}

func (r *lazyRE) re() *regexp.Regexp {
r.once.Do(r.build)
return r.rx
}

func (r *lazyRE) build() {
r.rx = regexp.MustCompile(r.str)
r.str = ""
}

func (r *lazyRE) FindStringSubmatchIndex(s string) []int {
return r.re().FindStringSubmatchIndex(s)
}

func (r *lazyRE) ReplaceAllString(src, repl string) string {
return r.re().ReplaceAllString(src, repl)
}

func (r *lazyRE) MatchString(s string) bool {
return r.re().MatchString(s)
}

var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")

func newLazyRE(str string) *lazyRE {
lr := &lazyRE{str: str}
if inTest {
// In tests, always compile the regexps early.
lr.re()
}
return lr
}
7 changes: 3 additions & 4 deletions src/go/doc/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package doc
import (
"go/ast"
"go/token"
"regexp"
"sort"
"strconv"
)
Expand Down Expand Up @@ -425,9 +424,9 @@ func (r *reader) readFunc(fun *ast.FuncDecl) {
}

var (
noteMarker = `([A-Z][A-Z]+)\(([^)]+)\):?` // MARKER(uid), MARKER at least 2 chars, uid at least 1 char
noteMarkerRx = regexp.MustCompile(`^[ \t]*` + noteMarker) // MARKER(uid) at text start
noteCommentRx = regexp.MustCompile(`^/[/*][ \t]*` + noteMarker) // MARKER(uid) at comment start
noteMarker = `([A-Z][A-Z]+)\(([^)]+)\):?` // MARKER(uid), MARKER at least 2 chars, uid at least 1 char
noteMarkerRx = newLazyRE(`^[ \t]*` + noteMarker) // MARKER(uid) at text start
noteCommentRx = newLazyRE(`^/[/*][ \t]*` + noteMarker) // MARKER(uid) at comment start
)

// readNote collects a single note from a sequence of comments.
Expand Down

0 comments on commit fc5107c

Please sign in to comment.