Add hidden cli option to allow validator reports replayed transaction cost metrics (#22369)
* add hidden cli option to allow validator reports replayed transaction cost detail metrics * Update validator/src/main.rs Co-authored-by: Michael Vines <mvines@gmail.com> * - rebase master, using unbounded instead of channel; dowgrade to datapoint_trace * removed cli arg, prefer log at trace Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
parent
2aa113fd8c
commit
a724fa2347
|
@ -51,6 +51,7 @@ use {
|
||||||
bank::{Bank, NewBankOptions},
|
bank::{Bank, NewBankOptions},
|
||||||
bank_forks::BankForks,
|
bank_forks::BankForks,
|
||||||
commitment::BlockCommitmentCache,
|
commitment::BlockCommitmentCache,
|
||||||
|
transaction_cost_metrics_sender::TransactionCostMetricsSender,
|
||||||
vote_sender_types::ReplayVoteSender,
|
vote_sender_types::ReplayVoteSender,
|
||||||
},
|
},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
@ -339,6 +340,7 @@ impl ReplayStage {
|
||||||
voting_sender: Sender<VoteOp>,
|
voting_sender: Sender<VoteOp>,
|
||||||
drop_bank_sender: Sender<Vec<Arc<Bank>>>,
|
drop_bank_sender: Sender<Vec<Arc<Bank>>>,
|
||||||
block_metadata_notifier: Option<BlockMetadataNotifierLock>,
|
block_metadata_notifier: Option<BlockMetadataNotifierLock>,
|
||||||
|
transaction_cost_metrics_sender: Option<TransactionCostMetricsSender>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let ReplayStageConfig {
|
let ReplayStageConfig {
|
||||||
vote_account,
|
vote_account,
|
||||||
|
@ -445,6 +447,7 @@ impl ReplayStage {
|
||||||
&mut duplicate_slots_to_repair,
|
&mut duplicate_slots_to_repair,
|
||||||
&ancestor_hashes_replay_update_sender,
|
&ancestor_hashes_replay_update_sender,
|
||||||
block_metadata_notifier.clone(),
|
block_metadata_notifier.clone(),
|
||||||
|
transaction_cost_metrics_sender.as_ref(),
|
||||||
);
|
);
|
||||||
replay_active_banks_time.stop();
|
replay_active_banks_time.stop();
|
||||||
|
|
||||||
|
@ -1570,6 +1573,7 @@ impl ReplayStage {
|
||||||
bank_progress: &mut ForkProgress,
|
bank_progress: &mut ForkProgress,
|
||||||
transaction_status_sender: Option<&TransactionStatusSender>,
|
transaction_status_sender: Option<&TransactionStatusSender>,
|
||||||
replay_vote_sender: &ReplayVoteSender,
|
replay_vote_sender: &ReplayVoteSender,
|
||||||
|
transaction_cost_metrics_sender: Option<&TransactionCostMetricsSender>,
|
||||||
verify_recyclers: &VerifyRecyclers,
|
verify_recyclers: &VerifyRecyclers,
|
||||||
) -> result::Result<usize, BlockstoreProcessorError> {
|
) -> result::Result<usize, BlockstoreProcessorError> {
|
||||||
let tx_count_before = bank_progress.replay_progress.num_txs;
|
let tx_count_before = bank_progress.replay_progress.num_txs;
|
||||||
|
@ -1581,6 +1585,7 @@ impl ReplayStage {
|
||||||
false,
|
false,
|
||||||
transaction_status_sender,
|
transaction_status_sender,
|
||||||
Some(replay_vote_sender),
|
Some(replay_vote_sender),
|
||||||
|
transaction_cost_metrics_sender,
|
||||||
None,
|
None,
|
||||||
verify_recyclers,
|
verify_recyclers,
|
||||||
false,
|
false,
|
||||||
|
@ -2070,6 +2075,7 @@ impl ReplayStage {
|
||||||
duplicate_slots_to_repair: &mut DuplicateSlotsToRepair,
|
duplicate_slots_to_repair: &mut DuplicateSlotsToRepair,
|
||||||
ancestor_hashes_replay_update_sender: &AncestorHashesReplayUpdateSender,
|
ancestor_hashes_replay_update_sender: &AncestorHashesReplayUpdateSender,
|
||||||
block_metadata_notifier: Option<BlockMetadataNotifierLock>,
|
block_metadata_notifier: Option<BlockMetadataNotifierLock>,
|
||||||
|
transaction_cost_metrics_sender: Option<&TransactionCostMetricsSender>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut did_complete_bank = false;
|
let mut did_complete_bank = false;
|
||||||
let mut tx_count = 0;
|
let mut tx_count = 0;
|
||||||
|
@ -2119,6 +2125,7 @@ impl ReplayStage {
|
||||||
bank_progress,
|
bank_progress,
|
||||||
transaction_status_sender,
|
transaction_status_sender,
|
||||||
replay_vote_sender,
|
replay_vote_sender,
|
||||||
|
transaction_cost_metrics_sender,
|
||||||
verify_recyclers,
|
verify_recyclers,
|
||||||
);
|
);
|
||||||
match replay_result {
|
match replay_result {
|
||||||
|
@ -3652,6 +3659,7 @@ pub mod tests {
|
||||||
bank1_progress,
|
bank1_progress,
|
||||||
None,
|
None,
|
||||||
&replay_vote_sender,
|
&replay_vote_sender,
|
||||||
|
None,
|
||||||
&VerifyRecyclers::default(),
|
&VerifyRecyclers::default(),
|
||||||
);
|
);
|
||||||
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
|
let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
|
||||||
|
|
|
@ -49,6 +49,9 @@ use {
|
||||||
snapshot_package::{
|
snapshot_package::{
|
||||||
AccountsPackageReceiver, AccountsPackageSender, PendingSnapshotPackage,
|
AccountsPackageReceiver, AccountsPackageSender, PendingSnapshotPackage,
|
||||||
},
|
},
|
||||||
|
transaction_cost_metrics_sender::{
|
||||||
|
TransactionCostMetricsSender, TransactionCostMetricsService,
|
||||||
|
},
|
||||||
vote_sender_types::ReplayVoteSender,
|
vote_sender_types::ReplayVoteSender,
|
||||||
},
|
},
|
||||||
solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Keypair},
|
solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Keypair},
|
||||||
|
@ -72,6 +75,7 @@ pub struct Tvu {
|
||||||
cost_update_service: CostUpdateService,
|
cost_update_service: CostUpdateService,
|
||||||
voting_service: VotingService,
|
voting_service: VotingService,
|
||||||
drop_bank_service: DropBankService,
|
drop_bank_service: DropBankService,
|
||||||
|
transaction_cost_metrics_service: TransactionCostMetricsService,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TvuSockets {
|
pub struct TvuSockets {
|
||||||
|
@ -309,6 +313,15 @@ impl Tvu {
|
||||||
);
|
);
|
||||||
|
|
||||||
let (drop_bank_sender, drop_bank_receiver) = unbounded();
|
let (drop_bank_sender, drop_bank_receiver) = unbounded();
|
||||||
|
|
||||||
|
let (tx_cost_metrics_sender, tx_cost_metrics_receiver) = unbounded();
|
||||||
|
let transaction_cost_metrics_sender = Some(TransactionCostMetricsSender::new(
|
||||||
|
cost_model.clone(),
|
||||||
|
tx_cost_metrics_sender,
|
||||||
|
));
|
||||||
|
let transaction_cost_metrics_service =
|
||||||
|
TransactionCostMetricsService::new(tx_cost_metrics_receiver);
|
||||||
|
|
||||||
let drop_bank_service = DropBankService::new(drop_bank_receiver);
|
let drop_bank_service = DropBankService::new(drop_bank_receiver);
|
||||||
|
|
||||||
let replay_stage = ReplayStage::new(
|
let replay_stage = ReplayStage::new(
|
||||||
|
@ -332,6 +345,7 @@ impl Tvu {
|
||||||
voting_sender,
|
voting_sender,
|
||||||
drop_bank_sender,
|
drop_bank_sender,
|
||||||
block_metadata_notifier,
|
block_metadata_notifier,
|
||||||
|
transaction_cost_metrics_sender,
|
||||||
);
|
);
|
||||||
|
|
||||||
let ledger_cleanup_service = tvu_config.max_ledger_shreds.map(|max_ledger_shreds| {
|
let ledger_cleanup_service = tvu_config.max_ledger_shreds.map(|max_ledger_shreds| {
|
||||||
|
@ -366,6 +380,7 @@ impl Tvu {
|
||||||
cost_update_service,
|
cost_update_service,
|
||||||
voting_service,
|
voting_service,
|
||||||
drop_bank_service,
|
drop_bank_service,
|
||||||
|
transaction_cost_metrics_service,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,6 +397,7 @@ impl Tvu {
|
||||||
self.cost_update_service.join()?;
|
self.cost_update_service.join()?;
|
||||||
self.voting_service.join()?;
|
self.voting_service.join()?;
|
||||||
self.drop_bank_service.join()?;
|
self.drop_bank_service.join()?;
|
||||||
|
self.transaction_cost_metrics_service.join()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ use {
|
||||||
snapshot_package::{AccountsPackageSender, SnapshotType},
|
snapshot_package::{AccountsPackageSender, SnapshotType},
|
||||||
snapshot_utils::{self, BankFromArchiveTimings},
|
snapshot_utils::{self, BankFromArchiveTimings},
|
||||||
transaction_batch::TransactionBatch,
|
transaction_batch::TransactionBatch,
|
||||||
|
transaction_cost_metrics_sender::TransactionCostMetricsSender,
|
||||||
vote_account::VoteAccount,
|
vote_account::VoteAccount,
|
||||||
vote_sender_types::ReplayVoteSender,
|
vote_sender_types::ReplayVoteSender,
|
||||||
},
|
},
|
||||||
|
@ -317,6 +318,7 @@ pub fn process_entries_for_tests(
|
||||||
None,
|
None,
|
||||||
transaction_status_sender,
|
transaction_status_sender,
|
||||||
replay_vote_sender,
|
replay_vote_sender,
|
||||||
|
None,
|
||||||
&mut timings,
|
&mut timings,
|
||||||
Arc::new(RwLock::new(BlockCostCapacityMeter::default())),
|
Arc::new(RwLock::new(BlockCostCapacityMeter::default())),
|
||||||
);
|
);
|
||||||
|
@ -333,6 +335,7 @@ fn process_entries_with_callback(
|
||||||
entry_callback: Option<&ProcessCallback>,
|
entry_callback: Option<&ProcessCallback>,
|
||||||
transaction_status_sender: Option<&TransactionStatusSender>,
|
transaction_status_sender: Option<&TransactionStatusSender>,
|
||||||
replay_vote_sender: Option<&ReplayVoteSender>,
|
replay_vote_sender: Option<&ReplayVoteSender>,
|
||||||
|
transaction_cost_metrics_sender: Option<&TransactionCostMetricsSender>,
|
||||||
timings: &mut ExecuteTimings,
|
timings: &mut ExecuteTimings,
|
||||||
cost_capacity_meter: Arc<RwLock<BlockCostCapacityMeter>>,
|
cost_capacity_meter: Arc<RwLock<BlockCostCapacityMeter>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -366,6 +369,11 @@ fn process_entries_with_callback(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EntryType::Transactions(transactions) => {
|
EntryType::Transactions(transactions) => {
|
||||||
|
if let Some(transaction_cost_metrics_sender) = transaction_cost_metrics_sender {
|
||||||
|
transaction_cost_metrics_sender
|
||||||
|
.send_cost_details(bank.clone(), transactions.iter());
|
||||||
|
}
|
||||||
|
|
||||||
if randomize {
|
if randomize {
|
||||||
transactions.shuffle(&mut rng);
|
transactions.shuffle(&mut rng);
|
||||||
}
|
}
|
||||||
|
@ -791,6 +799,7 @@ fn confirm_full_slot(
|
||||||
skip_verification,
|
skip_verification,
|
||||||
transaction_status_sender,
|
transaction_status_sender,
|
||||||
replay_vote_sender,
|
replay_vote_sender,
|
||||||
|
None,
|
||||||
opts.entry_callback.as_ref(),
|
opts.entry_callback.as_ref(),
|
||||||
recyclers,
|
recyclers,
|
||||||
opts.allow_dead_slots,
|
opts.allow_dead_slots,
|
||||||
|
@ -858,6 +867,7 @@ pub fn confirm_slot(
|
||||||
skip_verification: bool,
|
skip_verification: bool,
|
||||||
transaction_status_sender: Option<&TransactionStatusSender>,
|
transaction_status_sender: Option<&TransactionStatusSender>,
|
||||||
replay_vote_sender: Option<&ReplayVoteSender>,
|
replay_vote_sender: Option<&ReplayVoteSender>,
|
||||||
|
transaction_cost_metrics_sender: Option<&TransactionCostMetricsSender>,
|
||||||
entry_callback: Option<&ProcessCallback>,
|
entry_callback: Option<&ProcessCallback>,
|
||||||
recyclers: &VerifyRecyclers,
|
recyclers: &VerifyRecyclers,
|
||||||
allow_dead_slots: bool,
|
allow_dead_slots: bool,
|
||||||
|
@ -954,6 +964,7 @@ pub fn confirm_slot(
|
||||||
entry_callback,
|
entry_callback,
|
||||||
transaction_status_sender,
|
transaction_status_sender,
|
||||||
replay_vote_sender,
|
replay_vote_sender,
|
||||||
|
transaction_cost_metrics_sender,
|
||||||
&mut execute_timings,
|
&mut execute_timings,
|
||||||
cost_capacity_meter,
|
cost_capacity_meter,
|
||||||
)
|
)
|
||||||
|
|
|
@ -57,6 +57,7 @@ pub mod stakes;
|
||||||
pub mod status_cache;
|
pub mod status_cache;
|
||||||
mod system_instruction_processor;
|
mod system_instruction_processor;
|
||||||
pub mod transaction_batch;
|
pub mod transaction_batch;
|
||||||
|
pub mod transaction_cost_metrics_sender;
|
||||||
pub mod vote_account;
|
pub mod vote_account;
|
||||||
pub mod vote_sender_types;
|
pub mod vote_sender_types;
|
||||||
pub mod waitable_condvar;
|
pub mod waitable_condvar;
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
use {
|
||||||
|
crate::{bank::Bank, cost_model::CostModel},
|
||||||
|
crossbeam_channel::{Receiver, Sender},
|
||||||
|
log::*,
|
||||||
|
solana_sdk::{clock::Slot, signature::Signature, transaction::SanitizedTransaction},
|
||||||
|
std::{
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
thread::{self, Builder, JoinHandle},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub enum TransactionCostMetrics {
|
||||||
|
TransactionCostDetail {
|
||||||
|
slot: Slot,
|
||||||
|
tx_signature: Signature,
|
||||||
|
signature_cost: u64,
|
||||||
|
write_lock_cost: u64,
|
||||||
|
data_bytes_cost: u64,
|
||||||
|
execution_cost: u64,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TransactionCostMetricsSender {
|
||||||
|
cost_model: Arc<RwLock<CostModel>>,
|
||||||
|
metrics_sender: Sender<TransactionCostMetrics>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransactionCostMetricsSender {
|
||||||
|
pub fn new(
|
||||||
|
cost_model: Arc<RwLock<CostModel>>,
|
||||||
|
metrics_sender: Sender<TransactionCostMetrics>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
cost_model,
|
||||||
|
metrics_sender,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_cost_details<'a>(
|
||||||
|
&self,
|
||||||
|
bank: Arc<Bank>,
|
||||||
|
txs: impl Iterator<Item = &'a SanitizedTransaction>,
|
||||||
|
) {
|
||||||
|
let cost_model = self.cost_model.read().unwrap();
|
||||||
|
txs.for_each(|tx| {
|
||||||
|
let cost = cost_model.calculate_cost(tx);
|
||||||
|
self.metrics_sender
|
||||||
|
.send(TransactionCostMetrics::TransactionCostDetail {
|
||||||
|
slot: bank.slot(),
|
||||||
|
tx_signature: *tx.signature(),
|
||||||
|
signature_cost: cost.signature_cost,
|
||||||
|
write_lock_cost: cost.write_lock_cost,
|
||||||
|
data_bytes_cost: cost.data_bytes_cost,
|
||||||
|
execution_cost: cost.execution_cost,
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
|
warn!(
|
||||||
|
"transaction cost metrics service report cost detail failed: {:?}",
|
||||||
|
err
|
||||||
|
)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TransactionCostMetricsService {
|
||||||
|
thread_hdl: JoinHandle<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransactionCostMetricsService {
|
||||||
|
pub fn new(transaction_cost_metrics_receiver: Receiver<TransactionCostMetrics>) -> Self {
|
||||||
|
let thread_hdl = Builder::new()
|
||||||
|
.name("transaction_cost_metrics_service".to_string())
|
||||||
|
.spawn(move || {
|
||||||
|
Self::service_loop(transaction_cost_metrics_receiver);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Self { thread_hdl }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join(self) -> thread::Result<()> {
|
||||||
|
self.thread_hdl.join()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn service_loop(transaction_cost_metrics_receiver: Receiver<TransactionCostMetrics>) {
|
||||||
|
for tx_cost_metrics in transaction_cost_metrics_receiver.iter() {
|
||||||
|
match tx_cost_metrics {
|
||||||
|
TransactionCostMetrics::TransactionCostDetail {
|
||||||
|
slot,
|
||||||
|
tx_signature,
|
||||||
|
signature_cost,
|
||||||
|
write_lock_cost,
|
||||||
|
data_bytes_cost,
|
||||||
|
execution_cost,
|
||||||
|
} => {
|
||||||
|
// report transaction cost details per slot|signature
|
||||||
|
datapoint_trace!(
|
||||||
|
"transaction-cost-details",
|
||||||
|
("slot", slot as i64, i64),
|
||||||
|
("tx_signature", tx_signature.to_string(), String),
|
||||||
|
("signature_cost", signature_cost as i64, i64),
|
||||||
|
("write_lock_cost", write_lock_cost as i64, i64),
|
||||||
|
("data_bytes_cost", data_bytes_cost as i64, i64),
|
||||||
|
("execution_cost", execution_cost as i64, i64),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue