I was looking at text/template/parse/lex.go and noticed it seemed to be
very inefficient in how it searched for {{ in its input.  I rewrote lexText
to us strings.Index rather than calling l.next() for every single rune in
the string.  The results were up to a 9x speed improvement, depending on
the density of {{'s in the text.

My results were:

BenchmarkOldR512-4  100000     12300 ns/op
BenchmarkNewR512-4  300000      4513 ns/op
BenchmarkOldT512-4  100000     23600 ns/op
BenchmarkNewT512-4  100000     13898 ns/op
BenchmarkOldR8k-4   10000    133261 ns/op
BenchmarkNewR8k-4  100000     14852 ns/op
BenchmarkOldT8k-4    5000    264654 ns/op
BenchmarkNewT8k-4   10000    135056 ns/op
BenchmarkOldMany-4     300   5577909 ns/op
BenchmarkNewMany-4     300   5632914 ns/op

BenchmarkOldR512-4  100000     12100 ns/op
BenchmarkNewR512-4  300000      4507 ns/op
BenchmarkOldT512-4  100000     23297 ns/op
BenchmarkNewT512-4  100000     14699 ns/op
BenchmarkOldR8k-4   10000    136474 ns/op
BenchmarkNewR8k-4  100000     16566 ns/op
BenchmarkOldT8k-4    5000    266256 ns/op
BenchmarkNewT8k-4   10000    137201 ns/op
BenchmarkOldMany-4     300   5606573 ns/op
BenchmarkNewMany-4     300   5596660 ns/op

BenchmarkOldR512-4  100000     12150 ns/op
BenchmarkNewR512-4  300000      4405 ns/op
BenchmarkOldT512-4  100000     21539 ns/op
BenchmarkNewT512-4  100000     13735 ns/op
BenchmarkOldR8k-4   10000    133586 ns/op
BenchmarkNewR8k-4  100000     14076 ns/op
BenchmarkOldT8k-4    5000    264374 ns/op
BenchmarkNewT8k-4   10000    132618 ns/op
BenchmarkOldMany-4     300   5622040 ns/op
BenchmarkNewMany-4     300   5638461 ns/op


R512 was 512 bytes of Lorem Ipsum text with no {{}}'s
R8K was 8,192 bytes of Lorem Ipsum text with no {{}}'s

The T versions are the same, but with all occurrences of ipsum changed to
{{.}}
(3 times in T512 and 13 times in T8K).

The Many version was the string "{{.}}" repeated 1000 times.

The old code:

        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
                }
                if l.next() == eof {
                        break
                }
        }


The new code:

        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])
                }
                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))
        }

Is this something that would be accepted into the standard library?

Thanks,

    -Paul

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to