Commit 8e77cf48 authored by Kirill Smelkov's avatar Kirill Smelkov

X BufAlloc draftly works

parent f6017d6d
...@@ -21,7 +21,6 @@ package zodb ...@@ -21,7 +21,6 @@ package zodb
// data buffers management // data buffers management
import ( import (
"math/bits"
"sync" "sync"
"lab.nexedi.com/kirr/go123/xmath" "lab.nexedi.com/kirr/go123/xmath"
...@@ -46,7 +45,9 @@ var bufPoolv = [14]sync.Pool{} // buf size stop at 2^(4+14-1) (=128K) ...@@ -46,7 +45,9 @@ var bufPoolv = [14]sync.Pool{} // buf size stop at 2^(4+14-1) (=128K)
func init() { func init() {
for i := 0; i < len(bufPoolv); i++ { for i := 0; i < len(bufPoolv); i++ {
i := i
bufPoolv[i].New = func() interface{} { bufPoolv[i].New = func() interface{} {
//println("X allocating for order", i)
// NOTE *Buf, not just buf, to avoid allocation when // NOTE *Buf, not just buf, to avoid allocation when
// making interface{} from it (interface{} wants to always point to heap) // making interface{} from it (interface{} wants to always point to heap)
return &Buf{Data: make([]byte, 1 << (order0 + uint(i)))} return &Buf{Data: make([]byte, 1 << (order0 + uint(i)))}
...@@ -61,17 +62,22 @@ func BufAlloc(size int) *Buf { ...@@ -61,17 +62,22 @@ func BufAlloc(size int) *Buf {
// order = min i: 2^i >= size // order = min i: 2^i >= size
order := xmath.CeilLog2(uint64(size)) order := xmath.CeilLog2(uint64(size))
//println("alloc", size, "order:", order)
order -= order0 order -= order0
if order < 0 { if order < 0 {
order = 0 order = 0
} }
//println("\t->", order)
// if too big - allocate straightly from heap // if too big - allocate straightly from heap
if order >= len(bufPoolv) { if order >= len(bufPoolv) {
return &Buf{Data: make([]byte, size)} return &Buf{Data: make([]byte, size)}
} }
buf := bufPoolv[order].Get().(*Buf) buf := bufPoolv[order].Get().(*Buf)
//println("\tlen:", len(buf.Data), "cap:", cap(buf.Data))
buf.Data = buf.Data[:size] // leaving cap as is = 2^i buf.Data = buf.Data[:size] // leaving cap as is = 2^i
return buf return buf
} }
...@@ -81,7 +87,9 @@ func BufAlloc(size int) *Buf { ...@@ -81,7 +87,9 @@ func BufAlloc(size int) *Buf {
// The caller must not use buf after call to Free. // The caller must not use buf after call to Free.
func (buf *Buf) Free() { func (buf *Buf) Free() {
// order = max i: 2^i <= cap // order = max i: 2^i <= cap
order := bits.Len(uint(cap(buf.Data))) //order := bits.Len(uint(cap(buf.Data)))
order := xmath.FloorLog2(uint64(cap(buf.Data)))
//println("YYY free", cap(buf.Data), "-> order:", order)
order -= order0 order -= order0
if order < 0 { if order < 0 {
......
// Copyright (C) 2017 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package zodb
import (
"reflect"
"testing"
"unsafe"
)
func sliceDataPtr(b []byte) unsafe.Pointer {
return unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data)
}
func TestBufAllocFree(t *testing.T) {
for i := uint(0); i < 20; i++ {
//if i < 7 { continue }
size := 1<<i - 1
xcap := 1<<i
buf := BufAlloc(size)
if i < order0 {
xcap = 1<<order0
}
if int(i) >= order0 + len(bufPoolv) {
xcap = size
}
if len(buf.Data) != size {
t.Errorf("%v: len=%v ; want %v", i, len(buf.Data), size)
}
if cap(buf.Data) != xcap {
t.Errorf("%v: cap=%v ; want %v", i, cap(buf.Data), xcap)
}
// this allocations are not from pool - memory won't be reused
if int(i) >= order0 + len(bufPoolv) {
continue
}
// free and allocate another buf -> it must be it
data := buf.Data
buf.Free()
buf2 := BufAlloc(size)
if !(buf2 == buf && sliceDataPtr(buf2.Data) == sliceDataPtr(data)) {
t.Errorf("%v: buffer not reused on free/realloc", i)
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment