Cli: better estimate of epoch time elapsed/remaining (#15893)
* Add rpc_client api for getRecentPerformanceSamples * Prep fn for variable avg slot time * Use recent-perf-samples to more-accurately estimate epoch completed times * Spell out average
This commit is contained in:
		@@ -19,7 +19,7 @@ use {
 | 
			
		||||
        RpcVoteAccountInfo,
 | 
			
		||||
    },
 | 
			
		||||
    solana_sdk::{
 | 
			
		||||
        clock::{self, Epoch, Slot, UnixTimestamp},
 | 
			
		||||
        clock::{Epoch, Slot, UnixTimestamp},
 | 
			
		||||
        epoch_info::EpochInfo,
 | 
			
		||||
        hash::Hash,
 | 
			
		||||
        native_token::lamports_to_sol,
 | 
			
		||||
@@ -231,12 +231,8 @@ pub struct CliSlotStatus {
 | 
			
		||||
pub struct CliEpochInfo {
 | 
			
		||||
    #[serde(flatten)]
 | 
			
		||||
    pub epoch_info: EpochInfo,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<EpochInfo> for CliEpochInfo {
 | 
			
		||||
    fn from(epoch_info: EpochInfo) -> Self {
 | 
			
		||||
        Self { epoch_info }
 | 
			
		||||
    }
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    pub average_slot_time_ms: u64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl QuietDisplay for CliEpochInfo {}
 | 
			
		||||
@@ -286,16 +282,16 @@ impl fmt::Display for CliEpochInfo {
 | 
			
		||||
            "Epoch Completed Time:",
 | 
			
		||||
            &format!(
 | 
			
		||||
                "{}/{} ({} remaining)",
 | 
			
		||||
                slot_to_human_time(self.epoch_info.slot_index),
 | 
			
		||||
                slot_to_human_time(self.epoch_info.slots_in_epoch),
 | 
			
		||||
                slot_to_human_time(remaining_slots_in_epoch)
 | 
			
		||||
                slot_to_human_time(self.epoch_info.slot_index, self.average_slot_time_ms),
 | 
			
		||||
                slot_to_human_time(self.epoch_info.slots_in_epoch, self.average_slot_time_ms),
 | 
			
		||||
                slot_to_human_time(remaining_slots_in_epoch, self.average_slot_time_ms)
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn slot_to_human_time(slot: Slot) -> String {
 | 
			
		||||
    humantime::format_duration(Duration::from_millis(slot * clock::DEFAULT_MS_PER_SLOT)).to_string()
 | 
			
		||||
fn slot_to_human_time(slot: Slot, slot_time_ms: u64) -> String {
 | 
			
		||||
    humantime::format_duration(Duration::from_secs((slot * slot_time_ms) / 1000)).to_string()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Default)]
 | 
			
		||||
 
 | 
			
		||||
@@ -993,7 +993,20 @@ pub fn process_get_epoch(rpc_client: &RpcClient, _config: &CliConfig) -> Process
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn process_get_epoch_info(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult {
 | 
			
		||||
    let epoch_info: CliEpochInfo = rpc_client.get_epoch_info()?.into();
 | 
			
		||||
    let epoch_info = rpc_client.get_epoch_info()?;
 | 
			
		||||
    let average_slot_time_ms = rpc_client
 | 
			
		||||
        .get_recent_performance_samples(Some(60))
 | 
			
		||||
        .map(|samples| {
 | 
			
		||||
            let (slots, secs) = samples.iter().fold((0, 0), |(slots, secs), sample| {
 | 
			
		||||
                (slots + sample.num_slots, secs + sample.sample_period_secs)
 | 
			
		||||
            });
 | 
			
		||||
            (secs as u64 * 1000) / slots
 | 
			
		||||
        })
 | 
			
		||||
        .unwrap_or(clock::DEFAULT_MS_PER_SLOT);
 | 
			
		||||
    let epoch_info = CliEpochInfo {
 | 
			
		||||
        epoch_info,
 | 
			
		||||
        average_slot_time_ms,
 | 
			
		||||
    };
 | 
			
		||||
    Ok(config.output_format.formatted_string(&epoch_info))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1008,8 +1021,8 @@ pub fn process_get_slot(rpc_client: &RpcClient, _config: &CliConfig) -> ProcessR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn process_get_block_height(rpc_client: &RpcClient, _config: &CliConfig) -> ProcessResult {
 | 
			
		||||
    let epoch_info: CliEpochInfo = rpc_client.get_epoch_info()?.into();
 | 
			
		||||
    Ok(epoch_info.epoch_info.block_height.to_string())
 | 
			
		||||
    let epoch_info = rpc_client.get_epoch_info()?;
 | 
			
		||||
    Ok(epoch_info.block_height.to_string())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn parse_show_block_production(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
 | 
			
		||||
 
 | 
			
		||||
@@ -644,6 +644,13 @@ impl RpcClient {
 | 
			
		||||
        self.send(RpcRequest::GetEpochSchedule, Value::Null)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_recent_performance_samples(
 | 
			
		||||
        &self,
 | 
			
		||||
        limit: Option<usize>,
 | 
			
		||||
    ) -> ClientResult<Vec<RpcPerfSample>> {
 | 
			
		||||
        self.send(RpcRequest::GetRecentPerformanceSamples, json!([limit]))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_identity(&self) -> ClientResult<Pubkey> {
 | 
			
		||||
        let rpc_identity: RpcIdentity = self.send(RpcRequest::GetIdentity, Value::Null)?;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ pub enum RpcRequest {
 | 
			
		||||
    GetMultipleAccounts,
 | 
			
		||||
    GetProgramAccounts,
 | 
			
		||||
    GetRecentBlockhash,
 | 
			
		||||
    GetRecentPerformanceSamples,
 | 
			
		||||
    GetSnapshotSlot,
 | 
			
		||||
    GetSignatureStatuses,
 | 
			
		||||
    GetSlot,
 | 
			
		||||
@@ -90,6 +91,7 @@ impl fmt::Display for RpcRequest {
 | 
			
		||||
            RpcRequest::GetMultipleAccounts => "getMultipleAccounts",
 | 
			
		||||
            RpcRequest::GetProgramAccounts => "getProgramAccounts",
 | 
			
		||||
            RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
 | 
			
		||||
            RpcRequest::GetRecentPerformanceSamples => "getRecentPerformanceSamples",
 | 
			
		||||
            RpcRequest::GetSnapshotSlot => "getSnapshotSlot",
 | 
			
		||||
            RpcRequest::GetSignatureStatuses => "getSignatureStatuses",
 | 
			
		||||
            RpcRequest::GetSlot => "getSlot",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user