From eced0cdb72fad71d8e2c4578eaba0271d30c4c97 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Tue, 17 Nov 2020 09:12:41 +0530 Subject: [PATCH] MM-29981 - optimize markdown.Inspect (#16188) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * MM-29981 - optimize markdown.Inspect - Cache regexp.MustCompile - Reuse slice in MergeInlineText - Remove pointer to slice in closeBlocks - Pre-allocate slice in ParseLines - Some more small cleanups ``` name old time/op new time/op delta Inspect-8 10.5µs ± 3% 6.6µs ± 1% -37.59% (p=0.000 n=10+7) name old alloc/op new alloc/op delta Inspect-8 6.66kB ± 0% 3.22kB ± 0% -51.62% (p=0.000 n=10+9) name old allocs/op new allocs/op delta Inspect-8 117 ± 0% 76 ± 0% -35.04% (p=0.000 n=10+10) ``` * fix lint * remove ignore Co-authored-by: Mattermod --- utils/markdown/autolink.go | 12 +++++------- utils/markdown/blocks.go | 13 +++++++------ utils/markdown/inlines.go | 2 +- utils/markdown/inspect_test.go | 21 +++++++++++++++++++++ utils/markdown/lines.go | 7 +++++-- utils/markdown/markdown.go | 3 +-- 6 files changed, 40 insertions(+), 18 deletions(-) diff --git a/utils/markdown/autolink.go b/utils/markdown/autolink.go index 1418083688..d06ada667e 100644 --- a/utils/markdown/autolink.go +++ b/utils/markdown/autolink.go @@ -14,6 +14,7 @@ import ( var ( DefaultUrlSchemes = []string{"http", "https", "ftp", "mailto", "tel"} + wwwAutoLinkRegex = regexp.MustCompile(`^www\d{0,3}\.`) ) // Given a string with a w at the given position, tries to parse and return a range containing a www link. @@ -30,7 +31,7 @@ func parseWWWAutolink(data string, position int) (Range, bool) { } // Check that this starts with www - if len(data)-position < 4 || !regexp.MustCompile(`^www\d{0,3}\.`).MatchString(data[position:]) { + if len(data)-position < 4 || !wwwAutoLinkRegex.MatchString(data[position:]) { return Range{}, false } @@ -59,9 +60,8 @@ func isAllowedBeforeWWWLink(c byte) bool { switch c { case '*', '_', '~', ')': return true - default: - return false } + return false } // Given a string with a : at the given position, tried to parse and return a range containing a URL scheme @@ -153,9 +153,8 @@ func checkDomain(data string, allowShort bool) int { // this is called from parseWWWAutolink if foundPeriod { return i - } else { - return 0 } + return 0 } // Returns true if the provided link starts with a valid character for a domain name. Equivalent to @@ -251,7 +250,6 @@ func canEndAutolink(c rune) bool { switch c { case '?', '!', '.', ',', ':', '*', '_', '~', '\'', '"': return false - default: - return true } + return true } diff --git a/utils/markdown/blocks.go b/utils/markdown/blocks.go index 44ee178d1b..607356e097 100644 --- a/utils/markdown/blocks.go +++ b/utils/markdown/blocks.go @@ -37,13 +37,14 @@ type Range struct { End int } -func closeBlocks(blocks []Block, referenceDefinitions *[]*ReferenceDefinition) { +func closeBlocks(blocks []Block, referenceDefinitions []*ReferenceDefinition) []*ReferenceDefinition { for _, block := range blocks { block.Close() if p, ok := block.(*Paragraph); ok && len(p.ReferenceDefinitions) > 0 { - *referenceDefinitions = append(*referenceDefinitions, p.ReferenceDefinitions...) + referenceDefinitions = append(referenceDefinitions, p.ReferenceDefinitions...) } } + return referenceDefinitions } func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefinition) { @@ -78,7 +79,7 @@ func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefiniti for i := lastMatchIndex; i >= 0; i-- { if container, ok := openBlocks[i].(ContainerBlock); ok { if addedBlocks := container.AddChild(newBlocks); addedBlocks != nil { - closeBlocks(openBlocks[i+1:], &referenceDefinitions) + referenceDefinitions = closeBlocks(openBlocks[i+1:], referenceDefinitions) openBlocks = openBlocks[:i+1] openBlocks = append(openBlocks, addedBlocks...) didAdd = true @@ -98,7 +99,7 @@ func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefiniti continue } - closeBlocks(openBlocks[lastMatchIndex+1:], &referenceDefinitions) + referenceDefinitions = closeBlocks(openBlocks[lastMatchIndex+1:], referenceDefinitions) openBlocks = openBlocks[:lastMatchIndex+1] if openBlocks[lastMatchIndex].AddLine(indentation, r) { @@ -109,7 +110,7 @@ func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefiniti for i := lastMatchIndex; i >= 0; i-- { if container, ok := openBlocks[i].(ContainerBlock); ok { if newBlocks := container.AddChild([]Block{paragraph}); newBlocks != nil { - closeBlocks(openBlocks[i+1:], &referenceDefinitions) + referenceDefinitions = closeBlocks(openBlocks[i+1:], referenceDefinitions) openBlocks = openBlocks[:i+1] openBlocks = append(openBlocks, newBlocks...) break @@ -119,7 +120,7 @@ func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefiniti } } - closeBlocks(openBlocks, &referenceDefinitions) + referenceDefinitions = closeBlocks(openBlocks, referenceDefinitions) return document, referenceDefinitions } diff --git a/utils/markdown/inlines.go b/utils/markdown/inlines.go index 4303607fdd..a67f2f04f1 100644 --- a/utils/markdown/inlines.go +++ b/utils/markdown/inlines.go @@ -595,7 +595,7 @@ func ParseInlines(markdown string, ranges []Range, referenceDefinitions []*Refer } func MergeInlineText(inlines []Inline) []Inline { - var ret []Inline + ret := inlines[:0] for i, v := range inlines { // always add first node if i == 0 { diff --git a/utils/markdown/inspect_test.go b/utils/markdown/inspect_test.go index 41ec683dce..56899381e7 100644 --- a/utils/markdown/inspect_test.go +++ b/utils/markdown/inspect_test.go @@ -52,3 +52,24 @@ func TestInspect(t *testing.T) { " Text", }, visited) } + +var counterSink int + +func BenchmarkInspect(b *testing.B) { + text := `Some standard piece of text. + +Has a link [post](https://github.com) and also has a blockquote. + +> This is a famous quote. + +Some bold text **Text for markdown?** to go with it. + +At the end, some more lines` + + for i := 0; i < b.N; i++ { + Inspect(text, func(_ interface{}) bool { + counterSink++ + return true + }) + } +} diff --git a/utils/markdown/lines.go b/utils/markdown/lines.go index a0a644916e..a67ec97658 100644 --- a/utils/markdown/lines.go +++ b/utils/markdown/lines.go @@ -3,13 +3,16 @@ package markdown +import "strings" + type Line struct { Range } -func ParseLines(markdown string) (lines []Line) { +func ParseLines(markdown string) []Line { lineStartPosition := 0 isAfterCarriageReturn := false + lines := make([]Line, 0, strings.Count(markdown, "\n")) for position, r := range markdown { if r == '\n' { lines = append(lines, Line{Range{lineStartPosition, position + 1}}) @@ -23,5 +26,5 @@ func ParseLines(markdown string) (lines []Line) { if lineStartPosition < len(markdown) { lines = append(lines, Line{Range{lineStartPosition, len(markdown)}}) } - return + return lines } diff --git a/utils/markdown/markdown.go b/utils/markdown/markdown.go index a9879ceedf..5ccdad8ced 100644 --- a/utils/markdown/markdown.go +++ b/utils/markdown/markdown.go @@ -23,9 +23,8 @@ func isWhitespace(c rune) bool { switch c { case ' ', '\t', '\n', '\u000b', '\u000c', '\r': return true - default: - return false } + return false } func isWhitespaceByte(c byte) bool {