Skip to content

Pass the prefix by reference in storage key prefix iteration - #2100

Open
oliv3rdrt wants to merge 1 commit into
mintlayer:masterfrom
oliv3rdrt:refactor/417-storage-prefix-by-ref
Open

Pass the prefix by reference in storage key prefix iteration#2100
oliv3rdrt wants to merge 1 commit into
mintlayer:masterfrom
oliv3rdrt:refactor/417-storage-prefix-by-ref

Conversation

@oliv3rdrt

Copy link
Copy Markdown

The prefix and key passed to prefix_iter and greater_equal_iter are only read, but they were taken by value, so callers had to hand over an owned Vec even when they already had a slice. In the locking adaptor this meant cloning the prefix twice on every call.

This changes the ReadOps methods, and the matching helpers in the database module, to take &[u8], and updates the backends (in-memory, lmdb, sqlite, failing, and the locking adaptor) and their callers.

What it removes in practice:

  • the two prefix.clone() calls and the key.clone() in the locking adaptor
  • Vec::new() and Data::new() allocations at call sites that only needed an empty prefix
  • a couple of clone() calls in the backend test suite

One thing worth a look during review: since the crate is on edition 2024, the returned impl Iterator would otherwise capture the prefix lifetime as well as the transaction's. I used the precise capturing syntax (use<..>) on the trait methods and the impls so the iterator only borrows from the transaction, which is what the previous signature effectively guaranteed. If you would rather see it done another way I am happy to change it.

Checked with cargo check --workspace --all-targets, cargo fmt, and the storage tests (storage, storage-core, storage-inmemory, storage-lmdb, storage-sqlite) plus chainstate-storage and utxo, all passing. Note that a few of the lmdb property tests fail intermittently when run in parallel both with and without this change, which looks like the flakiness tracked in #762, they pass with --test-threads=1.

Addresses #417.

The prefix and key passed to prefix_iter and greater_equal_iter are only read,
but they were taken by value, so callers had to hand over an owned Vec and in
a few places clone it first. Change the ReadOps methods, and the corresponding
helpers in the database module, to take a slice instead, and update the
backends and their callers.

This removes the clones in the locking adaptor, which cloned the prefix twice
per call, and lets callers that only have a slice avoid allocating. The
returned iterator borrows from the transaction only, so the precise capturing
syntax is used to keep it from borrowing the prefix as well.
@oliv3rdrt

Copy link
Copy Markdown
Author

@erubboli can I be assigned this?

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.

1 participant