From 67120158c024886ed31a46bc4238c71d33480bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Mon, 11 Mar 2019 17:21:14 +0000 Subject: [PATCH] syntax: use fewer tabwriter escape characters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta Print-8 11.5µs ± 0% 11.4µs ± 1% -1.03% (p=0.002 n=6+6) name old alloc/op new alloc/op delta Print-8 344B ± 0% 312B ± 0% -9.30% (p=0.002 n=6+6) name old allocs/op new allocs/op delta Print-8 10.0 ± 0% 9.0 ± 0% -10.00% (p=0.002 n=6+6) We'll leave the tabwriter optimizations here for now. I've sent https://go-review.googlesource.com/c/go/+/166797 to upstream, which shaves off 27% from our benchmark. In total, the overhead of tabwriter goes down from the initial ~135% to ~55%, which is much more acceptable. We even allocate less garbage, too. name old time/op new time/op delta Print-8 5.29µs ± 0% 8.21µs ± 1% +55.19% (p=0.002 n=6+6) name old alloc/op new alloc/op delta Print-8 344B ± 0% 312B ± 0% -9.30% (p=0.002 n=6+6) name old allocs/op new allocs/op delta Print-8 13.0 ± 0% 9.0 ± 0% -30.77% (p=0.002 n=6+6) --- syntax/printer.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/syntax/printer.go b/syntax/printer.go index 3628eb0f0..13303429d 100644 --- a/syntax/printer.go +++ b/syntax/printer.go @@ -167,7 +167,7 @@ func (c *colCounter) Reset(w io.Writer) { type Printer struct { bufWriter tabWriter *tabwriter.Writer - cols colCounter + cols colCounter indentSpaces uint binNextLine bool @@ -297,16 +297,16 @@ func (p *Printer) writeLit(s string) { p.WriteString(s) return } + p.WriteByte('\xff') for i := 0; i < len(s); i++ { b := s[i] if b != '\t' { p.WriteByte(b) continue } - p.WriteByte('\xff') p.WriteByte(b) - p.WriteByte('\xff') } + p.WriteByte('\xff') } func (p *Printer) incLevel() { @@ -1188,9 +1188,13 @@ func (e *extraIndenter) WriteByte(b byte) error { if b != '\n' { return nil } - trimmed := bytes.TrimLeft(e.curLine, "\xff\t") - // divided by 3, as each tab is escaped via "\xff\t\xff" - lineIndent := (len(e.curLine) - len(trimmed)) / 3 + line := e.curLine + if bytes.HasPrefix(e.curLine, []byte("\xff")) { + // beginning a multiline sequence, with the leading escape + line = line[1:] + } + trimmed := bytes.TrimLeft(line, "\t") + lineIndent := len(line) - len(trimmed) if e.firstIndent < 0 { e.firstIndent = lineIndent e.firstChange = e.baseIndent - lineIndent