diff --git a/mdbx/mdbxgo.c b/mdbx/mdbxgo.c index 5ba68a8..31ebef4 100644 --- a/mdbx/mdbxgo.c +++ b/mdbx/mdbxgo.c @@ -35,12 +35,18 @@ int mdbxgo_del(MDBX_txn *txn, MDBX_dbi dbi, char *kdata, size_t kn, char *vdata, return mdbx_del(txn, dbi, &key, NULL); } -int mdbxgo_get(MDBX_txn *txn, MDBX_dbi dbi, char *kdata, size_t kn, MDBX_val *val) { +int mdbxgo_get(MDBX_txn *txn, MDBX_dbi dbi, char* kdata, size_t kn, MDBX_val *val) { MDBX_val key; MDBXGO_SET_VAL(&key, kn, kdata); return mdbx_get(txn, dbi, &key, val); } +int mdbxgo_getfast(MDBX_txn *txn, MDBX_dbi dbi, char kdata[128], MDBX_val *val) { + MDBX_val key; + MDBXGO_SET_VAL(&key, 128, kdata); + return mdbx_get(txn, dbi, &key, val); +} + int mdbxgo_put2(MDBX_txn *txn, MDBX_dbi dbi, char *kdata, size_t kn, char *vdata, size_t vn, MDBX_put_flags_t flags) { MDBX_val key, val; MDBXGO_SET_VAL(&key, kn, kdata); diff --git a/mdbx/mdbxgo.h b/mdbx/mdbxgo.h index 9b1ed64..c863599 100644 --- a/mdbx/mdbxgo.h +++ b/mdbx/mdbxgo.h @@ -19,6 +19,7 @@ * */ int mdbxgo_del(MDBX_txn *txn, MDBX_dbi dbi, char *kdata, size_t kn, char *vdata, size_t vn); int mdbxgo_get(MDBX_txn *txn, MDBX_dbi dbi, char *kdata, size_t kn, MDBX_val *val); +int mdbxgo_getfast(MDBX_txn *txn, MDBX_dbi dbi, char kdata[128], MDBX_val *val); int mdbxgo_put1(MDBX_txn *txn, MDBX_dbi dbi, char *kdata, size_t kn, MDBX_val *val, MDBX_put_flags_t flags); int mdbxgo_put2(MDBX_txn *txn, MDBX_dbi dbi, char *kdata, size_t kn, char *vdata, size_t vn, MDBX_put_flags_t flags); int mdbxgo_cursor_put1(MDBX_cursor *cur, char *kdata, size_t kn, MDBX_val *val, MDBX_put_flags_t flags); diff --git a/mdbx/txn.go b/mdbx/txn.go index fa1787b..16e1793 100644 --- a/mdbx/txn.go +++ b/mdbx/txn.go @@ -596,6 +596,26 @@ func (txn *Txn) Get(dbi DBI, key []byte) ([]byte, error) { txn.val, ) err := operrno("mdbx_get", ret) + if err != nil { + //*txn.val = C.MDBX_val{} + return nil, err + } + b := castToBytes(txn.val) + //*txn.val = C.MDBX_val{} + return b, nil +} + +func (txn *Txn) GetFast(dbi DBI, key [128]byte) ([]byte, error) { + var ckey [128]C.char + for i, v := range key { + ckey[i] = C.char(v) + } + ret := C.mdbxgo_getfast( + txn._txn, C.MDBX_dbi(dbi), + ckey, + txn.val, + ) + err := operrno("mdbx_getfast", ret) if err != nil { *txn.val = C.MDBX_val{} return nil, err diff --git a/mdbx/txn_test.go b/mdbx/txn_test.go index 60f0dce..722525c 100644 --- a/mdbx/txn_test.go +++ b/mdbx/txn_test.go @@ -1263,19 +1263,33 @@ func openDBI(env *Env, key string, flags uint) (DBI, error) { return db, nil } +func PutUint64(b [128]byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 56) + b[1] = byte(v >> 48) + b[2] = byte(v >> 40) + b[3] = byte(v >> 32) + b[4] = byte(v >> 24) + b[5] = byte(v >> 16) + b[6] = byte(v >> 8) + b[7] = byte(v) +} + func BenchmarkTxn_Get(b *testing.B) { env, _ := setup(b) var db DBI - k := make([]byte, 8) - binary.BigEndian.PutUint64(k, uint64(1)) + k := [128]byte{} + kSl := make([]byte, 8) + binary.BigEndian.PutUint64(kSl, uint64(1)) + PutUint64(k, uint64(1)) if err := env.Update(func(txn *Txn) (err error) { db, err = txn.OpenRoot(0) if err != nil { return err } - err = txn.Put(db, k, k, 0) + err = txn.Put(db, kSl, kSl, 0) if err != nil { return err } @@ -1288,7 +1302,7 @@ func BenchmarkTxn_Get(b *testing.B) { if err := env.View(func(txn *Txn) (err error) { b.ResetTimer() for i := 0; i < b.N; i++ { - _, err := txn.Get(db, k) + _, err := txn.GetFast(db, k) if err != nil { return err }