From 5bfb29d1a8810b802ab117dc2fbc211ae213b32f Mon Sep 17 00:00:00 2001 From: Ilya Miheev Date: Wed, 12 Jun 2024 11:38:21 +0400 Subject: [PATCH 1/2] added valNP (no pointer value) argument to Txn obj tp increase performance (see GetFast for more details) --- mdbx/txn.go | 29 +++++++++++++++++++++++++---- mdbx/txn_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) 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) From 6f9a27c0dbed2d4c0756aa30bca0e6e0fedd791b Mon Sep 17 00:00:00 2001 From: Ilya Miheev Date: Wed, 12 Jun 2024 12:03:56 +0400 Subject: [PATCH 2/2] replace txn.Get with txn.GetFast realization --- mdbx/txn.go | 24 ++---------------------- mdbx/txn_test.go | 36 ------------------------------------ 2 files changed, 2 insertions(+), 58 deletions(-) diff --git a/mdbx/txn.go b/mdbx/txn.go index 1d7b51c..2a15005 100644 --- a/mdbx/txn.go +++ b/mdbx/txn.go @@ -587,26 +587,6 @@ func (txn *Txn) bytes(val *C.MDBX_val) []byte { // // See mdbx_get. func (txn *Txn) Get(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.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 []byte) ([]byte, error) { var k *C.char if len(key) > 0 { k = (*C.char)(unsafe.Pointer(&key[0])) @@ -618,11 +598,11 @@ func (txn *Txn) GetFast(dbi DBI, key []byte) ([]byte, error) { ) err := operrno("mdbx_get", ret) if err != nil { - txn.valNP = C.MDBX_val{} + txn.valNP.iov_base, txn.valNP.iov_len = nil, 0 return nil, err } b := castToBytes(&txn.valNP) - txn.valNP = C.MDBX_val{} + txn.valNP.iov_base, txn.valNP.iov_len = nil, 0 return b, nil } diff --git a/mdbx/txn_test.go b/mdbx/txn_test.go index 65e426d..60f0dce 100644 --- a/mdbx/txn_test.go +++ b/mdbx/txn_test.go @@ -1299,42 +1299,6 @@ 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)