feat: faster lookups and batch note requests#1387
Conversation
| loop { | ||
| if !self | ||
| .sync_state_step( | ||
| &mut state_sync_update, | ||
| &mut current_partial_mmr, | ||
| &accounts, | ||
| note_tags.clone(), | ||
| ) | ||
| .await? | ||
| { | ||
| let step = self | ||
| .sync_state_step(state_sync_update.block_num, &account_ids, note_tags.clone()) | ||
| .await?; | ||
| let Some(step) = step else { | ||
| break; | ||
| }; | ||
| state_sync_update.block_num = step.block_header.block_num(); | ||
| state_sync_steps.push(step); | ||
| } |
There was a problem hiding this comment.
Most of the code in this file is the same but rearranged:
- Before, we'd do a call to
sync_statewhich would return a set of new committed notes some of which could be public (and not currently tracked by the client), so a call toget_notes_by_idwould be done subsequently - Now, all calls to
sync_stateare done down to the chain tip and then all public notes requests are batched into a singleget_notes_by_idcall
| "{QUERY} WHERE tx.status_variant IN ({}, {})", | ||
| TransactionStatusVariant::Pending as u8, | ||
| TransactionStatusVariant::Discarded as u8 |
There was a problem hiding this comment.
This makes the query hit the index
| CREATE TABLE IF NOT EXISTS tracked_accounts ( | ||
| id TEXT NOT NULL PRIMARY KEY | ||
| ); |
There was a problem hiding this comment.
This is added for faster lookups. Selecting distinct account IDs still does a full table scan which means scanning through 35K rows, even with the index. We could use the settings table for this but it's not present in the 0.11 versions
There was a problem hiding this comment.
Selecting distinct account IDs still does a full table scan
You mean selecting unique account ids from the accounts table, right?
I don't have the full context on the problem, but an alternative idea would be to create an index on account id (and potentially nonce?):
CREATE INDEX idx_accounts_id_nonce ON accounts(id, nonce DESC);There was a problem hiding this comment.
This is what I meant with my comment above. Even with that same index (which already exists BTW), the query scans the same amount of rows (although it does not touch the table because the index covers it). There is also concrete difference in the flamegraph when benchmarking this. I can pull up an example if you are interested later since it would require setting it up.
An equivalent alternative could be to add something like is_latest_state and do a partial index (WHERE is_latest_state=1), but not sure we prefer it.
| /// Applies the state sync update to the store. | ||
| /// | ||
| /// See [`crate::Store::apply_state_sync()`] for what the update implies. | ||
| pub async fn apply_state_sync(&mut self, update: StateSyncUpdate) -> Result<(), ClientError> { |
There was a problem hiding this comment.
Made this public function so that users can easily apply syncs that they do manually through the StateSync component. This should help the faucet decide what it requests. For instance, we don't need to send the account ID prefix because we don't expect to receive notes from other accounts, we only care about the ones we create.
There was a problem hiding this comment.
If we give the users the option to apply this, we might also want to give them the tools to build what the state sync component needs to run correctly. Users can work around this by having an instance of their store though.
|
|
||
| let return_notes = self.rpc_api.get_public_note_records(query_notes, None).await?; | ||
| let mut public_notes = BTreeMap::new(); | ||
| for chunk in query_notes.chunks(1_000) { |
There was a problem hiding this comment.
We need a better structured way of getting limits as defined by the node (#1139)
b40f3b6 to
fe7615a
Compare
| CREATE TABLE IF NOT EXISTS tracked_accounts ( | ||
| id TEXT NOT NULL PRIMARY KEY | ||
| ); |
There was a problem hiding this comment.
Selecting distinct account IDs still does a full table scan
You mean selecting unique account ids from the accounts table, right?
I don't have the full context on the problem, but an alternative idea would be to create an index on account id (and potentially nonce?):
CREATE INDEX idx_accounts_id_nonce ON accounts(id, nonce DESC);| "{QUERY} WHERE tx.status_variant IN ({}, {})", | ||
| TransactionStatusVariant::Pending as u8, | ||
| TransactionStatusVariant::Discarded as u8 |
mmagician
left a comment
There was a problem hiding this comment.
LGTM barring the lint (it looks like the usage of BlockUpdates::insert makes BlockUpdates::extend unused)
Co-authored-by: Marti <marti@miden.team>
|
I'm looking at improving one more thing that I should be pushing in the next few minutes. |
* feat: faster lookups * chore: lints * reviews: logical or, add comment * refactor: simpler inesrt function and comment * chore: lints * chore: add trace logs * chore: format * Update CHANGELOG.md Co-authored-by: Marti <marti@miden.team> * refactor: improve block header lookup and migration logic * chore: lints --------- Co-authored-by: Marti <marti@miden.team>
No description provided.