Created
November 7, 2018 02:20
-
-
Save zz-jason/c98d942dddbb32c134c9cadffd983f61 to your computer and use it in GitHub Desktop.
benchmarks of different column pool implementations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package chunk | |
import ( | |
"container/list" | |
"sync" | |
"testing" | |
) | |
// implementation and benchmark of colPoolSlice. | |
type colPoolSlice struct { | |
sync.Mutex | |
cols []*column | |
} | |
func (ps *colPoolSlice) put(col *column) { | |
ps.Lock() | |
defer ps.Unlock() | |
ps.cols = append(ps.cols, col) | |
} | |
func (ps *colPoolSlice) get() *column { | |
ps.Lock() | |
defer ps.Unlock() | |
if len(ps.cols) > 0 { | |
col := ps.cols[len(ps.cols)-1] | |
ps.cols = ps.cols[:len(ps.cols)-1] | |
return col | |
} | |
return nil | |
} | |
func BenchmarkColPoolSlice(b *testing.B) { | |
pool := &colPoolSlice{cols: make([]*column, 0, 128)} | |
col := newFixedLenColumn(8, 1024) | |
pool.put(col) | |
b.ResetTimer() | |
b.RunParallel(func(pb *testing.PB) { | |
for pb.Next() { | |
pool.put(pool.get()) | |
} | |
}) | |
} | |
// implementation and benchmark of colPoolList. | |
type colPoolList struct { | |
sync.Mutex | |
cols *list.List | |
} | |
func (ps *colPoolList) put(col *column) { | |
ps.Lock() | |
defer ps.Unlock() | |
ps.cols.PushFront(col) | |
} | |
func (ps *colPoolList) get() *column { | |
ps.Lock() | |
defer ps.Unlock() | |
if ps.cols.Len() > 0 { | |
head := ps.cols.Front() | |
return ps.cols.Remove(head).(*column) | |
} | |
return nil | |
} | |
func BenchmarkColPoolList(b *testing.B) { | |
pool := &colPoolList{cols: list.New()} | |
col := newFixedLenColumn(8, 1024) | |
pool.put(col) | |
b.ResetTimer() | |
b.RunParallel(func(pb *testing.PB) { | |
for pb.Next() { | |
pool.put(pool.get()) | |
} | |
}) | |
} | |
// implementation and benchmark of colPoolChannel. | |
type colPoolChannel struct { | |
pool chan *column | |
elemLen int | |
initCap int | |
} | |
func (p *colPoolChannel) put(col *column) { | |
select { | |
case p.pool <- col: | |
default: | |
// channel full, throw it away. | |
} | |
} | |
func (p *colPoolChannel) get() *column { | |
select { | |
case col := <-p.pool: | |
return col | |
default: | |
return newFixedLenColumn(p.elemLen, p.initCap) | |
} | |
} | |
func BenchmarkColPoolChannel(b *testing.B) { | |
pool := &colPoolChannel{ | |
pool: make(chan *column, 128), | |
elemLen: 8, | |
initCap: 8, | |
} | |
col := newFixedLenColumn(8, 1024) | |
pool.put(col) | |
b.ResetTimer() | |
b.RunParallel(func(pb *testing.PB) { | |
for pb.Next() { | |
pool.put(pool.get()) | |
} | |
}) | |
} | |
// implementation and benchmark of colPoolSyncPool. | |
type colPoolSyncPool struct { | |
sync.Pool | |
} | |
func NewColPoolSyncPool(elemLen int, initCap int) *colPoolSyncPool { | |
return &colPoolSyncPool{ | |
Pool: sync.Pool{ | |
// The Pool's New function should generally only return pointer | |
// types, since a pointer can be put into the return interface | |
// value without an allocation: | |
New: func() interface{} { return newFixedLenColumn(elemLen, initCap) }, | |
}, | |
} | |
} | |
func (p *colPoolSyncPool) put(col *column) { | |
p.Put(col) | |
} | |
func (p *colPoolSyncPool) get() *column { | |
return p.Get().(*column) | |
} | |
func BenchmarkColPoolSyncPool(b *testing.B) { | |
pool := NewColPoolSyncPool(8, 1024) | |
col := newFixedLenColumn(8, 1024) | |
pool.put(col) | |
b.ResetTimer() | |
b.RunParallel(func(pb *testing.PB) { | |
for pb.Next() { | |
pool.put(pool.get()) | |
} | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
the benchmark results are: