From e42b4fd9a6cfb691c73d5d3b225e81aa4dafd694 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 20 Mar 2023 21:00:04 +0530 Subject: [PATCH] Decrease allocs when wrapping --- tools/utils/style/indent-and-wrap.go | 48 ++++++++++++---------------- tools/wcswidth/wcswidth.go | 4 +++ 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/tools/utils/style/indent-and-wrap.go b/tools/utils/style/indent-and-wrap.go index b7b5eb723..d748af970 100644 --- a/tools/utils/style/indent-and-wrap.go +++ b/tools/utils/style/indent-and-wrap.go @@ -248,12 +248,12 @@ func (self hyperlink_state) as_escape_codes(for_close bool) string { } type line_builder struct { - buf strings.Builder + buf []byte last_text_pos, cursor_pos int } func (self *line_builder) reset() string { - ans := self.buf.String() + ans := string(self.buf) if len(ans) > self.last_text_pos { prefix := ans[:self.last_text_pos] suffix := ans[self.last_text_pos:] @@ -264,15 +264,9 @@ func (self *line_builder) reset() string { } else { ans = strings.TrimRightFunc(ans, unicode.IsSpace) } - sz := self.buf.Len() - self.buf.Reset() + self.buf = self.buf[:0] self.last_text_pos = 0 self.cursor_pos = 0 - if sz > 1024 { - self.buf.Grow(sz) - } else { - self.buf.Grow(1024) - } return ans } @@ -281,25 +275,25 @@ func (self *line_builder) has_space_for_width(w, max_width int) bool { } func (self *line_builder) add_char(ch rune) { - self.buf.WriteRune(ch) - self.last_text_pos = self.buf.Len() + self.buf = utf8.AppendRune(self.buf, ch) + self.last_text_pos = len(self.buf) self.cursor_pos += wcswidth.Runewidth(ch) } -func (self *line_builder) add_word(word string, width int) { - self.buf.WriteString(word) - self.last_text_pos = self.buf.Len() +func (self *line_builder) add_word(word []byte, width int) { + self.buf = append(self.buf, word...) + self.last_text_pos = len(self.buf) self.cursor_pos += width } func (self *line_builder) add_escape_code(code string) { - self.buf.WriteString(code) + self.buf = append(self.buf, code...) } func (self *line_builder) add_escape_code2(prefix string, body []byte, suffix string) { - self.buf.WriteString(prefix) - self.buf.Write(body) - self.buf.WriteString(suffix) + self.buf = append(self.buf, prefix...) + self.buf = append(self.buf, body...) + self.buf = append(self.buf, suffix...) } type escape_code_ struct { @@ -313,14 +307,12 @@ type word_builder struct { wcswidth *wcswidth.WCWidthIterator } -func (self *word_builder) reset() string { - ans := utils.UnsafeBytesToString(self.buf) - sz := utils.Min(utils.Max(64, len(ans)), 4096) - self.buf = make([]byte, 0, sz) +func (self *word_builder) reset(copy_current_word func([]byte)) { + copy_current_word(self.buf) + self.buf = self.buf[:0] self.escape_codes = self.escape_codes[:0] self.text_start_position = 0 self.wcswidth.Reset() - return ans } func (self *word_builder) is_empty() bool { @@ -401,7 +393,7 @@ type wrapper struct { func (self *wrapper) newline_prefix() { self.current_line.add_escape_code(self.sgr.as_escape_codes(true)) self.current_line.add_escape_code(self.hyperlink.as_escape_codes(true)) - self.current_line.add_word(self.indent, self.indent_width) + self.current_line.add_word(utils.UnsafeStringToBytes(self.indent), self.indent_width) self.current_line.add_escape_code(self.sgr.as_escape_codes(false)) self.current_line.add_escape_code(self.hyperlink.as_escape_codes(false)) } @@ -438,7 +430,9 @@ func (self *wrapper) print_word() { self.sgr.apply_csi(e.body) } } - self.current_line.add_word(self.current_word.reset(), w) + self.current_word.reset(func(word []byte) { + self.current_line.add_word(word, w) + }) } func (self *wrapper) handle_rune(ch rune) error { @@ -474,9 +468,9 @@ func (self *wrapper) wrap_text(text string) []string { return []string{""} } self.current_line.reset() - self.current_word.reset() + self.current_word.reset(func([]byte) {}) self.lines = self.lines[:0] - self.current_line.add_word(self.indent, self.indent_width) + self.current_line.add_word(utils.UnsafeStringToBytes(self.indent), self.indent_width) self.ep.ParseString(text) if !self.current_word.is_empty() { self.print_word() diff --git a/tools/wcswidth/wcswidth.go b/tools/wcswidth/wcswidth.go index 10d3a0610..d152d9c85 100644 --- a/tools/wcswidth/wcswidth.go +++ b/tools/wcswidth/wcswidth.go @@ -122,6 +122,10 @@ func (self *WCWidthIterator) Parse(b []byte) (ans int) { return self.current_width } +func (self *WCWidthIterator) CurrentWidth() int { + return self.current_width +} + func Stringwidth(text string) int { w := CreateWCWidthIterator() return w.Parse(utils.UnsafeStringToBytes(text))