Skip to content

Commit 01b8ef0

Browse files
committed
change implementation of kvbatch copying []byte into C
previous implementation used C.memmove to do heavy lifting doing this involves passing a pointer into the []byte to C in Go 1.6 this has an unintended performance penalty as it unnecessarily checks the entire slice this is a bug in Go 1.6 documented here: golang/go#14387 however, it seems as though this call can be avoided entirely, by creating an artificial slice header which points to the newly malloc'd C buffer, we use Go's builtin copy() method in addition to avoid this bug, it also avoids a cgo call which we know can add up Change-Id: I910e5705e29e6c86343fd0e6315c8430f56b07ef Reviewed-on: http://review.couchbase.org/60991 Reviewed-by: Steve Yen <[email protected]> Tested-by: Marty Schoch <[email protected]>
1 parent 21e1d59 commit 01b8ef0

File tree

1 file changed

+24
-25
lines changed

1 file changed

+24
-25
lines changed

kvbatch.go

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ package forestdb
1010
// and limitations under the License.
1111

1212
//#include <stdlib.h>
13-
//#include <string.h>
1413
//#include <libforestdb/forestdb.h>
1514
import "C"
16-
import "unsafe"
15+
import (
16+
"reflect"
17+
"unsafe"
18+
)
1719

1820
type batchOp struct {
1921
del bool
@@ -33,34 +35,31 @@ func NewKVBatch() *KVBatch {
3335
}
3436
}
3537

38+
func copySliceToC(in []byte) (C.size_t, unsafe.Pointer) {
39+
outl := C.size_t(len(in))
40+
outv := C.malloc(outl)
41+
var tmpSlice []byte
42+
shdr := (*reflect.SliceHeader)(unsafe.Pointer(&tmpSlice))
43+
shdr.Data = uintptr(outv)
44+
shdr.Len = int(outl)
45+
shdr.Cap = shdr.Len
46+
copy(tmpSlice, in)
47+
return outl, outv
48+
}
49+
3650
func (b *KVBatch) Set(k, v []byte) {
37-
klen := C.size_t(len(k))
38-
kc := C.malloc(klen)
39-
C.memmove(kc, unsafe.Pointer(&k[0]), klen)
40-
vlen := C.size_t(len(v))
41-
var vc unsafe.Pointer
42-
if vlen > 0 {
43-
vc = C.malloc(vlen)
44-
C.memmove(vc, unsafe.Pointer(&v[0]), vlen)
51+
bo := batchOp{del: false}
52+
bo.klen, bo.k = copySliceToC(k)
53+
if len(v) > 0 {
54+
bo.vlen, bo.v = copySliceToC(v)
4555
}
46-
b.ops = append(b.ops, &batchOp{
47-
del: false,
48-
k: unsafe.Pointer(kc),
49-
klen: klen,
50-
v: unsafe.Pointer(vc),
51-
vlen: vlen,
52-
})
56+
b.ops = append(b.ops, &bo)
5357
}
5458

5559
func (b *KVBatch) Delete(k []byte) {
56-
klen := C.size_t(len(k))
57-
kc := C.malloc(klen)
58-
C.memmove(kc, unsafe.Pointer(&k[0]), klen)
59-
b.ops = append(b.ops, &batchOp{
60-
del: true,
61-
k: unsafe.Pointer(kc),
62-
klen: klen,
63-
})
60+
bo := batchOp{del: true}
61+
bo.klen, bo.k = copySliceToC(k)
62+
b.ops = append(b.ops, &bo)
6463
}
6564

6665
func (b *KVBatch) Reset() {

0 commit comments

Comments
 (0)