Skip to content

Commit

Permalink
rpc: performance fix for getProgramAccounts (#19941)
Browse files Browse the repository at this point in the history
* rpc: performance fix for getProgramAccounts

The accounts were gradually pushed into a vector, which produced
significant slowdowns for very large responses.

* rpc: rewrite loops using iterators

Co-authored-by: Christian Kamm <[email protected]>
  • Loading branch information
ckamm and ckamm authored Sep 16, 2021
1 parent 43d4aa7 commit f1bbf1d
Showing 1 changed file with 21 additions and 22 deletions.
43 changes: 21 additions & 22 deletions rpc/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,18 +350,15 @@ impl JsonRpcRequestProcessor {
pubkeys: Vec<Pubkey>,
config: Option<RpcAccountInfoConfig>,
) -> Result<RpcResponse<Vec<Option<UiAccount>>>> {
let mut accounts: Vec<Option<UiAccount>> = vec![];

let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Base64);
check_slice_and_encoding(&encoding, config.data_slice.is_some())?;

for pubkey in pubkeys {
let response_account =
get_encoded_account(&bank, &pubkey, encoding, config.data_slice)?;
accounts.push(response_account)
}
let accounts = pubkeys
.into_iter()
.map(|pubkey| get_encoded_account(&bank, &pubkey, encoding, config.data_slice))
.collect::<Result<Vec<_>>>()?;
Ok(new_response(&bank, accounts))
}

Expand Down Expand Up @@ -395,19 +392,21 @@ impl JsonRpcRequestProcessor {
self.get_filtered_program_accounts(&bank, program_id, filters)?
}
};
let result =
if program_id == &spl_token_id_v2_0() && encoding == UiAccountEncoding::JsonParsed {
get_parsed_token_accounts(bank.clone(), keyed_accounts.into_iter()).collect()
} else {
let mut encoded_accounts = vec![];
for (pubkey, account) in keyed_accounts {
encoded_accounts.push(RpcKeyedAccount {
let result = if program_id == &spl_token_id_v2_0()
&& encoding == UiAccountEncoding::JsonParsed
{
get_parsed_token_accounts(bank.clone(), keyed_accounts.into_iter()).collect()
} else {
keyed_accounts
.into_iter()
.map(|(pubkey, account)| {
Ok(RpcKeyedAccount {
pubkey: pubkey.to_string(),
account: encode_account(&account, &pubkey, encoding, data_slice_config)?,
});
}
encoded_accounts
};
})
})
.collect::<Result<Vec<_>>>()?
};
Ok(result).map(|result| match with_context {
true => OptionalContext::Context(new_response(&bank, result)),
false => OptionalContext::NoContext(result),
Expand Down Expand Up @@ -2826,10 +2825,10 @@ pub mod rpc_accounts {
max_multiple_accounts
)));
}
let mut pubkeys: Vec<Pubkey> = vec![];
for pubkey_str in pubkey_strs {
pubkeys.push(verify_pubkey(&pubkey_str)?);
}
let pubkeys = pubkey_strs
.into_iter()
.map(|pubkey_str| verify_pubkey(&pubkey_str))
.collect::<Result<Vec<_>>>()?;
meta.get_multiple_accounts(pubkeys, config)
}

Expand Down

0 comments on commit f1bbf1d

Please sign in to comment.