diff --git a/mdbx/mdbxgo.c b/mdbx/mdbxgo.c index 5ba68a8..e1dfc7f 100644 --- a/mdbx/mdbxgo.c +++ b/mdbx/mdbxgo.c @@ -7,6 +7,8 @@ #include "mdbxgo.h" #include "mdbx.h" +#define MDBXGO_SET_VAL_UINTPTR(val, size, data) \ + *(val) = (MDBX_val){ .iov_len = (size), .iov_base = ((char*)(uintptr_t)data) } #define MDBXGO_SET_VAL(val, size, data) \ *(val) = (MDBX_val){ .iov_len = (size), .iov_base = (data) } @@ -41,6 +43,14 @@ int mdbxgo_get(MDBX_txn *txn, MDBX_dbi dbi, char *kdata, size_t kn, MDBX_val *va return mdbx_get(txn, dbi, &key, val); } +int mdbxgo_getfast(uint64_t txnUint, MDBX_dbi dbi, uint64_t kdataUint, size_t kn, uint64_t valUint) { + MDBX_val key; + MDBXGO_SET_VAL_UINTPTR(&key, kn, kdataUint); + MDBX_txn* txn = (MDBX_txn*)(uintptr_t)txnUint; + MDBX_val* val = (MDBX_val*)(uintptr_t)valUint; + 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..ccb1522 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(uint64_t txnUint, MDBX_dbi dbi, uint64_t kdataUint, size_t kn, uint64_t valUint); 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..7009cc2 100644 --- a/mdbx/txn.go +++ b/mdbx/txn.go @@ -605,6 +605,40 @@ func (txn *Txn) Get(dbi DBI, key []byte) ([]byte, error) { return b, nil } +func TxnGetFast(txn uint64, val uint64, dbi DBI, key uint64, lenK int) error { + var k, v, tx C.uint64_t + if key > 0 { + k = C.uint64_t(key) + } + + if val > 0 { + v = C.uint64_t(val) + } + + if txn > 0 { + tx = C.uint64_t(key) + } + + ret := C.mdbxgo_getfast( + tx, C.MDBX_dbi(dbi), + k, C.size_t(lenK), + v, + ) + err := operrno("mdbx_getfast", ret) + if err != nil { + return err + } + + return nil +} + +func TxnGetFastWrap(txn *Txn, dbi DBI, k []byte) ([]byte, error) { + err := TxnGetFast(uint64(uintptr(unsafe.Pointer(txn._txn))), uint64(uintptr(unsafe.Pointer(txn.val))), dbi, uint64(uintptr(unsafe.Pointer(&k[0]))), len(k)) + b := castToBytes(txn.val) + *txn.val = C.MDBX_val{} + return b, err +} + // Put stores an item in database dbi. // // See mdbx_put. diff --git a/mdbx/txn_test.go b/mdbx/txn_test.go index 60f0dce..ad14f2f 100644 --- a/mdbx/txn_test.go +++ b/mdbx/txn_test.go @@ -1288,7 +1288,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 = TxnGetFastWrap(txn, db, k) if err != nil { return err }