solana_rpc_bench/
client.rs1use std::{ops::Div, time::Duration};
2
3use solana_client::{client_error::Result as ClientResult, nonblocking::rpc_client::RpcClient};
4use tokio::time::{Instant, sleep};
5use tracing::error;
6
7use crate::{Result, accounts::ACCOUNTS, setting::SettingClient};
8
9pub struct Client {
10 label: String,
11 pub rpc: RpcClient,
12}
13
14impl From<SettingClient> for Client {
15 fn from(value: SettingClient) -> Self {
16 Self {
17 label: value.label,
18 rpc: RpcClient::new(value.url),
19 }
20 }
21}
22
23pub struct TestResult {
24 best: Duration,
25 worst: Duration,
26 total: Duration,
27 count: u32,
28}
29
30impl TestResult {
31 fn to_table(&self, label: &str, call: &str) -> Vec<String> {
32 vec![
33 label.to_string(),
34 call.to_string(),
35 format!("{} ms", self.total.div(self.count).as_millis()),
36 format!("{} ms", self.best.as_millis()),
37 format!("{} ms", self.worst.as_millis()),
38 ]
39 }
40}
41
42impl Client {
43 pub async fn test(&self, count: u32) -> Vec<Vec<String>> {
44 let mut results = vec![];
45 results.push(
46 self.run_test(|| self.rpc.get_slot(), count)
47 .await
48 .to_table(&self.label, "get_slot"),
49 );
50
51 results.push(
52 self.run_test(|| self.rpc.get_multiple_accounts(&ACCOUNTS), count)
53 .await
54 .to_table(&self.label, "get_multiple_accounts"),
55 );
56
57 results
58 }
59
60 async fn run_test<F, Fut, T>(&self, mut f: F, count: u32) -> TestResult
61 where
62 F: FnMut() -> Fut,
63 Fut: Future<Output = ClientResult<T>>,
64 {
65 let mut best = Duration::MAX;
66 let mut worst = Duration::ZERO;
67 let mut total = Duration::ZERO;
68
69 for _ in 0..count {
70 match self.internal_test(f()).await {
71 Ok(duration) => {
72 if duration < best {
73 best = duration
74 }
75 if duration > worst {
76 worst = duration
77 }
78 total += duration;
79 }
80 Err(e) => {
81 error!("{e}");
82 }
83 }
84
85 sleep(Duration::from_millis(500)).await;
87 }
88
89 TestResult {
90 best,
91 worst,
92 total,
93 count,
94 }
95 }
96
97 async fn internal_test<T>(&self, f: impl Future<Output = ClientResult<T>>) -> Result<Duration> {
100 let start = Instant::now();
101 let _ = f.await?;
102 Ok(start.elapsed())
103 }
104}