Skip to content

Instantly share code, notes, and snippets.

@zz-jason
Created November 7, 2018 02:20
Show Gist options
  • Save zz-jason/c98d942dddbb32c134c9cadffd983f61 to your computer and use it in GitHub Desktop.
Save zz-jason/c98d942dddbb32c134c9cadffd983f61 to your computer and use it in GitHub Desktop.
benchmarks of different column pool implementations
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())
}
})
}
@zz-jason
Copy link
Author

zz-jason commented Nov 7, 2018

the benchmark results are:

[jianzhang.zj:~/opt ... tidb/util/chunk] git:(colpool/pool ✗)
➜ go test -bench BenchmarkColPool -run xx -count 5 -parallel 100 -benchmem
goos: darwin
goarch: amd64
pkg: github.com/pingcap/tidb/util/chunk
BenchmarkColPoolSlice-8         10000000               191 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolSlice-8         10000000               192 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolSlice-8         10000000               200 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolSlice-8         10000000               197 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolSlice-8         10000000               197 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolList-8           5000000               271 ns/op              48 B/op          1 allocs/op
BenchmarkColPoolList-8           5000000               276 ns/op              48 B/op          1 allocs/op
BenchmarkColPoolList-8           5000000               277 ns/op              48 B/op          1 allocs/op
BenchmarkColPoolList-8           5000000               274 ns/op              48 B/op          1 allocs/op
BenchmarkColPoolList-8           5000000               277 ns/op              48 B/op          1 allocs/op
BenchmarkColPoolChannel-8       10000000               115 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolChannel-8       20000000               117 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolChannel-8       10000000               119 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolChannel-8       10000000               119 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolChannel-8       10000000               118 ns/op               0 B/op          0 allocs/op
BenchmarkColPoolSyncPool-8      300000000                5.52 ns/op            0 B/op          0 allocs/op
BenchmarkColPoolSyncPool-8      300000000                5.69 ns/op            0 B/op          0 allocs/op
BenchmarkColPoolSyncPool-8      300000000                5.67 ns/op            0 B/op          0 allocs/op
BenchmarkColPoolSyncPool-8      300000000                5.65 ns/op            0 B/op          0 allocs/op
BenchmarkColPoolSyncPool-8      300000000                5.62 ns/op            0 B/op          0 allocs/op
PASS
ok      github.com/pingcap/tidb/util/chunk      38.202s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment