gemachain_client/
perf_utils.rs

1use {
2    log::*,
3    gemachain_sdk::{client::Client, commitment_config::CommitmentConfig, timing::duration_as_s},
4    std::{
5        sync::{
6            atomic::{AtomicBool, Ordering},
7            Arc, RwLock,
8        },
9        thread::sleep,
10        time::{Duration, Instant},
11    },
12};
13
14#[derive(Default)]
15pub struct SampleStats {
16    /// Maximum TPS reported by this node
17    pub tps: f32,
18    /// Total time taken for those txs
19    pub elapsed: Duration,
20    /// Total transactions reported by this node
21    pub txs: u64,
22}
23
24pub fn sample_txs<T>(
25    exit_signal: &Arc<AtomicBool>,
26    sample_stats: &Arc<RwLock<Vec<(String, SampleStats)>>>,
27    sample_period: u64,
28    client: &Arc<T>,
29) where
30    T: Client,
31{
32    let mut max_tps = 0.0;
33    let mut total_elapsed;
34    let mut total_txs;
35    let mut now = Instant::now();
36    let start_time = now;
37    let initial_txs = client
38        .get_transaction_count_with_commitment(CommitmentConfig::processed())
39        .expect("transaction count");
40    let mut last_txs = initial_txs;
41
42    loop {
43        total_elapsed = start_time.elapsed();
44        let elapsed = now.elapsed();
45        now = Instant::now();
46        let mut txs;
47        match client.get_transaction_count_with_commitment(CommitmentConfig::processed()) {
48            Err(e) => {
49                // ThinClient with multiple options should pick a better one now.
50                info!("Couldn't get transaction count {:?}", e);
51                sleep(Duration::from_secs(sample_period));
52                continue;
53            }
54            Ok(tx_count) => {
55                txs = tx_count;
56            }
57        }
58
59        if txs < last_txs {
60            info!("Expected txs({}) >= last_txs({})", txs, last_txs);
61            txs = last_txs;
62        }
63        total_txs = txs - initial_txs;
64        let sample_txs = txs - last_txs;
65        last_txs = txs;
66
67        let tps = sample_txs as f32 / duration_as_s(&elapsed);
68        if tps > max_tps {
69            max_tps = tps;
70        }
71
72        info!(
73            "Sampler {:9.2} TPS, Transactions: {:6}, Total transactions: {} over {} s",
74            tps,
75            sample_txs,
76            total_txs,
77            total_elapsed.as_secs(),
78        );
79
80        if exit_signal.load(Ordering::Relaxed) {
81            let stats = SampleStats {
82                tps: max_tps,
83                elapsed: total_elapsed,
84                txs: total_txs,
85            };
86            sample_stats
87                .write()
88                .unwrap()
89                .push((client.tpu_addr(), stats));
90            return;
91        }
92        sleep(Duration::from_secs(sample_period));
93    }
94}