diff --git a/mdbx/txn.go b/mdbx/txn.go index fa1787b..1d7b51c 100644 --- a/mdbx/txn.go +++ b/mdbx/txn.go @@ -57,10 +57,11 @@ const ( // // See MDBX_txn. type Txn struct { - env *Env - _txn *C.MDBX_txn - key *C.MDBX_val - val *C.MDBX_val + env *Env + _txn *C.MDBX_txn + key *C.MDBX_val + valNP C.MDBX_val + val *C.MDBX_val errLogf func(format string, v ...interface{}) @@ -605,6 +606,26 @@ func (txn *Txn) Get(dbi DBI, key []byte) ([]byte, error) { return b, nil } +func (txn *Txn) GetFast(dbi DBI, key []byte) ([]byte, error) { + var k *C.char + if len(key) > 0 { + k = (*C.char)(unsafe.Pointer(&key[0])) + } + ret := C.mdbxgo_get( + txn._txn, C.MDBX_dbi(dbi), + k, C.size_t(len(key)), + &txn.valNP, + ) + err := operrno("mdbx_get", ret) + if err != nil { + txn.valNP = C.MDBX_val{} + return nil, err + } + b := castToBytes(&txn.valNP) + txn.valNP = C.MDBX_val{} + return b, nil +} + // Put stores an item in database dbi. // // See mdbx_put. diff --git a/mdbx/txn_test.go b/mdbx/txn_test.go index 60f0dce..65e426d 100644 --- a/mdbx/txn_test.go +++ b/mdbx/txn_test.go @@ -1299,6 +1299,42 @@ func BenchmarkTxn_Get(b *testing.B) { } } +func BenchmarkTxn_GetFast(b *testing.B) { + env, _ := setup(b) + + var db DBI + k := make([]byte, 8) + binary.BigEndian.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) + if err != nil { + return err + } + return nil + }); err != nil { + b.Errorf("dbi: %v", err) + return + } + + if err := env.View(func(txn *Txn) (err error) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := txn.GetFast(db, k) + if err != nil { + return err + } + } + return nil + }); err != nil { + b.Errorf("put: %v", err) + } +} + func TestTxnEnvWarmup(t *testing.T) { env, _ := setup(t)