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: use fixed number of db transactions for storage proofs #14860

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

Rjected
Copy link
Member

@Rjected Rjected commented Mar 6, 2025

Creates a task that manages a fixed number of db transactions, specifically for calculating many storage proofs

ref #14850

@Rjected Rjected added the A-trie Related to Merkle Patricia Trie implementation label Mar 6, 2025
@Rjected Rjected force-pushed the dan/fixed-db-tx-multiproof branch 4 times, most recently from 64136eb to ab4eb0f Compare March 6, 2025 06:09
Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

this looks good already

Comment on lines 98 to 138
if self.pending_targets.front().is_none() {
return;
}

let next_input = self.pending_targets.pop_front().unwrap();

Copy link
Collaborator

Choose a reason for hiding this comment

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

can be let Some else return?

@Rjected Rjected force-pushed the dan/fixed-db-tx-multiproof branch 5 times, most recently from b68a291 to 565b7fc Compare March 10, 2025 17:18
@Rjected Rjected marked this pull request as ready for review March 10, 2025 18:49
@Rjected Rjected force-pushed the dan/fixed-db-tx-multiproof branch 7 times, most recently from 6018b0c to 2d9dc24 Compare March 10, 2025 20:42
Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

some questions about message passing

Comment on lines 72 to 77
// initialize proof task txs
let mut proof_task_txs = Vec::with_capacity(max_concurrency);
for item in &mut proof_task_txs {
let provider_ro = view.provider_ro()?;
let tx = provider_ro.into_tx();
*item = ProofTaskTx::new(tx, task_ctx.clone());
Copy link
Collaborator

Choose a reason for hiding this comment

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

we're currently paying for this upfront before twe spawn this, right?

which doesn't seem reasonable especially because we spawn this and can just do all of this in the background or on demand.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, we could do this on the spawned run function

Copy link
Member Author

Choose a reason for hiding this comment

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

We now create transactions on-demand

Comment on lines 151 to 155
let RunningProofTask { task_receiver, sender } = running_task;
match task_receiver.try_recv() {
Ok(ProofTaskOutput { tx, result }) => {
let _ = sender.send(result);
Copy link
Collaborator

Choose a reason for hiding this comment

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

this feels a bit weird, why are we awaiting both the result and the sender here only to send the result through that sender

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess we could send the result directly in the spawned storage proof task, and only pass the tx back in the ProofTaskOutput

Copy link
Member Author

Choose a reason for hiding this comment

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

now we send the result directly to the sender in storage_proof

Comment on lines +127 to +156
loop {
// TODO: condvar for
// * either running or proof tasks have stuff
// * otherwise yield thread
let message = match self.proof_task_rx.try_recv() {
Ok(message) => match message {
Copy link
Collaborator

Choose a reason for hiding this comment

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

hmm, this task now has do advance more than one channel, making this loop a bit complex with try_recv.

isn't the flow of messages just
<- incoming request for storage proof with a tx
if < concurrency: pick available db tx or spawn that task without one and create one on the task
handle the storageproof request on the task and return the db tx

then this only has to loop over a single receiver

or are we then running into issues with generics if we need to carry the db tx in the prooftaskmessage enum

Copy link
Member Author

Choose a reason for hiding this comment

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

The design currently uses 2 channels, one for incoming proof requests, and one for returning txs from finished storage proof tasks. If we want only one channel in this loop, we would need another way (other than message passing) to keep track of txs in-use / not in-use

@Rjected Rjected force-pushed the dan/fixed-db-tx-multiproof branch 3 times, most recently from bac17cc to d7397bb Compare March 10, 2025 22:49
@Rjected
Copy link
Member Author

Rjected commented Mar 10, 2025

Note, I still have this:

let max_concurrency = 32;

any suggestions on the value / how to derive this?

@Rjected Rjected force-pushed the dan/fixed-db-tx-multiproof branch from 6a3cd28 to e039441 Compare March 11, 2025 21:22
Copy link
Collaborator

@shekhirin shekhirin left a 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, only nits

Comment on lines +67 to +70
/// Creates a new [`ProofTaskManager`] with the given max concurrency, creating that number of
/// cursor factories.
///
/// Returns an error if the consistent view provider fails to create a read-only transaction.
Copy link
Collaborator

Choose a reason for hiding this comment

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

outdated comment?

Comment on lines +96 to +98
/// Spawns the proof task on the executor, with the input multiproof targets.
///
/// If a task cannot be spawned immediately, this will be queued for completion later.
Copy link
Collaborator

Choose a reason for hiding this comment

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

this always queues and the spawn happens in the main loop

Comment on lines +131 to +137
let Some(proof_task_tx) = self.get_or_create_tx()? else { return Ok(()) };

let Some((pending_proof, sender)) = self.pending_proofs.pop_front() else {
// if there are no targets to do anything with put the tx back
self.proof_task_txs.push(proof_task_tx);
return Ok(())
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we swap these, so that txs aren't created if they won't be used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trie Related to Merkle Patricia Trie implementation
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

3 participants