From 26ae43fdeeea7db6778850f76cc828b232da1e13 Mon Sep 17 00:00:00 2001 From: Albert Nigmatzianov Date: Tue, 30 May 2017 19:27:36 +0200 Subject: [PATCH] Use bytes.Buffer for tomlLexer.buffer (#166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use bytes.Buffer for tomlLexer.buffer * Add BenchmarkLexer Fix #165 name old time/op new time/op delta Lexer-4 343µs ± 1% 331µs ± 1% -3.56% (p=0.000 n=20+19) name old alloc/op new alloc/op delta Lexer-4 55.8kB ± 0% 50.8kB ± 0% -8.86% (p=0.000 n=20+20) name old allocs/op new allocs/op delta Lexer-4 2.01k ± 0% 1.84k ± 0% -8.46% (p=0.000 n=20+20) --- lexer.go | 13 +++++++------ lexer_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lexer.go b/lexer.go index 104f3b1..db3ab4e 100644 --- a/lexer.go +++ b/lexer.go @@ -6,6 +6,7 @@ package toml import ( + "bytes" "errors" "fmt" "io" @@ -24,7 +25,7 @@ type tomlLexStateFn func() tomlLexStateFn // Define lexer type tomlLexer struct { input *buffruneio.Reader // Textual source - buffer []rune // Runes composing the current token + buffer bytes.Buffer // Runes composing the current token tokens chan token depth int line int @@ -53,13 +54,13 @@ func (l *tomlLexer) next() rune { r := l.read() if r != eof { - l.buffer = append(l.buffer, r) + l.buffer.WriteRune(r) } return r } func (l *tomlLexer) ignore() { - l.buffer = make([]rune, 0) + l.buffer.Reset() l.line = l.endbufferLine l.col = l.endbufferCol } @@ -85,7 +86,7 @@ func (l *tomlLexer) emitWithValue(t tokenType, value string) { } func (l *tomlLexer) emit(t tokenType) { - l.emitWithValue(t, string(l.buffer)) + l.emitWithValue(t, l.buffer.String()) } func (l *tomlLexer) peek() rune { @@ -536,7 +537,7 @@ func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn { for r := l.peek(); r != eof; r = l.peek() { switch r { case ']': - if len(l.buffer) > 0 { + if l.buffer.Len() > 0 { l.emit(tokenKeyGroupArray) } l.next() @@ -559,7 +560,7 @@ func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn { for r := l.peek(); r != eof; r = l.peek() { switch r { case ']': - if len(l.buffer) > 0 { + if l.buffer.Len() > 0 { l.emit(tokenKeyGroup) } l.next() diff --git a/lexer_test.go b/lexer_test.go index 6b324ea..dce7a63 100644 --- a/lexer_test.go +++ b/lexer_test.go @@ -1,6 +1,7 @@ package toml import ( + "os" "strings" "testing" ) @@ -748,3 +749,31 @@ func TestLexUnknownRvalue(t *testing.T) { {Position{1, 5}, tokenError, `no value can start with \`}, }) } + +func BenchmarkLexer(b *testing.B) { + sample := `title = "Hugo: A Fast and Flexible Website Generator" +baseurl = "http://gohugo.io/" +MetaDataFormat = "yaml" +pluralizeListTitles = false + +[params] + description = "Documentation of Hugo, a fast and flexible static site generator built with love by spf13, bep and friends in Go" + author = "Steve Francia (spf13) and friends" + release = "0.22-DEV" + +[[menu.main]] + name = "Download Hugo" + pre = "" + url = "https://github.com/spf13/hugo/releases" + weight = -200 +` + rd := strings.NewReader(sample) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + rd.Seek(0, os.SEEK_SET) + ch := lexToml(rd) + for _ = range ch { + } + } +}