From 36af432f9354ed912b91788bb1ca80d60b917364 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Wed, 14 Sep 2016 22:04:39 +0900 Subject: [PATCH 1/8] add benchmark --- go/vimlparser_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/go/vimlparser_test.go b/go/vimlparser_test.go index 3236c73..67f4a8a 100644 --- a/go/vimlparser_test.go +++ b/go/vimlparser_test.go @@ -13,7 +13,7 @@ import ( "testing" ) -func recovert(t *testing.T) { +func recovert(t testing.TB) { if r := recover(); r != nil { t.Errorf("Recovered: %v\n%s", r, debug.Stack()) } @@ -174,6 +174,16 @@ func readlines(path string) ([]string, error) { } func TestVimLParser_VimLParser(t *testing.T) { + testParseVimLParser(t) +} + +func BenchmarkVimLParser_VimLParser(b *testing.B) { + for i := 0; i < b.N; i++ { + testParseVimLParser(b) + } +} + +func testParseVimLParser(t testing.TB) { defer recovert(t) p, err := build.Default.Import(basePkg, "", build.FindOnly) if err != nil { From ce9df412fdf1386a0a503923c43a4d08c4d631c9 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Wed, 14 Sep 2016 22:30:59 +0900 Subject: [PATCH 2/8] use builtin len instead of viml_len to avoid allocations benchmark old ns/op new ns/op delta BenchmarkVimLParser_VimLParser-4 522557385 384606362 -26.40% --- go/_test/let.go | 6 ++-- go/gocompiler.vim | 2 ++ go/type.go | 2 +- go/vimlfunc.go | 6 +--- go/vimlfunc_test.go | 20 ------------ go/vimlparser.go | 74 ++++++++++++++++++++++----------------------- 6 files changed, 44 insertions(+), 66 deletions(-) diff --git a/go/_test/let.go b/go/_test/let.go index cc099c6..dc2a6b9 100644 --- a/go/_test/let.go +++ b/go/_test/let.go @@ -32,20 +32,20 @@ if x { func F() { var cmd *Cmd = nil for _, x := range builtin_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = x break } } if self.neovim { for _, x := range neovim_additional_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = x break } } for _, x := range neovim_removed_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = nil break } diff --git a/go/gocompiler.vim b/go/gocompiler.vim index 716c4cd..e94d363 100644 --- a/go/gocompiler.vim +++ b/go/gocompiler.vim @@ -871,6 +871,8 @@ function s:GoCompiler.compile_call(node) if index(s:viml_builtin_functions, left) != -1 if left == 'add' let left = 'append' + elseif left == 'len' + let left = 'len' else let left = printf('viml_%s', left) endif diff --git a/go/type.go b/go/type.go index cf1f17b..303706e 100644 --- a/go/type.go +++ b/go/type.go @@ -200,7 +200,7 @@ func (self *Compiler) __init__() { } func (self *Compiler) out(f string, args ...interface{}) { - if viml_len(args) == 0 { + if len(args) == 0 { if string(f[0]) == ")" { self.lines[len(self.lines)-1] += f } else { diff --git a/go/vimlfunc.go b/go/vimlfunc.go index 59ebdf8..3834b0a 100644 --- a/go/vimlfunc.go +++ b/go/vimlfunc.go @@ -77,7 +77,7 @@ func init() { type vimlList interface{} func viml_empty(obj interface{}) bool { - return viml_len(obj) == 0 + return reflect.ValueOf(obj).Len() == 0 } func viml_equalci(a, b string) bool { @@ -125,10 +125,6 @@ func viml_join(lst vimlList, sep string) string { return strings.Join(ss, sep) } -func viml_len(obj interface{}) int { - return reflect.ValueOf(obj).Len() -} - func viml_printf(f string, args ...interface{}) string { return fmt.Sprintf(f, args...) } diff --git a/go/vimlfunc_test.go b/go/vimlfunc_test.go index 9fa164d..1019761 100644 --- a/go/vimlfunc_test.go +++ b/go/vimlfunc_test.go @@ -5,26 +5,6 @@ import ( "testing" ) -func TestViml_len(t *testing.T) { - tests := []struct { - in interface{} - want int - }{ - {in: "hoge", want: 4}, - {in: "あいうえお", want: 15}, - {in: "", want: 0}, - {in: []string{"hoge", "foo"}, want: 2}, - {in: []int{1, 2, 3}, want: 3}, - {in: []interface{}{1, "2", float64(3)}, want: 3}, - } - for _, tt := range tests { - got := viml_len(tt.in) - if got != tt.want { - t.Errorf("viml_len(%v) = %v, want %v", tt.in, got, tt.want) - } - } -} - func TestViml_eqreg(t *testing.T) { tests := []struct { in string diff --git a/go/vimlparser.go b/go/vimlparser.go index b369d30..2f05b2e 100644 --- a/go/vimlparser.go +++ b/go/vimlparser.go @@ -427,55 +427,55 @@ func (self *VimLParser) parse_command_modifiers() { var k = self.reader.read_alpha() var c = self.reader.peekn(1) self.reader.skip_white() - if viml_stridx("aboveleft", k) == 0 && viml_len(k) >= 3 { + if viml_stridx("aboveleft", k) == 0 && len(k) >= 3 { // abo\%[veleft] modifiers = append(modifiers, map[string]interface{}{"name":"aboveleft"}) - } else if viml_stridx("belowright", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("belowright", k) == 0 && len(k) >= 3 { // bel\%[owright] modifiers = append(modifiers, map[string]interface{}{"name":"belowright"}) - } else if viml_stridx("browse", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("browse", k) == 0 && len(k) >= 3 { // bro\%[wse] modifiers = append(modifiers, map[string]interface{}{"name":"browse"}) - } else if viml_stridx("botright", k) == 0 && viml_len(k) >= 2 { + } else if viml_stridx("botright", k) == 0 && len(k) >= 2 { // bo\%[tright] modifiers = append(modifiers, map[string]interface{}{"name":"botright"}) - } else if viml_stridx("confirm", k) == 0 && viml_len(k) >= 4 { + } else if viml_stridx("confirm", k) == 0 && len(k) >= 4 { // conf\%[irm] modifiers = append(modifiers, map[string]interface{}{"name":"confirm"}) - } else if viml_stridx("keepmarks", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("keepmarks", k) == 0 && len(k) >= 3 { // kee\%[pmarks] modifiers = append(modifiers, map[string]interface{}{"name":"keepmarks"}) - } else if viml_stridx("keepalt", k) == 0 && viml_len(k) >= 5 { + } else if viml_stridx("keepalt", k) == 0 && len(k) >= 5 { // keepa\%[lt] modifiers = append(modifiers, map[string]interface{}{"name":"keepalt"}) - } else if viml_stridx("keepjumps", k) == 0 && viml_len(k) >= 5 { + } else if viml_stridx("keepjumps", k) == 0 && len(k) >= 5 { // keepj\%[umps] modifiers = append(modifiers, map[string]interface{}{"name":"keepjumps"}) - } else if viml_stridx("keeppatterns", k) == 0 && viml_len(k) >= 5 { + } else if viml_stridx("keeppatterns", k) == 0 && len(k) >= 5 { // keepp\%[atterns] modifiers = append(modifiers, map[string]interface{}{"name":"keeppatterns"}) - } else if viml_stridx("hide", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("hide", k) == 0 && len(k) >= 3 { //hid\%[e] if self.ends_excmds(c) { break } modifiers = append(modifiers, map[string]interface{}{"name":"hide"}) - } else if viml_stridx("lockmarks", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("lockmarks", k) == 0 && len(k) >= 3 { // loc\%[kmarks] modifiers = append(modifiers, map[string]interface{}{"name":"lockmarks"}) - } else if viml_stridx("leftabove", k) == 0 && viml_len(k) >= 5 { + } else if viml_stridx("leftabove", k) == 0 && len(k) >= 5 { // lefta\%[bove] modifiers = append(modifiers, map[string]interface{}{"name":"leftabove"}) - } else if viml_stridx("noautocmd", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("noautocmd", k) == 0 && len(k) >= 3 { // noa\%[utocmd] modifiers = append(modifiers, map[string]interface{}{"name":"noautocmd"}) - } else if viml_stridx("rightbelow", k) == 0 && viml_len(k) >= 6 { + } else if viml_stridx("rightbelow", k) == 0 && len(k) >= 6 { //rightb\%[elow] modifiers = append(modifiers, map[string]interface{}{"name":"rightbelow"}) - } else if viml_stridx("sandbox", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("sandbox", k) == 0 && len(k) >= 3 { // san\%[dbox] modifiers = append(modifiers, map[string]interface{}{"name":"sandbox"}) - } else if viml_stridx("silent", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("silent", k) == 0 && len(k) >= 3 { // sil\%[ent] if c == "!" { self.reader.get() @@ -490,16 +490,16 @@ func (self *VimLParser) parse_command_modifiers() { } else { modifiers = append(modifiers, map[string]interface{}{"name":"tab"}) } - } else if viml_stridx("topleft", k) == 0 && viml_len(k) >= 2 { + } else if viml_stridx("topleft", k) == 0 && len(k) >= 2 { // to\%[pleft] modifiers = append(modifiers, map[string]interface{}{"name":"topleft"}) - } else if viml_stridx("unsilent", k) == 0 && viml_len(k) >= 3 { + } else if viml_stridx("unsilent", k) == 0 && len(k) >= 3 { // uns\%[ilent] modifiers = append(modifiers, map[string]interface{}{"name":"unsilent"}) - } else if viml_stridx("vertical", k) == 0 && viml_len(k) >= 4 { + } else if viml_stridx("vertical", k) == 0 && len(k) >= 4 { // vert\%[ical] modifiers = append(modifiers, map[string]interface{}{"name":"vertical"}) - } else if viml_stridx("verbose", k) == 0 && viml_len(k) >= 4 { + } else if viml_stridx("verbose", k) == 0 && len(k) >= 4 { // verb\%[ose] if d != "" { modifiers = append(modifiers, map[string]interface{}{"name":"verbose", "count":viml_str2nr(d, 10)}) @@ -803,7 +803,7 @@ func (self *VimLParser) find_command() *Cmd { name = self.reader.read_alpha() if name != "del" && viml_eqregh(name, "\\v^d%[elete][lp]$") { self.reader.seek_set(pos) - name = self.reader.getn(viml_len(name) - 1) + name = self.reader.getn(len(name) - 1) } } if name == "" { @@ -814,20 +814,20 @@ func (self *VimLParser) find_command() *Cmd { } var cmd *Cmd = nil for _, x := range builtin_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = x break } } if self.neovim { for _, x := range neovim_additional_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = x break } } for _, x := range neovim_removed_commands { - if viml_stridx(x.name, name) == 0 && viml_len(name) >= x.minlen { + if viml_stridx(x.name, name) == 0 && len(name) >= x.minlen { cmd = nil break } @@ -2543,7 +2543,7 @@ func (self *ExprParser) parse_expr8() *VimNode { } } } - if viml_len(node.rlist) > MAX_FUNC_ARGS { + if len(node.rlist) > MAX_FUNC_ARGS { // TODO: funcname E740: Too many arguments for function: %s panic(Err("E740: Too many arguments for function", node.pos)) } @@ -2723,7 +2723,7 @@ func (self *ExprParser) parse_identifier() *VimNode { self.reader.skip_white() var npos = self.reader.getpos() var curly_parts = self.parse_curly_parts() - if viml_len(curly_parts) == 1 && curly_parts[0].type_ == NODE_CURLYNAMEPART { + if len(curly_parts) == 1 && curly_parts[0].type_ == NODE_CURLYNAMEPART { var node = Node(NODE_IDENTIFIER) node.pos = npos node.value = curly_parts[0].value @@ -2894,14 +2894,14 @@ func (self *LvalueParser) parse_lv9() *VimNode { func (self *StringReader) __init__(lines []string) { var lnum = 0 - for lnum < viml_len(lines) { + for lnum < len(lines) { var col = 0 for _, c := range viml_split(lines[lnum], "\\zs") { self.buf = append(self.buf, c) self.pos = append(self.pos, []interface{}{lnum + 1, col + 1}) - col += viml_len(c) + col += len(c) } - for lnum + 1 < viml_len(lines) && viml_eqregh(lines[lnum + 1], "^\\s*\\\\") { + for lnum + 1 < len(lines) && viml_eqregh(lines[lnum + 1], "^\\s*\\\\") { var skip = true col = 0 for _, c := range viml_split(lines[lnum + 1], "\\zs") { @@ -2913,7 +2913,7 @@ func (self *StringReader) __init__(lines []string) { self.buf = append(self.buf, c) self.pos = append(self.pos, []interface{}{lnum + 2, col + 1}) } - col += viml_len(c) + col += len(c) } lnum += 1 } @@ -2927,7 +2927,7 @@ func (self *StringReader) __init__(lines []string) { } func (self *StringReader) eof() bool { - return self.i >= viml_len(self.buf) + return self.i >= len(self.buf) } func (self *StringReader) tell() int { @@ -2943,25 +2943,25 @@ func (self *StringReader) seek_cur(i int) { } func (self *StringReader) seek_end(i int) { - self.i = viml_len(self.buf) + i + self.i = len(self.buf) + i } func (self *StringReader) p(i int) string { - if self.i >= viml_len(self.buf) { + if self.i >= len(self.buf) { return "" } return self.buf[self.i + i] } func (self *StringReader) peek() string { - if self.i >= viml_len(self.buf) { + if self.i >= len(self.buf) { return "" } return self.buf[self.i] } func (self *StringReader) get() string { - if self.i >= viml_len(self.buf) { + if self.i >= len(self.buf) { return "" } self.i += 1 @@ -2978,7 +2978,7 @@ func (self *StringReader) peekn(n int) string { func (self *StringReader) getn(n int) string { var r = "" var j = 0 - for self.i < viml_len(self.buf) && (n < 0 || j < n) { + for self.i < len(self.buf) && (n < 0 || j < n) { var c = self.buf[self.i] if c == "" { break @@ -3003,7 +3003,7 @@ func (self *StringReader) readline() string { func (self *StringReader) getstr(begin *pos, end *pos) string { var r = "" for _, i := range viml_range(begin.i, end.i - 1) { - if i >= viml_len(self.buf) { + if i >= len(self.buf) { break } var c = self.buf[i] From c18ec64170f3f8189ec52b5603b11b58f60c42ad Mon Sep 17 00:00:00 2001 From: haya14busa Date: Wed, 14 Sep 2016 22:40:14 +0900 Subject: [PATCH 3/8] little improvement of viml_split before: . . 140:func viml_split(s string, sep string) []string { . . 141: if sep == `\zs` { . . 142: var ss []string . . 143: for _, r := range s { 58.05MB 58.05MB 144: ss = append(ss, string(r)) . . 145: } . . 146: return ss . . 147: } . . 148: panic("NotImplemented viml_split") . . 149:} after: . . 140:func viml_split(s string, sep string) []string { . . 141: if sep == `\zs` { 21.02MB 21.02MB 142: ss := make([]string, 0, len(s)) . . 143: for _, r := range s { 4MB 4MB 144: ss = append(ss, string(r)) . . 145: } . . 146: return ss . . 147: } . . 148: panic("NotImplemented viml_split") . . 149:} --- go/vimlfunc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/vimlfunc.go b/go/vimlfunc.go index 3834b0a..caf8f27 100644 --- a/go/vimlfunc.go +++ b/go/vimlfunc.go @@ -139,7 +139,7 @@ func viml_range(start, end int) []int { func viml_split(s string, sep string) []string { if sep == `\zs` { - var ss []string + ss := make([]string, 0, len(s)) for _, r := range s { ss = append(ss, string(r)) } From 15f9979df1ddac2b464e87a8dc50a4e16917104f Mon Sep 17 00:00:00 2001 From: haya14busa Date: Wed, 14 Sep 2016 23:00:36 +0900 Subject: [PATCH 4/8] write StringReader.__init__() by hand and use &pos{} instead of []interface{}{lnum, col} benchmark old ns/op new ns/op delta BenchmarkVimLParser_VimLParser-4 366894571 295205749 -19.54% --- go/_test/special.vim | 4 ++++ go/gocompiler.vim | 2 +- go/type.go | 42 ++++++++++++++++++++++++++++++++++++++---- go/vimlparser.go | 34 ---------------------------------- 4 files changed, 43 insertions(+), 39 deletions(-) diff --git a/go/_test/special.vim b/go/_test/special.vim index 855006f..134c149 100644 --- a/go/_test/special.vim +++ b/go/_test/special.vim @@ -11,6 +11,10 @@ function! s:ExprTokenizer.token() " skip ExprTokenizer.token endfunction +function! s:StringReader.__init__() + " skip StringReader.__init__ +endfunction + function! s:StringReader.getpos() " skip StringReader.getpos endfunction diff --git a/go/gocompiler.vim b/go/gocompiler.vim index e94d363..51e10b2 100644 --- a/go/gocompiler.vim +++ b/go/gocompiler.vim @@ -347,7 +347,7 @@ function s:GoCompiler.compile_function(node) let [_0, struct, name; _] = matchlist(left, '^\(.*\)\.\(.*\)$') if name == 'new' \ || (struct == 'ExprTokenizer' && name == 'token') - \ || (struct == 'StringReader' && name == 'getpos') + \ || (struct == 'StringReader' && (name == 'getpos' || name == '__init__')) \ || (struct == 'VimLParser' && (name =~ '\(push\|pop\)_context\|__init__')) \ || (struct == 'Compiler' && ( \ name == '__init__' diff --git a/go/type.go b/go/type.go index 303706e..fd9dbc7 100644 --- a/go/type.go +++ b/go/type.go @@ -167,7 +167,7 @@ func NewLvalueParser(reader *StringReader) *LvalueParser { type StringReader struct { i int - pos [][]interface{} // (lnum, col int) + pos []*pos buf []string } @@ -177,10 +177,44 @@ func NewStringReader(lines []string) *StringReader { return obj } +func (self *StringReader) __init__(lines []string) { + var lnum = 0 + for lnum < len(lines) { + var col = 0 + for _, c := range viml_split(lines[lnum], "\\zs") { + self.buf = append(self.buf, c) + self.pos = append(self.pos, &pos{lnum: lnum + 1, col: col + 1}) + col += len(c) + } + for lnum+1 < len(lines) && viml_eqregh(lines[lnum+1], "^\\s*\\\\") { + var skip = true + col = 0 + for _, c := range viml_split(lines[lnum+1], "\\zs") { + if skip { + if c == "\\" { + skip = false + } + } else { + self.buf = append(self.buf, c) + self.pos = append(self.pos, &pos{lnum: lnum + 2, col: col + 1}) + } + col += len(c) + } + lnum += 1 + } + self.buf = append(self.buf, "") + self.pos = append(self.pos, &pos{lnum: lnum + 1, col: col + 1}) + lnum += 1 + } + // for + self.pos = append(self.pos, &pos{lnum: lnum + 1, col: 0}) + self.i = 0 +} + func (self *StringReader) getpos() *pos { - var p = self.pos[self.i] - var lnum, col = p[0].(int), p[1].(int) - return &pos{i: self.i, lnum: lnum, col: col} + p := self.pos[self.i] + p.i = self.i + return p } type Compiler struct { diff --git a/go/vimlparser.go b/go/vimlparser.go index 2f05b2e..a092aaa 100644 --- a/go/vimlparser.go +++ b/go/vimlparser.go @@ -2892,40 +2892,6 @@ func (self *LvalueParser) parse_lv9() *VimNode { return node } -func (self *StringReader) __init__(lines []string) { - var lnum = 0 - for lnum < len(lines) { - var col = 0 - for _, c := range viml_split(lines[lnum], "\\zs") { - self.buf = append(self.buf, c) - self.pos = append(self.pos, []interface{}{lnum + 1, col + 1}) - col += len(c) - } - for lnum + 1 < len(lines) && viml_eqregh(lines[lnum + 1], "^\\s*\\\\") { - var skip = true - col = 0 - for _, c := range viml_split(lines[lnum + 1], "\\zs") { - if skip { - if c == "\\" { - skip = false - } - } else { - self.buf = append(self.buf, c) - self.pos = append(self.pos, []interface{}{lnum + 2, col + 1}) - } - col += len(c) - } - lnum += 1 - } - self.buf = append(self.buf, "") - self.pos = append(self.pos, []interface{}{lnum + 1, col + 1}) - lnum += 1 - } - // for - self.pos = append(self.pos, []interface{}{lnum + 1, 0}) - self.i = 0 -} - func (self *StringReader) eof() bool { return self.i >= len(self.buf) } From 5d93cfda53d79758b1948a17b89b0231fadc2648 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Wed, 14 Sep 2016 23:17:41 +0900 Subject: [PATCH 5/8] initialize StringReader.buf and StringReader.pos size in advance benchmark old ns/op new ns/op delta BenchmarkVimLParser_VimLParser-4 295205749 262219875 -11.17% --- go/type.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/go/type.go b/go/type.go index fd9dbc7..cb96757 100644 --- a/go/type.go +++ b/go/type.go @@ -178,6 +178,12 @@ func NewStringReader(lines []string) *StringReader { } func (self *StringReader) __init__(lines []string) { + size := 0 + for _, l := range lines { + size += len(l) + } + self.buf = make([]string, 0, size) + self.pos = make([]*pos, 0, size) var lnum = 0 for lnum < len(lines) { var col = 0 From 331a0fe1d14e4705d66402b1f43bd5c0794792e3 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Wed, 14 Sep 2016 23:29:27 +0900 Subject: [PATCH 6/8] use pos instead of *pos internally in StringReader benchmark old ns/op new ns/op delta BenchmarkVimLParser_VimLParser-4 262219875 248887206 -5.08% --- go/type.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/go/type.go b/go/type.go index cb96757..742d1bc 100644 --- a/go/type.go +++ b/go/type.go @@ -167,7 +167,7 @@ func NewLvalueParser(reader *StringReader) *LvalueParser { type StringReader struct { i int - pos []*pos + pos []pos buf []string } @@ -183,13 +183,13 @@ func (self *StringReader) __init__(lines []string) { size += len(l) } self.buf = make([]string, 0, size) - self.pos = make([]*pos, 0, size) + self.pos = make([]pos, 0, size) var lnum = 0 for lnum < len(lines) { var col = 0 for _, c := range viml_split(lines[lnum], "\\zs") { self.buf = append(self.buf, c) - self.pos = append(self.pos, &pos{lnum: lnum + 1, col: col + 1}) + self.pos = append(self.pos, pos{lnum: lnum + 1, col: col + 1}) col += len(c) } for lnum+1 < len(lines) && viml_eqregh(lines[lnum+1], "^\\s*\\\\") { @@ -202,25 +202,25 @@ func (self *StringReader) __init__(lines []string) { } } else { self.buf = append(self.buf, c) - self.pos = append(self.pos, &pos{lnum: lnum + 2, col: col + 1}) + self.pos = append(self.pos, pos{lnum: lnum + 2, col: col + 1}) } col += len(c) } lnum += 1 } self.buf = append(self.buf, "") - self.pos = append(self.pos, &pos{lnum: lnum + 1, col: col + 1}) + self.pos = append(self.pos, pos{lnum: lnum + 1, col: col + 1}) lnum += 1 } // for - self.pos = append(self.pos, &pos{lnum: lnum + 1, col: 0}) + self.pos = append(self.pos, pos{lnum: lnum + 1, col: 0}) self.i = 0 } func (self *StringReader) getpos() *pos { p := self.pos[self.i] p.i = self.i - return p + return &p } type Compiler struct { From 71f910dca40b31f2936257a1026d920837fe8210 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Wed, 14 Sep 2016 23:36:23 +0900 Subject: [PATCH 7/8] use range {string} instead of viml_split({string}, "\\zs") benchmark old ns/op new ns/op delta BenchmarkVimLParser_VimLParser-4 248887206 235228838 -5.49% --- go/type.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/go/type.go b/go/type.go index 742d1bc..50a1fcc 100644 --- a/go/type.go +++ b/go/type.go @@ -187,7 +187,8 @@ func (self *StringReader) __init__(lines []string) { var lnum = 0 for lnum < len(lines) { var col = 0 - for _, c := range viml_split(lines[lnum], "\\zs") { + for _, r := range lines[lnum] { + c := string(r) self.buf = append(self.buf, c) self.pos = append(self.pos, pos{lnum: lnum + 1, col: col + 1}) col += len(c) @@ -195,7 +196,8 @@ func (self *StringReader) __init__(lines []string) { for lnum+1 < len(lines) && viml_eqregh(lines[lnum+1], "^\\s*\\\\") { var skip = true col = 0 - for _, c := range viml_split(lines[lnum+1], "\\zs") { + for _, r := range lines[lnum+1] { + c := string(r) if skip { if c == "\\" { skip = false From 1dc4167c84a62de65868b60175a147dc35724937 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Wed, 14 Sep 2016 23:57:40 +0900 Subject: [PATCH 8/8] fix StringReader.__init__ initialization of buf and pos --- go/type.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/type.go b/go/type.go index 50a1fcc..8971f41 100644 --- a/go/type.go +++ b/go/type.go @@ -180,10 +180,10 @@ func NewStringReader(lines []string) *StringReader { func (self *StringReader) __init__(lines []string) { size := 0 for _, l := range lines { - size += len(l) + size += len(l) + 1 // +1 for EOL } self.buf = make([]string, 0, size) - self.pos = make([]pos, 0, size) + self.pos = make([]pos, 0, size+1) // +1 for EOF var lnum = 0 for lnum < len(lines) { var col = 0