Skip to content

Commit

Permalink
template: add ASCII fast path for lexer.next
Browse files Browse the repository at this point in the history
lexer.next is a hot function, as demonstrated by profiling. Most programs
will consist of ASCII characters only, which we can optimize for. Ideally
DecodeRuneInString would be inlined here and this wouldn't be a problem at all,
but that won't be the case until golang/go#31666
is resolved.

name                 old time/op    new time/op    delta
Parse/lorem_ipsum-4     733ns ± 2%     733ns ± 2%    ~     (p=0.933 n=8+8)
Parse/short-4          16.6µs ± 1%    15.5µs ± 2%  -6.75%  (p=0.000 n=8+8)
Parse/medium-4         40.1µs ± 1%    38.7µs ± 1%  -3.51%  (p=0.000 n=8+8)
Parse/long-4            123µs ± 1%     115µs ± 1%  -5.86%  (p=0.001 n=7+7)
Parse/very-long-4       416µs ± 1%     396µs ± 1%  -4.70%  (p=0.000 n=8+8)

name                 old alloc/op   new alloc/op   delta
Parse/lorem_ipsum-4    1.16kB ± 0%    1.16kB ± 0%    ~     (all equal)
Parse/short-4          5.42kB ± 0%    5.42kB ± 0%    ~     (all equal)
Parse/medium-4         12.6kB ± 0%    12.6kB ± 0%    ~     (all equal)
Parse/long-4           35.3kB ± 0%    35.3kB ± 0%    ~     (all equal)
Parse/very-long-4       113kB ± 0%     113kB ± 0%    ~     (all equal)

name                 old allocs/op  new allocs/op  delta
Parse/lorem_ipsum-4      10.0 ± 0%      10.0 ± 0%    ~     (all equal)
Parse/short-4             107 ± 0%       107 ± 0%    ~     (all equal)
Parse/medium-4            296 ± 0%       296 ± 0%    ~     (all equal)
Parse/long-4              777 ± 0%       777 ± 0%    ~     (all equal)
Parse/very-long-4       2.61k ± 0%     2.61k ± 0%    ~     (all equal)
  • Loading branch information
jo3-l committed Aug 27, 2022
1 parent 3193b25 commit f8be9e6
Showing 1 changed file with 11 additions and 1 deletion.
12 changes: 11 additions & 1 deletion lib/template/parse/lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,17 @@ func (l *lexer) next() rune {
l.width = 0
return eof
}
r, w := utf8.DecodeRuneInString(l.input[l.pos:])

var (
r rune
w int
)
// Fast path for ASCII. See https://github.com/golang/go/issues/31666.
if l.input[l.pos] < utf8.RuneSelf {
r, w = rune(l.input[l.pos]), 1
} else {
r, w = utf8.DecodeRuneInString(l.input[l.pos:])
}
l.width = Pos(w)
l.pos += l.width
if r == '\n' {
Expand Down

0 comments on commit f8be9e6

Please sign in to comment.