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

db-api: trait Compress and Encode use reference self #11186

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

nkysg
Copy link
Contributor

@nkysg nkysg commented Sep 25, 2024

ref #11185.

Trait Encode fn encodes use self. It's a bit weird.

I see many crate use &self, like

This is alloyed rlp Encode trait.
https://github.com/alloy-rs/rlp/blob/9aef28e6da7c2769460dd6bf22eeacd53adf0ffc/crates/rlp/src/encode.rs#L15

/// A type that can be encoded via RLP.
pub trait Encodable {
    /// Encodes the type into the `out` buffer.
    fn encode(&self, out: &mut dyn BufMut);

    /// Returns the length of the encoding of this type in bytes.
    ///
    /// The default implementation computes this by encoding the type.
    /// When possible, we recommender implementers override this with a
    /// specialized implementation.
    #[inline]
    fn length(&self) -> usize {
        let mut out = Vec::new();
        self.encode(&mut out);
        out.len()
    }
}

And then maybe we can remove some clone. I think some db fn like put also can use reference

fn compress(self) -> Self::Compressed {
self.value
fn compress(&self) -> Self::Compressed {
self.value.clone()
Copy link
Collaborator

Choose a reason for hiding this comment

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

headers, tx_lookup and hashing_account stages use this heavily, tbh don't know the impact of cloning for each row

wdyt @DaniPopes

Copy link
Member

Choose a reason for hiding this comment

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

better to return &Self::Compressed and letting caller context clone, if I understood the issue right, this is happening anyway on main?

always better to call clone in context using return value, so the dev is conscious of this perf downgrade wherever it's used.

fn encode(self) -> Self::Encoded {
self.key
fn encode(&self) -> Self::Encoded {
self.key.clone()
Copy link
Collaborator

Choose a reason for hiding this comment

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

same

@DaniPopes
Copy link
Member

This can only work if we propagate the reference all the way to all call sites (taking in &Table::Value by reference everywhere), and if type Encoded is changed to have a lifetime so we can return a reference to self in simple cases like &Vec<u8> -> &[u8]; even then, if we always have an owned key at all call sites this is not going to change a whole lot

@nkysg nkysg closed this Sep 26, 2024
@DaniPopes
Copy link
Member

DaniPopes commented Sep 27, 2024

@nkysg Hey actually I didn't consider another usecase, which is taking by reference in the DbTxMut methods and alike; this allows re-using buffers like so:

diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs
index 7159720bf..9efba8805 100644
--- a/crates/storage/provider/src/providers/database/provider.rs
+++ b/crates/storage/provider/src/providers/database/provider.rs
@@ -1340,6 +1340,7 @@ impl<TX: DbTxMut + DbTx, Spec: Send + Sync> DatabaseProvider<TX, Spec> {
         P: Copy,
         T: Table<Value = BlockNumberList>,
     {
+        let mut number_list = BlockNumberList::empty();
         for (partial_key, indices) in index_updates {
             let mut last_shard =
                 self.take_shard::<T>(sharded_key_factory(partial_key, u64::MAX))?;
@@ -1354,9 +1355,11 @@ impl<TX: DbTxMut + DbTx, Spec: Send + Sync> DatabaseProvider<TX, Spec> {
                     // Insert last list with `u64::MAX`.
                     u64::MAX
                 };
+                number_list.clear();
+                number_list.append(list.iter().copied());
                 self.tx.put::<T>(
                     sharded_key_factory(partial_key, highest_block_number),
-                    BlockNumberList::new_pre_sorted(list.iter().copied()),
+                    &number_list,
                 )?;
             }
         }

I think we should keep going with this, do you mind picking this up again? If not I'll open an issue for it

@nkysg nkysg reopened this Sep 27, 2024
@nkysg
Copy link
Contributor Author

nkysg commented Sep 27, 2024

@DaniPopes Got it. Thanks sir. pleasure to give me some suggestions to improve this. and I have opened this issue #11185 again.

@github-actions github-actions bot added the S-stale This issue/PR is stale and will close with no further activity label Oct 31, 2024
@github-actions github-actions bot removed the S-stale This issue/PR is stale and will close with no further activity label Nov 14, 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.

4 participants