Commit 07b80113 authored by Paul Borman's avatar Paul Borman Committed by Rob Pike

text/template: improve lexer performance in finding left delimiters.

The existing implementation calls l.next for each run up to the next
instance of the left delimiter ({{).  For ascii text, this is multiple
function calls per byte.  Change to use strings.Index to find the left
delimiter.  The performace improvement ranges from 1:1 (no text outside
of {{}}'s) to multiple times faster (9:1 was seen on 8K of text with no
{{ }}'s).

Change-Id: I2f82bea63b78b6714f09a725f7b2bbb00a3448a3
Reviewed-on: https://go-review.googlesource.com/24863Reviewed-by: 's avatarRob Pike <r@golang.org>
Run-TryBot: Rob Pike <r@golang.org>
parent 8f9671d1
......@@ -236,24 +236,23 @@ const (
// lexText scans until an opening action delimiter, "{{".
func lexText(l *lexer) stateFn {
for {
delim, trimSpace := l.atLeftDelim()
if delim {
trimLength := Pos(0)
if trimSpace {
trimLength = rightTrimLength(l.input[l.start:l.pos])
}
l.pos -= trimLength
if l.pos > l.start {
l.emit(itemText)
}
l.pos += trimLength
l.ignore()
return lexLeftDelim
l.width = 0
if x := strings.Index(l.input[l.pos:], l.leftDelim); x >= 0 {
ldn := Pos(len(l.leftDelim))
l.pos += Pos(x)
trimLength := Pos(0)
if strings.HasPrefix(l.input[l.pos+ldn:], leftTrimMarker) {
trimLength = rightTrimLength(l.input[l.start:l.pos])
}
if l.next() == eof {
break
l.pos -= trimLength
if l.pos > l.start {
l.emit(itemText)
}
l.pos += trimLength
l.ignore()
return lexLeftDelim
} else {
l.pos = Pos(len(l.input))
}
// Correctly reached EOF.
if l.pos > l.start {
......@@ -263,16 +262,6 @@ func lexText(l *lexer) stateFn {
return nil
}
// atLeftDelim reports whether the lexer is at a left delimiter, possibly followed by a trim marker.
func (l *lexer) atLeftDelim() (delim, trimSpaces bool) {
if !strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
return false, false
}
// The left delim might have the marker afterwards.
trimSpaces = strings.HasPrefix(l.input[l.pos+Pos(len(l.leftDelim)):], leftTrimMarker)
return true, trimSpaces
}
// rightTrimLength returns the length of the spaces at the end of the string.
func rightTrimLength(s string) Pos {
return Pos(len(s) - len(strings.TrimRight(s, spaceChars)))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment