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>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
95221d9ace
Коммит
eced0cdb72
@@ -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 {
|
||||
|
||||
Ссылка в новой задаче
Block a user