rpc: performance fix for getProgramAccounts (backport #19941) (#19949)

* rpc: performance fix for getProgramAccounts (#19941)

* 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 <ckamm@delightful-solutions.de>
(cherry picked from commit f1bbf1d8b0)

# Conflicts:
#	core/src/rpc.rs

* fix conflicts

* Fix conflicts

Co-authored-by: Christian Kamm <mail@ckamm.de>
Co-authored-by: Justin Starry <justin@solana.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
This commit is contained in:
mergify[bot]
2021-09-16 23:09:11 +00:00
committed by GitHub
parent ccef24c44e
commit da7185e2ed

View File

@ -328,18 +328,15 @@ impl JsonRpcRequestProcessor {
pubkeys: Vec<Pubkey>, pubkeys: Vec<Pubkey>,
config: Option<RpcAccountInfoConfig>, config: Option<RpcAccountInfoConfig>,
) -> Result<RpcResponse<Vec<Option<UiAccount>>>> { ) -> Result<RpcResponse<Vec<Option<UiAccount>>>> {
let mut accounts: Vec<Option<UiAccount>> = vec![];
let config = config.unwrap_or_default(); let config = config.unwrap_or_default();
let bank = self.bank(config.commitment); let bank = self.bank(config.commitment);
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Base64); let encoding = config.encoding.unwrap_or(UiAccountEncoding::Base64);
check_slice_and_encoding(&encoding, config.data_slice.is_some())?; check_slice_and_encoding(&encoding, config.data_slice.is_some())?;
for pubkey in pubkeys { let accounts = pubkeys
let response_account = .into_iter()
get_encoded_account(&bank, &pubkey, encoding, config.data_slice)?; .map(|pubkey| get_encoded_account(&bank, &pubkey, encoding, config.data_slice))
accounts.push(response_account) .collect::<Result<Vec<_>>>()?;
}
Ok(new_response(&bank, accounts)) Ok(new_response(&bank, accounts))
} }
@ -379,17 +376,19 @@ impl JsonRpcRequestProcessor {
} else { } else {
keyed_accounts keyed_accounts
.into_iter() .into_iter()
.map(|(pubkey, account)| RpcKeyedAccount { .map(|(pubkey, account)| {
pubkey: pubkey.to_string(), Ok(RpcKeyedAccount {
account: UiAccount::encode( pubkey: pubkey.to_string(),
&pubkey, account: UiAccount::encode(
&account, &pubkey,
encoding, &account,
None, encoding,
data_slice_config, None,
), data_slice_config,
),
})
}) })
.collect() .collect::<Result<Vec<_>>>()?
}; };
Ok(result).map(|result| match with_context { Ok(result).map(|result| match with_context {
true => OptionalContext::Context(new_response(&bank, result)), true => OptionalContext::Context(new_response(&bank, result)),
@ -2804,10 +2803,10 @@ pub mod rpc_full {
max_multiple_accounts max_multiple_accounts
))); )));
} }
let mut pubkeys: Vec<Pubkey> = vec![]; let pubkeys = pubkey_strs
for pubkey_str in pubkey_strs { .into_iter()
pubkeys.push(verify_pubkey(&pubkey_str)?); .map(|pubkey_str| verify_pubkey(&pubkey_str))
} .collect::<Result<Vec<_>>>()?;
meta.get_multiple_accounts(pubkeys, config) meta.get_multiple_accounts(pubkeys, config)
} }