-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
perf(persistence): reuse cursor for updating history indices #13622
Conversation
where | ||
T: Table<Value = BlockNumberList>, | ||
{ | ||
let mut cursor = self.tx.cursor_read::<T>()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This created a new cursor per account or storage slot change.
// delete old shard so new one can be inserted. | ||
self.tx.delete::<T>(shard_key, None)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This created another cursor and re-seeked even when cursor
is already on the needed key.
while let Some(list) = chunks.next() { | ||
let highest_block_number = if chunks.peek().is_some() { | ||
*list.last().expect("`chunks` does not return empty list") | ||
} else { | ||
// Insert last list with `u64::MAX`. | ||
u64::MAX | ||
}; | ||
self.tx.put::<T>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This created another cursor per chunk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let mut cursor = self.tx.cursor_write::<T>()?; | ||
for (partial_key, indices) in index_updates { | ||
let mut last_shard = | ||
self.take_shard::<T>(sharded_key_factory(partial_key, u64::MAX))?; | ||
self.take_shard::<T>(&mut cursor, sharded_key_factory(partial_key, u64::MAX))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this makes sense @rkrasiuk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense to me too
while let Some(list) = chunks.next() { | ||
let highest_block_number = if chunks.peek().is_some() { | ||
*list.last().expect("`chunks` does not return empty list") | ||
} else { | ||
// Insert last list with `u64::MAX`. | ||
u64::MAX | ||
}; | ||
self.tx.put::<T>( | ||
cursor.insert( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shekhirin @joshieDo any difference between tx.put
and cursor.insert
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when inserting multiple values, generally yes: #1130 (comment)
@hai-rise mind rebasing this pr? |
In our latest test load,
save_blocks
spends ~2.5% of its time creating and dropping new cursors intake_shard
alone. Another ~15% is spent on relatedtx.delete
andtx.put
that internally also create a new cursor per call.This PR minimizes the number of cursors per
append_history_index
from the number of changes (accounts or storage slots) * (2 + number of block shards) to only 1 cursor per table.P/s: this is untested code but I hope it improves
save_blocks
by 3~5% for us.