use sequenced pool

This commit is contained in:
gobwas 2016-02-22 20:22:04 +03:00
parent 325689ef4a
commit 9b07f114a0
4 changed files with 204 additions and 74 deletions

View File

@ -47,13 +47,6 @@ 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

View File

@ -3,7 +3,6 @@ package match
import (
"fmt"
"strings"
"sync"
)
const lenOne = 1
@ -28,72 +27,6 @@ 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) {
pool := sync.Pool{
New: func() interface{} {
// fmt.Printf("N%d;", i)
return make([]int, 0, i)
},
}
// for n := 0; n < 4; n++ {
// pool.Put(make([]int, 0, i))
// }
segmentsPools[i-1] = pool
}(i)
}
}
func getIdx(c int) int {
p := toPowerOfTwo(c)
switch {
case p >= maxSegment:
return maxSegmentMinusOne
case p <= minSegment:
return minSegmentMinusOne
default:
return p - 1
}
}
//var p = make([]int, 0, 128)
func acquireSegments(c int) []int {
// return p
// fmt.Printf("a%d;", getIdx(c))
return segmentsPools[getIdx(c)].Get().([]int)[:0]
}
func releaseSegments(s []int) {
// p = s
// fmt.Printf("r%d;", getIdx(cap(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)

39
match/segements_test.go Normal file
View File

@ -0,0 +1,39 @@
package match
import (
"testing"
)
func BenchmarkPerfPoolSequenced(b *testing.B) {
pool := NewPoolSequenced(32, func() []int {
return make([]int, 0, 16)
})
for i := 0; i < b.N; i++ {
s := pool.Get()
pool.Put(s)
}
}
func BenchmarkPerfPoolSynced(b *testing.B) {
pool := NewPoolSynced(32)
for i := 0; i < b.N; i++ {
s := pool.Get()
pool.Put(s)
}
}
func BenchmarkPerfPoolPoolNative(b *testing.B) {
pool := NewPoolNative(32)
for i := 0; i < b.N; i++ {
s := pool.Get()
pool.Put(s)
}
}
func BenchmarkPerfMake(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = make([]int, 0, 32)
}
}

165
match/segments.go Normal file
View File

@ -0,0 +1,165 @@
package match
import "sync"
var segmentsPools [1024]*PoolSequenced
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) {
// pool := sync.Pool{
// New: func() interface{} {
// // fmt.Printf("N%d;", i)
// return make([]int, 0, i)
// },
// }
pool := NewPoolSequenced(64, func() []int {
return make([]int, 0, i)
})
segmentsPools[i-1] = pool
}(i)
}
}
func getIdx(c int) int {
p := toPowerOfTwo(c)
switch {
case p >= maxSegment:
return maxSegmentMinusOne
case p <= minSegment:
return minSegmentMinusOne
default:
return p - 1
}
}
//var p = make([]int, 0, 128)
func acquireSegments(c int) []int {
// return p
// fmt.Printf("a%d;", getIdx(c))
return segmentsPools[getIdx(c)].Get()
}
func releaseSegments(s []int) {
// p = s
// fmt.Printf("r%d;", getIdx(cap(s)))
segmentsPools[getIdx(cap(s))].Put(s)
}
type newSegmentsFunc func() []int
// Pool holds Clients.
type PoolSequenced struct {
new newSegmentsFunc
pool chan []int
}
// NewPool creates a new pool of Clients.
func NewPoolSequenced(size int, f newSegmentsFunc) *PoolSequenced {
return &PoolSequenced{
new: f,
pool: make(chan []int, size),
}
}
// Borrow a Client from the pool.
func (p *PoolSequenced) Get() []int {
var s []int
select {
case s = <-p.pool:
default:
s = p.new()
}
return s[:0]
}
// Return returns a Client to the pool.
func (p *PoolSequenced) Put(s []int) {
select {
case p.pool <- s:
default:
// let it go, let it go...
}
}
type PoolSynced struct {
size int
mu sync.Mutex
list [][]int
}
func NewPoolSynced(size int) *PoolSynced {
return &PoolSynced{
size: size,
}
}
func (p *PoolSynced) Get() []int {
var s []int
p.mu.Lock()
ll := len(p.list)
if ll > 0 {
s, p.list = p.list[ll-1], p.list[:ll-1]
}
p.mu.Unlock()
if s == nil {
return make([]int, 0, p.size)
}
return s[:0]
}
func (p *PoolSynced) Put(s []int) {
p.mu.Lock()
defer p.mu.Unlock()
p.list = append(p.list, s)
}
type PoolNative struct {
size int
pool sync.Pool
}
func NewPoolNative(size int) *PoolNative {
return &PoolNative{
size: size,
}
}
func (p *PoolNative) Get() []int {
s := p.pool.Get()
if s == nil {
return make([]int, 0, p.size)
}
return s.([]int)
}
func (p *PoolNative) Put(s []int) {
p.pool.Put(s)
}