Skip to content

Instantly share code, notes, and snippets.

@honmaple
Created September 5, 2021 14:54
Show Gist options
  • Save honmaple/b6bd0a32dca04ca6616e6944656e3616 to your computer and use it in GitHub Desktop.
Save honmaple/b6bd0a32dca04ca6616e6944656e3616 to your computer and use it in GitHub Desktop.
golang多行匹配与逐行匹配性能
package main
import (
"fmt"
"regexp"
"strings"
"testing"
)
var template = `
%s
#+begin_src bash
cccc
bvv
%s
#+end_src
%s
`
var text = fmt.Sprintf(template,
strings.Repeat("vvvvvvvvvvvvasdasdasdads\n", 100),
strings.Repeat("vvvvvvvvvvvvasdasdasdads\n", 10),
strings.Repeat("vvvvvvvvvvvvasdasdasdads\n", 100),
)
var (
beginBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+BEGIN_(\w+)(.*)`)
endBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+END_(\w+)`)
)
var (
blockRegexp = regexp.MustCompile(`(?ism:^(\s*)#\+BEGIN_(\w+)(.+?)\n(.+?)^(\s*)#\+END_(\w+))`)
)
type Block struct {
Type string
Parameters []string
}
func parseSplit(lines []string) (*Block, int) {
match := beginBlockRegexp.FindStringSubmatch(lines[0])
if match == nil {
return nil, 0
}
blockType := strings.ToUpper(match[2])
end := len(lines)
num := 1
for num < end {
if m := endBlockRegexp.FindStringSubmatch(lines[num]); m != nil && strings.ToUpper(m[2]) == blockType {
return &Block{
Type: blockType,
Parameters: strings.Split(strings.TrimSpace(match[3]), " "),
}, num + 1
}
num++
}
return nil, 0
}
func parseRegex(lines string) (*Block, int) {
match := blockRegexp.FindStringSubmatch(lines)
if match == nil {
return nil, 0
}
blockType := strings.ToUpper(match[2])
b := &Block{
Type: blockType,
Parameters: strings.Split(strings.TrimSpace(match[3]), " "),
}
return b, 0
}
func BenchmarkSplit(b *testing.B) {
count := 0
lines := strings.Split(text, "\n")
for i := 0; i < b.N; i++ {
index := 0
end := len(lines)
for index < end {
if m, n := parseSplit(lines[index:]); m != nil {
index = index + n
if count == 0 {
b.Log(m)
}
count++
continue
}
index++
}
}
b.Log(count)
}
func BenchmarkRegex(b *testing.B) {
count := 0
for i := 0; i < b.N; i++ {
if m, _ := parseRegex(text); m != nil {
if count == 0 {
b.Log(m)
}
count++
}
}
b.Log(count)
}
@honmaple
Copy link
Author

honmaple commented Sep 5, 2021

goos: darwin
goarch: amd64
pkg: org
cpu: Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz
BenchmarkSplit
    main_test.go:84: &{SRC [bash]}
    main_test.go:92: 1
    main_test.go:84: &{SRC [bash]}
    main_test.go:92: 100
    main_test.go:84: &{SRC [bash]}
    main_test.go:92: 10000
    main_test.go:84: &{SRC [bash]}
    main_test.go:92: 47133
BenchmarkSplit-8   	   47133	     24606 ns/op	     313 B/op	       8 allocs/op
BenchmarkRegex
    main_test.go:100: &{SRC [bash]}
    main_test.go:105: 1
    main_test.go:100: &{SRC [bash]}
    main_test.go:105: 100
    main_test.go:100: &{SRC [bash]}
    main_test.go:105: 10000
    main_test.go:100: &{SRC [bash]}
    main_test.go:105: 21664
BenchmarkRegex-8   	   21664	     56515 ns/op	     293 B/op	       5 allocs/op
PASS
ok  	org	3.768s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment