forked from mirror/glob
reuse
This commit is contained in:
parent
0c30789d3a
commit
9c0c7cba85
|
@ -27,7 +27,7 @@ func (self AnyOf) Index(s string, segments []int) (int, []int) {
|
|||
index := -1
|
||||
|
||||
// create reusable segments
|
||||
seg := make([]int, 0, len(s))
|
||||
seg := acquireSegments(len(s))
|
||||
|
||||
for _, m := range self.Matchers {
|
||||
idx, seg := m.Index(s, seg[:0])
|
||||
|
@ -49,6 +49,8 @@ func (self AnyOf) Index(s string, segments []int) (int, []int) {
|
|||
segments = appendMerge(segments, seg)
|
||||
}
|
||||
|
||||
releaseSegments(seg)
|
||||
|
||||
if index == -1 {
|
||||
return -1, nil
|
||||
}
|
||||
|
|
|
@ -38,10 +38,10 @@ func TestAnyIndex(t *testing.T) {
|
|||
|
||||
func BenchmarkIndexAny(b *testing.B) {
|
||||
m := Any{bench_separators}
|
||||
|
||||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func BenchmarkIndexAnyParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -77,9 +77,16 @@ func (self BTree) Match(s string) bool {
|
|||
limit = inputLen
|
||||
}
|
||||
|
||||
if offset >= limit {
|
||||
return false
|
||||
}
|
||||
|
||||
// reusable segments list
|
||||
// inputLen is the maximum size of output segments values
|
||||
segments := make([]int, 0, inputLen)
|
||||
segments := acquireSegments(inputLen)
|
||||
defer func() {
|
||||
releaseSegments(segments)
|
||||
}()
|
||||
|
||||
for offset < limit {
|
||||
// search for matching part in substring
|
||||
|
|
|
@ -46,3 +46,44 @@ func TestBTree(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//type Matcher interface {
|
||||
// Match(string) bool
|
||||
// Index(string, []int) (int, []int)
|
||||
// Len() int
|
||||
// String() string
|
||||
//}
|
||||
|
||||
type fakeMatcher struct {
|
||||
len int
|
||||
name string
|
||||
}
|
||||
|
||||
func (f *fakeMatcher) Match(string) bool {
|
||||
return true
|
||||
}
|
||||
func (f *fakeMatcher) Index(s string, seg []int) (int, []int) {
|
||||
return 0, seg
|
||||
}
|
||||
func (f *fakeMatcher) Len() int {
|
||||
return f.len
|
||||
}
|
||||
func (f *fakeMatcher) String() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func BenchmarkMatchBTree(b *testing.B) {
|
||||
l := &fakeMatcher{4, "left_fake"}
|
||||
r := &fakeMatcher{4, "right_fake"}
|
||||
v := &fakeMatcher{2, "value_fake"}
|
||||
|
||||
// must be <= len(l + r + v)
|
||||
fixture := "abcdefghij"
|
||||
|
||||
bt := NewBTree(v, l, r)
|
||||
|
||||
b.SetParallelism(1)
|
||||
for i := 0; i < b.N; i++ {
|
||||
bt.Match(fixture)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ func BenchmarkIndexContains(b *testing.B) {
|
|||
|
||||
in := make([]int, 0, len(bench_pattern))
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ func BenchmarkIndexContainsParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -31,9 +31,15 @@ func (self EveryOf) Index(s string, out []int) (int, []int) {
|
|||
|
||||
// make `in` with cap as len(s),
|
||||
// cause it is the maximum size of output segments values
|
||||
seg := make([]int, 0, len(s))
|
||||
next := make([]int, 0, len(s))
|
||||
current := make([]int, 0, len(s))
|
||||
seg := acquireSegments(len(s))
|
||||
next := acquireSegments(len(s))
|
||||
current := acquireSegments(len(s))
|
||||
|
||||
defer func() {
|
||||
releaseSegments(seg)
|
||||
releaseSegments(next)
|
||||
releaseSegments(current)
|
||||
}()
|
||||
|
||||
sub := s
|
||||
for i, m := range self.Matchers {
|
||||
|
|
|
@ -44,7 +44,7 @@ func BenchmarkIndexList(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ func BenchmarkIndexListParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package match
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const lenOne = 1
|
||||
|
@ -27,6 +28,62 @@ func (m Matchers) String() string {
|
|||
return fmt.Sprintf("%s", strings.Join(s, ","))
|
||||
}
|
||||
|
||||
var segmentsPools [1024]sync.Pool
|
||||
|
||||
func toPowerOfTwo(v int) int {
|
||||
v--
|
||||
v |= v >> 1
|
||||
v |= v >> 2
|
||||
v |= v >> 4
|
||||
v |= v >> 8
|
||||
v |= v >> 16
|
||||
v++
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
const (
|
||||
minSegment = 32
|
||||
minSegmentMinusOne = 31
|
||||
maxSegment = 1024
|
||||
maxSegmentMinusOne = 1023
|
||||
)
|
||||
|
||||
func init() {
|
||||
for i := maxSegment; i >= minSegment; i >>= 1 {
|
||||
func(i int) {
|
||||
segmentsPools[i-1] = sync.Pool{
|
||||
New: func() interface{} {
|
||||
fmt.Println("new", i)
|
||||
return make([]int, 0, i)
|
||||
},
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
}
|
||||
|
||||
func getIdx(c int) int {
|
||||
p := toPowerOfTwo(c)
|
||||
switch {
|
||||
case p >= maxSegment:
|
||||
return maxSegmentMinusOne
|
||||
case p <= minSegment:
|
||||
return minSegmentMinusOne
|
||||
default:
|
||||
return p - 1
|
||||
}
|
||||
}
|
||||
|
||||
func acquireSegments(c int) []int {
|
||||
// fmt.Println("acquire", c)
|
||||
return segmentsPools[getIdx(c)].Get().([]int)[:0]
|
||||
}
|
||||
|
||||
func releaseSegments(s []int) {
|
||||
// fmt.Println("release", len(s))
|
||||
segmentsPools[getIdx(cap(s))].Put(s)
|
||||
}
|
||||
|
||||
// appendMerge merges and sorts given already SORTED and UNIQUE segments.
|
||||
func appendMerge(target, sub []int) []int {
|
||||
lt, ls := len(target), len(sub)
|
||||
|
|
|
@ -41,7 +41,7 @@ func BenchmarkIndexMax(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func BenchmarkIndexMaxParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func BenchmarkIndexMin(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func BenchmarkIndexMinParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func BenchmarkIndexNothing(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ func BenchmarkIndexNothingParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ func BenchmarkIndexPrefixSuffix(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ func BenchmarkIndexPrefixSuffixParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func BenchmarkIndexPrefix(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func BenchmarkIndexPrefixParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ func BenchmarkIndexRange(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ func BenchmarkIndexRangeParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ func BenchmarkRowIndex(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ func BenchmarkIndexRowParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func BenchmarkIndexSingle(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func BenchmarkIndexSingleParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func BenchmarkIndexSuffix(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func BenchmarkIndexSuffixParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func BenchmarkIndexSuper(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ func BenchmarkIndexSuperParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func BenchmarkIndexText(b *testing.B) {
|
|||
in := make([]int, 0, len(bench_pattern))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func BenchmarkIndexTextParallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern, in[:0])
|
||||
_, in = m.Index(bench_pattern, in[:0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue