remove acquire

This commit is contained in:
gobwas 2016-02-05 16:57:42 +03:00
parent ed108ad05a
commit f843e79707
19 changed files with 58 additions and 126 deletions

View File

@ -25,29 +25,28 @@ func (self AnyOf) Match(s string) bool {
func (self AnyOf) Index(s string, segments []int) (int, []int) { func (self AnyOf) Index(s string, segments []int) (int, []int) {
index := -1 index := -1
// create reusable segments
in := make([]int, 0, len(s))
for _, m := range self.Matchers { for _, m := range self.Matchers {
in := acquireSegments(len(s)) idx, seg := m.Index(s, in[:0])
idx, seg := m.Index(s, in)
if idx == -1 { if idx == -1 {
releaseSegments(in)
continue continue
} }
if index == -1 || idx < index { if index == -1 || idx < index {
index = idx index = idx
segments = append(segments[:0], seg...) segments = append(segments[:0], seg...)
releaseSegments(in)
continue continue
} }
if idx > index { if idx > index {
releaseSegments(in)
continue continue
} }
// here idx == index // here idx == index
segments = appendMerge(segments, seg) segments = appendMerge(segments, seg)
releaseSegments(in)
} }
if index == -1 { if index == -1 {

View File

@ -33,15 +33,13 @@ func TestAnyIndex(t *testing.T) {
if !reflect.DeepEqual(segments, test.segments) { if !reflect.DeepEqual(segments, test.segments) {
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments) t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
} }
releaseSegments(segments)
} }
} }
func BenchmarkIndexAny(b *testing.B) { func BenchmarkIndexAny(b *testing.B) {
m := Any{bench_separators} m := Any{bench_separators}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
} }
@ -49,7 +47,7 @@ func BenchmarkIndexAny(b *testing.B) {
func BenchmarkIndexAnyParallel(b *testing.B) { func BenchmarkIndexAnyParallel(b *testing.B) {
m := Any{bench_separators} m := Any{bench_separators}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -77,13 +77,14 @@ func (self BTree) Match(s string) bool {
limit = inputLen limit = inputLen
} }
in := acquireSegments(inputLen) // reusable segments list
// inputLen is the maximum size of output segments values
in := make([]int, 0, inputLen)
for offset < limit { for offset < limit {
// search for matching part in substring // search for matching part in substring
index, segments := self.Value.Index(s[offset:limit], in[:0]) index, segments := self.Value.Index(s[offset:limit], in[:0])
if index == -1 { if index == -1 {
releaseSegments(in)
return false return false
} }
@ -115,7 +116,6 @@ func (self BTree) Match(s string) bool {
} }
if right { if right {
releaseSegments(in)
return true return true
} }
} }
@ -125,8 +125,6 @@ func (self BTree) Match(s string) bool {
offset += index + step offset += index + step
} }
releaseSegments(in)
return false return false
} }

View File

@ -56,7 +56,7 @@ func TestContainsIndex(t *testing.T) {
func BenchmarkIndexContains(b *testing.B) { func BenchmarkIndexContains(b *testing.B) {
m := Contains{string(bench_separators), true} m := Contains{string(bench_separators), true}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
} }
@ -64,7 +64,7 @@ func BenchmarkIndexContains(b *testing.B) {
func BenchmarkIndexContainsParallel(b *testing.B) { func BenchmarkIndexContainsParallel(b *testing.B) {
m := Contains{string(bench_separators), true} m := Contains{string(bench_separators), true}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -25,35 +25,32 @@ func (self EveryOf) Len() (l int) {
return return
} }
func max(a, b int) int {
if a >= b {
return a
}
return b
}
func (self EveryOf) Index(s string, out []int) (int, []int) { func (self EveryOf) Index(s string, out []int) (int, []int) {
var index int var index int
var offset int var offset int
var current []int
// make `in` with cap as len(s),
// cause it is the maximum size of output segments values
in := make([]int, 0, len(s))
next := make([]int, 0, len(s))
current := make([]int, 0, len(s))
sub := s sub := s
for i, m := range self.Matchers { for i, m := range self.Matchers {
in := acquireSegments(len(sub)) idx, seg := m.Index(sub, in[:0])
idx, seg := m.Index(sub, in)
if idx == -1 { if idx == -1 {
releaseSegments(in)
if cap(current) > 0 {
releaseSegments(current)
}
return -1, nil return -1, nil
} }
next := acquireSegments(max(len(seg), len(current)))
if i == 0 { if i == 0 {
next = append(next, seg...) // we use copy here instead of `current = seg`
// cause seg is a slice from reusable buffer `in`
// and it could be overwritten in next iteration
current = append(current, seg...)
} else { } else {
// clear the next
next = next[:0]
delta := index - (idx + offset) delta := index - (idx + offset)
for _, ex := range current { for _, ex := range current {
for _, n := range seg { for _, n := range seg {
@ -62,27 +59,22 @@ func (self EveryOf) Index(s string, out []int) (int, []int) {
} }
} }
} }
}
if cap(current) > 0 { if len(next) == 0 {
releaseSegments(current) return -1, nil
} }
releaseSegments(in)
if len(next) == 0 { current = append(current[:0], next...)
releaseSegments(next)
return -1, nil
} }
current = next
index = idx + offset index = idx + offset
sub = s[index:] sub = s[index:]
offset += idx offset += idx
} }
// copy result in `out` to prevent
// allocation `current` on heap
out = append(out, current...) out = append(out, current...)
releaseSegments(current)
return index, out return index, out
} }

View File

@ -18,7 +18,7 @@ func TestEveryOfIndex(t *testing.T) {
NewText("b"), NewText("b"),
NewText("c"), NewText("c"),
}, },
"abc", "dbc",
-1, -1,
nil, nil,
}, },

View File

@ -41,7 +41,7 @@ func TestListIndex(t *testing.T) {
func BenchmarkIndexList(b *testing.B) { func BenchmarkIndexList(b *testing.B) {
m := List{[]rune("def"), false} m := List{[]rune("def"), false}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -50,7 +50,7 @@ func BenchmarkIndexList(b *testing.B) {
func BenchmarkIndexListParallel(b *testing.B) { func BenchmarkIndexListParallel(b *testing.B) {
m := List{[]rune("def"), false} m := List{[]rune("def"), false}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -3,7 +3,6 @@ package match
import ( import (
"fmt" "fmt"
"strings" "strings"
"sync"
) )
const lenOne = 1 const lenOne = 1
@ -28,63 +27,10 @@ func (m Matchers) String() string {
return fmt.Sprintf("%s", strings.Join(s, ",")) 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{} {
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 {
return segmentsPools[getIdx(c)].Get().([]int)[:0]
}
func releaseSegments(s []int) {
segmentsPools[getIdx(cap(s))].Put(s)
}
// appendMerge merges and sorts given already SORTED and UNIQUE segments. // appendMerge merges and sorts given already SORTED and UNIQUE segments.
func appendMerge(target, sub []int) []int { func appendMerge(target, sub []int) []int {
lt, ls := len(target), len(sub) lt, ls := len(target), len(sub)
out := acquireSegments(lt + ls) out := make([]int, 0, lt+ls)
for x, y := 0, 0; x < lt || y < ls; { for x, y := 0, 0; x < lt || y < ls; {
if x >= lt { if x >= lt {
@ -119,7 +65,6 @@ func appendMerge(target, sub []int) []int {
} }
target = append(target[:0], out...) target = append(target[:0], out...)
releaseSegments(out)
return target return target
} }

View File

@ -38,7 +38,7 @@ func TestMaxIndex(t *testing.T) {
func BenchmarkIndexMax(b *testing.B) { func BenchmarkIndexMax(b *testing.B) {
m := Max{10} m := Max{10}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -47,7 +47,7 @@ func BenchmarkIndexMax(b *testing.B) {
func BenchmarkIndexMaxParallel(b *testing.B) { func BenchmarkIndexMaxParallel(b *testing.B) {
m := Max{10} m := Max{10}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -38,7 +38,7 @@ func TestMinIndex(t *testing.T) {
func BenchmarkIndexMin(b *testing.B) { func BenchmarkIndexMin(b *testing.B) {
m := Min{10} m := Min{10}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -47,7 +47,7 @@ func BenchmarkIndexMin(b *testing.B) {
func BenchmarkIndexMinParallel(b *testing.B) { func BenchmarkIndexMinParallel(b *testing.B) {
m := Min{10} m := Min{10}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -35,7 +35,7 @@ func TestNothingIndex(t *testing.T) {
func BenchmarkIndexNothing(b *testing.B) { func BenchmarkIndexNothing(b *testing.B) {
m := Nothing{} m := Nothing{}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -44,7 +44,7 @@ func BenchmarkIndexNothing(b *testing.B) {
func BenchmarkIndexNothingParallel(b *testing.B) { func BenchmarkIndexNothingParallel(b *testing.B) {
m := Nothing{} m := Nothing{}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -48,7 +48,7 @@ func TestPrefixSuffixIndex(t *testing.T) {
func BenchmarkIndexPrefixSuffix(b *testing.B) { func BenchmarkIndexPrefixSuffix(b *testing.B) {
m := PrefixSuffix{"qew", "sqw"} m := PrefixSuffix{"qew", "sqw"}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -57,7 +57,7 @@ func BenchmarkIndexPrefixSuffix(b *testing.B) {
func BenchmarkIndexPrefixSuffixParallel(b *testing.B) { func BenchmarkIndexPrefixSuffixParallel(b *testing.B) {
m := PrefixSuffix{"qew", "sqw"} m := PrefixSuffix{"qew", "sqw"}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -38,7 +38,7 @@ func TestPrefixIndex(t *testing.T) {
func BenchmarkIndexPrefix(b *testing.B) { func BenchmarkIndexPrefix(b *testing.B) {
m := Prefix{"qew"} m := Prefix{"qew"}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -47,7 +47,7 @@ func BenchmarkIndexPrefix(b *testing.B) {
func BenchmarkIndexPrefixParallel(b *testing.B) { func BenchmarkIndexPrefixParallel(b *testing.B) {
m := Prefix{"qew"} m := Prefix{"qew"}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -48,7 +48,7 @@ func TestRangeIndex(t *testing.T) {
func BenchmarkIndexRange(b *testing.B) { func BenchmarkIndexRange(b *testing.B) {
m := Range{'0', '9', false} m := Range{'0', '9', false}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -57,7 +57,7 @@ func BenchmarkIndexRange(b *testing.B) {
func BenchmarkIndexRangeParallel(b *testing.B) { func BenchmarkIndexRangeParallel(b *testing.B) {
m := Range{'0', '9', false} m := Range{'0', '9', false}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -59,7 +59,7 @@ func BenchmarkRowIndex(b *testing.B) {
}, },
RunesLength: 7, RunesLength: 7,
} }
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -75,7 +75,7 @@ func BenchmarkIndexRowParallel(b *testing.B) {
}, },
RunesLength: 7, RunesLength: 7,
} }
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -38,7 +38,7 @@ func TestSingleIndex(t *testing.T) {
func BenchmarkIndexSingle(b *testing.B) { func BenchmarkIndexSingle(b *testing.B) {
m := Single{bench_separators} m := Single{bench_separators}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -47,7 +47,7 @@ func BenchmarkIndexSingle(b *testing.B) {
func BenchmarkIndexSingleParallel(b *testing.B) { func BenchmarkIndexSingleParallel(b *testing.B) {
m := Single{bench_separators} m := Single{bench_separators}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -38,7 +38,7 @@ func TestSuffixIndex(t *testing.T) {
func BenchmarkIndexSuffix(b *testing.B) { func BenchmarkIndexSuffix(b *testing.B) {
m := Suffix{"qwe"} m := Suffix{"qwe"}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -47,7 +47,7 @@ func BenchmarkIndexSuffix(b *testing.B) {
func BenchmarkIndexSuffixParallel(b *testing.B) { func BenchmarkIndexSuffixParallel(b *testing.B) {
m := Suffix{"qwe"} m := Suffix{"qwe"}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -35,7 +35,7 @@ func TestSuperIndex(t *testing.T) {
func BenchmarkIndexSuper(b *testing.B) { func BenchmarkIndexSuper(b *testing.B) {
m := Super{} m := Super{}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -44,7 +44,7 @@ func BenchmarkIndexSuper(b *testing.B) {
func BenchmarkIndexSuperParallel(b *testing.B) { func BenchmarkIndexSuperParallel(b *testing.B) {
m := Super{} m := Super{}
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {

View File

@ -38,7 +38,7 @@ func TestTextIndex(t *testing.T) {
func BenchmarkIndexText(b *testing.B) { func BenchmarkIndexText(b *testing.B) {
m := NewText("foo") m := NewText("foo")
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m.Index(bench_pattern, in[:0]) m.Index(bench_pattern, in[:0])
@ -47,7 +47,7 @@ func BenchmarkIndexText(b *testing.B) {
func BenchmarkIndexTextParallel(b *testing.B) { func BenchmarkIndexTextParallel(b *testing.B) {
m := NewText("foo") m := NewText("foo")
in := acquireSegments(len(bench_pattern)) in := make([]int, 0, len(bench_pattern))
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {