Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(db): mdbx integration & table skeletons #15

Merged
merged 15 commits into from
Oct 10, 2022
Merged

feat(db): mdbx integration & table skeletons #15

merged 15 commits into from
Oct 10, 2022

Conversation

joshieDo
Copy link
Collaborator

@joshieDo joshieDo commented Oct 5, 2022

I think it's a good first step.

Next follow-ups:

  • Start implementing the actual model types alongside their encoders/decoders.
  • Improve/add functions to access/manage libmdbx cursor as it is needed.
  • page_size/sizes/ open params

Theoretically, you insert stuff already, as long as it is a Vec<u8>. Check tests at crates/db/src/kv/mod.rs and some table declarations at crates/db/src/kv/tables.rs

@joshieDo joshieDo changed the title wip: kv mdbx wip: feat(db) mdbx Oct 5, 2022
@joshieDo joshieDo changed the title wip: feat(db) mdbx feat(db): mdbx integration & table skeletons Oct 6, 2022
@joshieDo joshieDo requested review from onbjerg and rakita and removed request for onbjerg and rakita October 6, 2022 12:24
crates/db/src/kv/cursor.rs Outdated Show resolved Hide resolved
crates/db/src/kv/cursor.rs Show resolved Hide resolved
crates/db/src/kv/mod.rs Outdated Show resolved Hide resolved
@rakita
Copy link
Collaborator

rakita commented Oct 7, 2022

This is very nice and clean, amazing work.

We start with the Env which can be NonWrite or Write (this is EnvironmentKind) depending in what mode db was open.

Env can spawn transactions Tx that can be ReadOnly or ReadWrite (this is TransactionKind). Internally it needs Environment maybe to spawn additional Tx, not sure. That is why we have both generics in Tx structure.

Tx have generic functions over Tables.
For RO and RW we have get and cursor and for RW we have put, delete and clear functions

Table is a placeholder that specifies Key and Value that are inside db and how to parse them (SeekKey is used inside Cursor for seeking the exact key)

and Cursor that takes TransactionType and Table allows us iteration over values.

@rakita
Copy link
Collaborator

rakita commented Oct 7, 2022

Only question, that is work for later, out of scope for this, is how are we going to abstract this, as in defining some trait that can use both mdbx and our In memory implementation (for example).

Maybe the abstraction cut is between Env and Tx as in define trait that has get,cursor,put, etc.?

@gakonst
Copy link
Member

gakonst commented Oct 7, 2022

Maybe the abstraction cut is between Env and Tx as in define trait that has get,cursor,put, etc.?

This makes sense as a direction.

Copy link
Member

@gakonst gakonst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is looking great. a few nits.

})
.set_flags(EnvironmentFlags {
mode,
no_rdahead: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the Erigon team on Discord had indicated that read ahead might be useful in some cases

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a TODO to reevaluate later

Comment on lines +201 to +204
let result = env.update(|tx| {
tx.put(PlainState, key, value.clone()).expect(ERROR_PUT);
200
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this API is really sick.

@@ -0,0 +1,131 @@
//! Table traits.
#![allow(missing_docs)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove and just add the docs to the encode/decode functions below?

Comment on lines +92 to +115
//
// TODO: Temporary types, until they're properly defined alongside with the Encode and Decode Trait
//

type ConfigKey = Vec<u8>;
type ConfigValue = Vec<u8>;
#[allow(non_camel_case_types)]
type BNum_BHash = Vec<u8>;
#[allow(non_camel_case_types)]
type BNum_BHash_TxId = Vec<u8>;
type RlpHeader = Vec<u8>;
type RlpTotalDifficulty = Vec<u8>;
type RlpTxBody = Vec<u8>;
type Receipt = Vec<u8>;
type NumTxesInBlock = u16; // TODO can it be u16
type BNum = u64; // TODO check size
type TxId = u64; // TODO check size
type HeaderHash = U256;
type PlainStateKey = Address; // TODO new type will have to account for address_incarna_skey as well
type TxIdList = Vec<u8>;
#[allow(non_camel_case_types)]
type Address_StorageKey = Vec<u8>;
type AccountBeforeTx = Vec<u8>;
type StorageKeyBeforeTx = Vec<u8>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is your plan here?

Copy link
Collaborator Author

@joshieDo joshieDo Oct 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the plan is to start implementing proper types for them, and remove them from here on further PRs

they're here now just as placeholders, and can be used by other crates if really necessary

Comment on lines 82 to 83
/// Deletes the `(key, value)` entry on `table`.
pub fn delete<T>(&self, table: T, key: T::Key, value: Option<T::Value>) -> Result<bool, KVError>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we need to provide value as Some? isn't the key always enough to delete both of them?

nvm from the docs

The data parameter is NOT ignored regardless the database does support sorted duplicate data items or not. If the data parameter is Some only the matching data item will be deleted. Otherwise, if data parameter is None, any/all value(s) for specified key will be deleted.

Let's add that note about value: Option<_> in the function doc?

Comment on lines 7 to 9

//! Database bindings for reth.
// TODO: Actually provide database bindings. For now, this is just a re-export of MDBX.
//! DB primitives for reth.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd just delete this, if you have the 1st line above

Comment on lines 19 to 28
let libmdbx_max_page_size = 0x10000;

if os_page_size < 4096 {
// May lead to errors if it's reduced further because of the potential size of the data.
4096
} else if os_page_size > libmdbx_max_page_size {
libmdbx_max_page_size
} else {
os_page_size
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this work?

Copy link
Collaborator Author

@joshieDo joshieDo Oct 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a source on the libmdbx max page size.

about the minimum value... that seems to have been the experience of erigon.

in my understanding, as long as it's supported by the system, a bigger page results in better performance

Copy link
Member

@onbjerg onbjerg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

marking here that it looks ok from my pov modulo georgios' comments 😄

Copy link
Member

@gakonst gakonst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Merging so we can iterate on it.

Please remove the static.rs in a follow-up PR, and add any glue tests as recommended so we don't have weird regressions later on.

}
self.cursor.next_dup_val().transpose()
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe OK to not add tests given this mostly forwards to LibMDBX, but if you don't think adding some regression tests to make sure we don't break anything later on (or if we want to e.g. optimize / bench) that'd help

Comment on lines +54 to +64
size: Some(0..0x100000), // TODO: reevaluate
growth_step: Some(0x100000), // TODO: reevaluate
shrink_threshold: None,
page_size: Some(PageSize::Set(default_page_size())),
})
.set_flags(EnvironmentFlags {
mode,
no_rdahead: true, // TODO: reevaluate
coalesce: true,
..Default::default()
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's track in an issue that we may want to make these configurable via CLI. Suspect we'll end up running benchmarks with various configs to compare perf.

@gakonst gakonst merged commit 60d3c64 into main Oct 10, 2022
@gakonst gakonst deleted the joshie/kv_mdbx branch October 10, 2022 19:35
@joshieDo joshieDo mentioned this pull request Oct 14, 2022
6 tasks
anonymousGiga added a commit to anonymousGiga/reth that referenced this pull request Feb 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants