From f843e797074287596287f752b725a69de564359e Mon Sep 17 00:00:00 2001 From: gobwas Date: Fri, 5 Feb 2016 16:57:42 +0300 Subject: [PATCH] remove acquire --- match/any_of.go | 11 ++++--- match/any_test.go | 6 ++-- match/btree.go | 8 ++---- match/contains_test.go | 4 +-- match/every_of.go | 48 +++++++++++++------------------ match/every_of_test.go | 2 +- match/list_test.go | 4 +-- match/match.go | 57 +------------------------------------ match/max_test.go | 4 +-- match/min_test.go | 4 +-- match/nothing_test.go | 4 +-- match/prefix_suffix_test.go | 4 +-- match/prefix_test.go | 4 +-- match/range_test.go | 4 +-- match/row_test.go | 4 +-- match/single_test.go | 4 +-- match/suffix_test.go | 4 +-- match/super_test.go | 4 +-- match/text_test.go | 4 +-- 19 files changed, 58 insertions(+), 126 deletions(-) diff --git a/match/any_of.go b/match/any_of.go index 602cd28..1b60287 100644 --- a/match/any_of.go +++ b/match/any_of.go @@ -25,29 +25,28 @@ func (self AnyOf) Match(s string) bool { func (self AnyOf) Index(s string, segments []int) (int, []int) { index := -1 + + // create reusable segments + in := make([]int, 0, len(s)) + for _, m := range self.Matchers { - in := acquireSegments(len(s)) - idx, seg := m.Index(s, in) + idx, seg := m.Index(s, in[:0]) if idx == -1 { - releaseSegments(in) continue } if index == -1 || idx < index { index = idx segments = append(segments[:0], seg...) - releaseSegments(in) continue } if idx > index { - releaseSegments(in) continue } // here idx == index segments = appendMerge(segments, seg) - releaseSegments(in) } if index == -1 { diff --git a/match/any_test.go b/match/any_test.go index 9239ffa..2a5b07e 100644 --- a/match/any_test.go +++ b/match/any_test.go @@ -33,15 +33,13 @@ func TestAnyIndex(t *testing.T) { if !reflect.DeepEqual(segments, test.segments) { t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments) } - - releaseSegments(segments) } } func BenchmarkIndexAny(b *testing.B) { m := Any{bench_separators} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) } @@ -49,7 +47,7 @@ func BenchmarkIndexAny(b *testing.B) { func BenchmarkIndexAnyParallel(b *testing.B) { m := Any{bench_separators} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/btree.go b/match/btree.go index 2358eb3..cbd93ee 100644 --- a/match/btree.go +++ b/match/btree.go @@ -77,13 +77,14 @@ func (self BTree) Match(s string) bool { 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 { // search for matching part in substring index, segments := self.Value.Index(s[offset:limit], in[:0]) if index == -1 { - releaseSegments(in) return false } @@ -115,7 +116,6 @@ func (self BTree) Match(s string) bool { } if right { - releaseSegments(in) return true } } @@ -125,8 +125,6 @@ func (self BTree) Match(s string) bool { offset += index + step } - releaseSegments(in) - return false } diff --git a/match/contains_test.go b/match/contains_test.go index ba9577b..4789c89 100644 --- a/match/contains_test.go +++ b/match/contains_test.go @@ -56,7 +56,7 @@ func TestContainsIndex(t *testing.T) { func BenchmarkIndexContains(b *testing.B) { 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++ { m.Index(bench_pattern, in[:0]) } @@ -64,7 +64,7 @@ func BenchmarkIndexContains(b *testing.B) { func BenchmarkIndexContainsParallel(b *testing.B) { m := Contains{string(bench_separators), true} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/every_of.go b/match/every_of.go index dba0154..22ea8c8 100644 --- a/match/every_of.go +++ b/match/every_of.go @@ -25,35 +25,32 @@ func (self EveryOf) Len() (l int) { return } -func max(a, b int) int { - if a >= b { - return a - } - - return b -} - func (self EveryOf) Index(s string, out []int) (int, []int) { var index 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 for i, m := range self.Matchers { - in := acquireSegments(len(sub)) - idx, seg := m.Index(sub, in) + idx, seg := m.Index(sub, in[:0]) if idx == -1 { - releaseSegments(in) - if cap(current) > 0 { - releaseSegments(current) - } return -1, nil } - next := acquireSegments(max(len(seg), len(current))) 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 { + // clear the next + next = next[:0] + delta := index - (idx + offset) for _, ex := range current { for _, n := range seg { @@ -62,27 +59,22 @@ func (self EveryOf) Index(s string, out []int) (int, []int) { } } } - } - if cap(current) > 0 { - releaseSegments(current) - } - releaseSegments(in) + if len(next) == 0 { + return -1, nil + } - if len(next) == 0 { - releaseSegments(next) - return -1, nil + current = append(current[:0], next...) } - current = next - index = idx + offset sub = s[index:] offset += idx } + // copy result in `out` to prevent + // allocation `current` on heap out = append(out, current...) - releaseSegments(current) return index, out } diff --git a/match/every_of_test.go b/match/every_of_test.go index c97ea70..08a1cbe 100644 --- a/match/every_of_test.go +++ b/match/every_of_test.go @@ -18,7 +18,7 @@ func TestEveryOfIndex(t *testing.T) { NewText("b"), NewText("c"), }, - "abc", + "dbc", -1, nil, }, diff --git a/match/list_test.go b/match/list_test.go index 8fd13a2..de1ff0c 100644 --- a/match/list_test.go +++ b/match/list_test.go @@ -41,7 +41,7 @@ func TestListIndex(t *testing.T) { func BenchmarkIndexList(b *testing.B) { m := List{[]rune("def"), false} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -50,7 +50,7 @@ func BenchmarkIndexList(b *testing.B) { func BenchmarkIndexListParallel(b *testing.B) { m := List{[]rune("def"), false} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/match.go b/match/match.go index a8351eb..dadc5a1 100644 --- a/match/match.go +++ b/match/match.go @@ -3,7 +3,6 @@ package match import ( "fmt" "strings" - "sync" ) const lenOne = 1 @@ -28,63 +27,10 @@ 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{} { - 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. func appendMerge(target, sub []int) []int { 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; { if x >= lt { @@ -119,7 +65,6 @@ func appendMerge(target, sub []int) []int { } target = append(target[:0], out...) - releaseSegments(out) return target } diff --git a/match/max_test.go b/match/max_test.go index 2c5cba5..f00b061 100644 --- a/match/max_test.go +++ b/match/max_test.go @@ -38,7 +38,7 @@ func TestMaxIndex(t *testing.T) { func BenchmarkIndexMax(b *testing.B) { m := Max{10} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -47,7 +47,7 @@ func BenchmarkIndexMax(b *testing.B) { func BenchmarkIndexMaxParallel(b *testing.B) { m := Max{10} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/min_test.go b/match/min_test.go index 5f9f126..da86aee 100644 --- a/match/min_test.go +++ b/match/min_test.go @@ -38,7 +38,7 @@ func TestMinIndex(t *testing.T) { func BenchmarkIndexMin(b *testing.B) { m := Min{10} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -47,7 +47,7 @@ func BenchmarkIndexMin(b *testing.B) { func BenchmarkIndexMinParallel(b *testing.B) { m := Min{10} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/nothing_test.go b/match/nothing_test.go index 76cb678..6bfab94 100644 --- a/match/nothing_test.go +++ b/match/nothing_test.go @@ -35,7 +35,7 @@ func TestNothingIndex(t *testing.T) { func BenchmarkIndexNothing(b *testing.B) { m := Nothing{} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -44,7 +44,7 @@ func BenchmarkIndexNothing(b *testing.B) { func BenchmarkIndexNothingParallel(b *testing.B) { m := Nothing{} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/prefix_suffix_test.go b/match/prefix_suffix_test.go index 23271c0..57db175 100644 --- a/match/prefix_suffix_test.go +++ b/match/prefix_suffix_test.go @@ -48,7 +48,7 @@ func TestPrefixSuffixIndex(t *testing.T) { func BenchmarkIndexPrefixSuffix(b *testing.B) { m := PrefixSuffix{"qew", "sqw"} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -57,7 +57,7 @@ func BenchmarkIndexPrefixSuffix(b *testing.B) { func BenchmarkIndexPrefixSuffixParallel(b *testing.B) { m := PrefixSuffix{"qew", "sqw"} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/prefix_test.go b/match/prefix_test.go index 5b38bfd..dfa3c00 100644 --- a/match/prefix_test.go +++ b/match/prefix_test.go @@ -38,7 +38,7 @@ func TestPrefixIndex(t *testing.T) { func BenchmarkIndexPrefix(b *testing.B) { m := Prefix{"qew"} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -47,7 +47,7 @@ func BenchmarkIndexPrefix(b *testing.B) { func BenchmarkIndexPrefixParallel(b *testing.B) { m := Prefix{"qew"} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/range_test.go b/match/range_test.go index a7cdef8..1a83301 100644 --- a/match/range_test.go +++ b/match/range_test.go @@ -48,7 +48,7 @@ func TestRangeIndex(t *testing.T) { func BenchmarkIndexRange(b *testing.B) { m := Range{'0', '9', false} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -57,7 +57,7 @@ func BenchmarkIndexRange(b *testing.B) { func BenchmarkIndexRangeParallel(b *testing.B) { m := Range{'0', '9', false} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/row_test.go b/match/row_test.go index ff59cff..b380434 100644 --- a/match/row_test.go +++ b/match/row_test.go @@ -59,7 +59,7 @@ func BenchmarkRowIndex(b *testing.B) { }, RunesLength: 7, } - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -75,7 +75,7 @@ func BenchmarkIndexRowParallel(b *testing.B) { }, RunesLength: 7, } - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/single_test.go b/match/single_test.go index e1e99ac..095cddc 100644 --- a/match/single_test.go +++ b/match/single_test.go @@ -38,7 +38,7 @@ func TestSingleIndex(t *testing.T) { func BenchmarkIndexSingle(b *testing.B) { m := Single{bench_separators} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -47,7 +47,7 @@ func BenchmarkIndexSingle(b *testing.B) { func BenchmarkIndexSingleParallel(b *testing.B) { m := Single{bench_separators} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/suffix_test.go b/match/suffix_test.go index aeda714..27cb60f 100644 --- a/match/suffix_test.go +++ b/match/suffix_test.go @@ -38,7 +38,7 @@ func TestSuffixIndex(t *testing.T) { func BenchmarkIndexSuffix(b *testing.B) { m := Suffix{"qwe"} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -47,7 +47,7 @@ func BenchmarkIndexSuffix(b *testing.B) { func BenchmarkIndexSuffixParallel(b *testing.B) { m := Suffix{"qwe"} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/super_test.go b/match/super_test.go index aa68cfb..02b9a67 100644 --- a/match/super_test.go +++ b/match/super_test.go @@ -35,7 +35,7 @@ func TestSuperIndex(t *testing.T) { func BenchmarkIndexSuper(b *testing.B) { m := Super{} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -44,7 +44,7 @@ func BenchmarkIndexSuper(b *testing.B) { func BenchmarkIndexSuperParallel(b *testing.B) { m := Super{} - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() { diff --git a/match/text_test.go b/match/text_test.go index b5c6964..5aab330 100644 --- a/match/text_test.go +++ b/match/text_test.go @@ -38,7 +38,7 @@ func TestTextIndex(t *testing.T) { func BenchmarkIndexText(b *testing.B) { m := NewText("foo") - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) for i := 0; i < b.N; i++ { m.Index(bench_pattern, in[:0]) @@ -47,7 +47,7 @@ func BenchmarkIndexText(b *testing.B) { func BenchmarkIndexTextParallel(b *testing.B) { m := NewText("foo") - in := acquireSegments(len(bench_pattern)) + in := make([]int, 0, len(bench_pattern)) b.RunParallel(func(pb *testing.PB) { for pb.Next() {