MM-29981 - optimize markdown.Inspect (#16188)

* 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 <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Agniva De Sarker
2020-11-17 09:12:41 +05:30
коммит произвёл GitHub
родитель 95221d9ace
Коммит eced0cdb72
6 изменённых файлов: 40 добавлений и 18 удалений

Просмотреть файл

@@ -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
}

Просмотреть файл

@@ -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
}

Просмотреть файл

@@ -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 {

Просмотреть файл

@@ -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
})
}
}

Просмотреть файл

@@ -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
}

Просмотреть файл

@@ -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 {