TransactionState: add TransactionCost (#34881)

This commit is contained in:
Andrew Fitzgerald 2024-01-22 16:21:06 -08:00 committed by GitHub
parent 2f744f1639
commit 45a2a701de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 69 additions and 12 deletions

View File

@ -191,9 +191,7 @@ impl PrioGraphScheduler {
saturating_add_assign!(num_scheduled, 1); saturating_add_assign!(num_scheduled, 1);
let sanitized_transaction_ttl = transaction_state.transition_to_pending(); let sanitized_transaction_ttl = transaction_state.transition_to_pending();
let cu_limit = transaction_state let cost = transaction_state.transaction_cost().sum();
.transaction_priority_details()
.compute_unit_limit;
let SanitizedTransactionTTL { let SanitizedTransactionTTL {
transaction, transaction,
@ -203,7 +201,7 @@ impl PrioGraphScheduler {
batches.transactions[thread_id].push(transaction); batches.transactions[thread_id].push(transaction);
batches.ids[thread_id].push(id.id); batches.ids[thread_id].push(id.id);
batches.max_age_slots[thread_id].push(max_age_slot); batches.max_age_slots[thread_id].push(max_age_slot);
saturating_add_assign!(batches.total_cus[thread_id], cu_limit); saturating_add_assign!(batches.total_cus[thread_id], cost);
// If target batch size is reached, send only this batch. // If target batch size is reached, send only this batch.
if batches.ids[thread_id].len() >= TARGET_NUM_TRANSACTIONS_PER_BATCH { if batches.ids[thread_id].len() >= TARGET_NUM_TRANSACTIONS_PER_BATCH {
@ -492,10 +490,12 @@ mod tests {
crate::banking_stage::consumer::TARGET_NUM_TRANSACTIONS_PER_BATCH, crate::banking_stage::consumer::TARGET_NUM_TRANSACTIONS_PER_BATCH,
crossbeam_channel::{unbounded, Receiver}, crossbeam_channel::{unbounded, Receiver},
itertools::Itertools, itertools::Itertools,
solana_cost_model::cost_model::CostModel,
solana_runtime::transaction_priority_details::TransactionPriorityDetails, solana_runtime::transaction_priority_details::TransactionPriorityDetails,
solana_sdk::{ solana_sdk::{
compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, pubkey::Pubkey, compute_budget::ComputeBudgetInstruction, feature_set::FeatureSet, hash::Hash,
signature::Keypair, signer::Signer, system_instruction, transaction::Transaction, message::Message, pubkey::Pubkey, signature::Keypair, signer::Signer,
system_instruction, transaction::Transaction,
}, },
std::borrow::Borrow, std::borrow::Borrow,
}; };
@ -568,6 +568,7 @@ mod tests {
let id = TransactionId::new(index as u64); let id = TransactionId::new(index as u64);
let transaction = let transaction =
prioritized_tranfers(from_keypair.borrow(), to_pubkeys, lamports, priority); prioritized_tranfers(from_keypair.borrow(), to_pubkeys, lamports, priority);
let transaction_cost = CostModel::calculate_cost(&transaction, &FeatureSet::default());
let transaction_ttl = SanitizedTransactionTTL { let transaction_ttl = SanitizedTransactionTTL {
transaction, transaction,
max_age_slot: Slot::MAX, max_age_slot: Slot::MAX,
@ -579,6 +580,7 @@ mod tests {
priority, priority,
compute_unit_limit: 1, compute_unit_limit: 1,
}, },
transaction_cost,
); );
} }

View File

@ -18,6 +18,7 @@ use {
}, },
crossbeam_channel::RecvTimeoutError, crossbeam_channel::RecvTimeoutError,
solana_accounts_db::transaction_error_metrics::TransactionErrorMetrics, solana_accounts_db::transaction_error_metrics::TransactionErrorMetrics,
solana_cost_model::cost_model::CostModel,
solana_measure::measure_us, solana_measure::measure_us,
solana_runtime::{bank::Bank, bank_forks::BankForks}, solana_runtime::{bank::Bank, bank_forks::BankForks},
solana_sdk::{ solana_sdk::{
@ -342,6 +343,8 @@ impl SchedulerController {
{ {
saturating_add_assign!(post_transaction_check_count, 1); saturating_add_assign!(post_transaction_check_count, 1);
let transaction_id = self.transaction_id_generator.next(); let transaction_id = self.transaction_id_generator.next();
let transaction_cost = CostModel::calculate_cost(&transaction, &bank.feature_set);
let transaction_ttl = SanitizedTransactionTTL { let transaction_ttl = SanitizedTransactionTTL {
transaction, transaction,
max_age_slot: last_slot_in_epoch, max_age_slot: last_slot_in_epoch,
@ -351,6 +354,7 @@ impl SchedulerController {
transaction_id, transaction_id,
transaction_ttl, transaction_ttl,
priority_details, priority_details,
transaction_cost,
) { ) {
saturating_add_assign!(self.count_metrics.num_dropped_on_capacity, 1); saturating_add_assign!(self.count_metrics.num_dropped_on_capacity, 1);
} }

View File

@ -1,4 +1,5 @@
use { use {
solana_cost_model::transaction_cost::TransactionCost,
solana_runtime::transaction_priority_details::TransactionPriorityDetails, solana_runtime::transaction_priority_details::TransactionPriorityDetails,
solana_sdk::{slot_history::Slot, transaction::SanitizedTransaction}, solana_sdk::{slot_history::Slot, transaction::SanitizedTransaction},
}; };
@ -34,11 +35,13 @@ pub(crate) enum TransactionState {
Unprocessed { Unprocessed {
transaction_ttl: SanitizedTransactionTTL, transaction_ttl: SanitizedTransactionTTL,
transaction_priority_details: TransactionPriorityDetails, transaction_priority_details: TransactionPriorityDetails,
transaction_cost: TransactionCost,
forwarded: bool, forwarded: bool,
}, },
/// The transaction is currently scheduled or being processed. /// The transaction is currently scheduled or being processed.
Pending { Pending {
transaction_priority_details: TransactionPriorityDetails, transaction_priority_details: TransactionPriorityDetails,
transaction_cost: TransactionCost,
forwarded: bool, forwarded: bool,
}, },
} }
@ -48,10 +51,12 @@ impl TransactionState {
pub(crate) fn new( pub(crate) fn new(
transaction_ttl: SanitizedTransactionTTL, transaction_ttl: SanitizedTransactionTTL,
transaction_priority_details: TransactionPriorityDetails, transaction_priority_details: TransactionPriorityDetails,
transaction_cost: TransactionCost,
) -> Self { ) -> Self {
Self::Unprocessed { Self::Unprocessed {
transaction_ttl, transaction_ttl,
transaction_priority_details, transaction_priority_details,
transaction_cost,
forwarded: false, forwarded: false,
} }
} }
@ -70,6 +75,18 @@ impl TransactionState {
} }
} }
/// Returns a reference to the transaction cost of the transaction.
pub(crate) fn transaction_cost(&self) -> &TransactionCost {
match self {
Self::Unprocessed {
transaction_cost, ..
} => transaction_cost,
Self::Pending {
transaction_cost, ..
} => transaction_cost,
}
}
/// Returns the priority of the transaction. /// Returns the priority of the transaction.
pub(crate) fn priority(&self) -> u64 { pub(crate) fn priority(&self) -> u64 {
self.transaction_priority_details().priority self.transaction_priority_details().priority
@ -103,10 +120,12 @@ impl TransactionState {
TransactionState::Unprocessed { TransactionState::Unprocessed {
transaction_ttl, transaction_ttl,
transaction_priority_details, transaction_priority_details,
transaction_cost,
forwarded, forwarded,
} => { } => {
*self = TransactionState::Pending { *self = TransactionState::Pending {
transaction_priority_details, transaction_priority_details,
transaction_cost,
forwarded, forwarded,
}; };
transaction_ttl transaction_ttl
@ -128,11 +147,13 @@ impl TransactionState {
TransactionState::Unprocessed { .. } => panic!("already unprocessed"), TransactionState::Unprocessed { .. } => panic!("already unprocessed"),
TransactionState::Pending { TransactionState::Pending {
transaction_priority_details, transaction_priority_details,
transaction_cost,
forwarded, forwarded,
} => { } => {
*self = Self::Unprocessed { *self = Self::Unprocessed {
transaction_ttl, transaction_ttl,
transaction_priority_details, transaction_priority_details,
transaction_cost,
forwarded, forwarded,
} }
} }
@ -162,6 +183,9 @@ impl TransactionState {
priority: 0, priority: 0,
compute_unit_limit: 0, compute_unit_limit: 0,
}, },
transaction_cost: TransactionCost::SimpleVote {
writable_accounts: vec![],
},
forwarded: false, forwarded: false,
}, },
) )
@ -172,6 +196,7 @@ impl TransactionState {
mod tests { mod tests {
use { use {
super::*, super::*,
solana_cost_model::transaction_cost::UsageCostDetails,
solana_sdk::{ solana_sdk::{
compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message,
signature::Keypair, signer::Signer, system_instruction, transaction::Transaction, signature::Keypair, signer::Signer, system_instruction, transaction::Transaction,
@ -190,6 +215,10 @@ mod tests {
]; ];
let message = Message::new(&ixs, Some(&from_keypair.pubkey())); let message = Message::new(&ixs, Some(&from_keypair.pubkey()));
let tx = Transaction::new(&[&from_keypair], message, Hash::default()); let tx = Transaction::new(&[&from_keypair], message, Hash::default());
let transaction_cost = TransactionCost::Transaction(UsageCostDetails {
signature_cost: 5000,
..UsageCostDetails::default()
});
let transaction_ttl = SanitizedTransactionTTL { let transaction_ttl = SanitizedTransactionTTL {
transaction: SanitizedTransaction::from_transaction_for_tests(tx), transaction: SanitizedTransaction::from_transaction_for_tests(tx),
@ -202,6 +231,7 @@ mod tests {
priority, priority,
compute_unit_limit: 0, compute_unit_limit: 0,
}, },
transaction_cost,
) )
} }

View File

@ -5,6 +5,7 @@ use {
}, },
crate::banking_stage::scheduler_messages::TransactionId, crate::banking_stage::scheduler_messages::TransactionId,
min_max_heap::MinMaxHeap, min_max_heap::MinMaxHeap,
solana_cost_model::transaction_cost::TransactionCost,
solana_runtime::transaction_priority_details::TransactionPriorityDetails, solana_runtime::transaction_priority_details::TransactionPriorityDetails,
std::collections::HashMap, std::collections::HashMap,
}; };
@ -125,12 +126,17 @@ impl TransactionStateContainer {
transaction_id: TransactionId, transaction_id: TransactionId,
transaction_ttl: SanitizedTransactionTTL, transaction_ttl: SanitizedTransactionTTL,
transaction_priority_details: TransactionPriorityDetails, transaction_priority_details: TransactionPriorityDetails,
transaction_cost: TransactionCost,
) -> bool { ) -> bool {
let priority_id = let priority_id =
TransactionPriorityId::new(transaction_priority_details.priority, transaction_id); TransactionPriorityId::new(transaction_priority_details.priority, transaction_id);
self.id_to_transaction_state.insert( self.id_to_transaction_state.insert(
transaction_id, transaction_id,
TransactionState::new(transaction_ttl, transaction_priority_details), TransactionState::new(
transaction_ttl,
transaction_priority_details,
transaction_cost,
),
); );
self.push_id_into_queue(priority_id) self.push_id_into_queue(priority_id)
} }
@ -176,8 +182,10 @@ impl TransactionStateContainer {
mod tests { mod tests {
use { use {
super::*, super::*,
solana_cost_model::cost_model::CostModel,
solana_sdk::{ solana_sdk::{
compute_budget::ComputeBudgetInstruction, compute_budget::ComputeBudgetInstruction,
feature_set::FeatureSet,
hash::Hash, hash::Hash,
message::Message, message::Message,
signature::Keypair, signature::Keypair,
@ -188,7 +196,13 @@ mod tests {
}, },
}; };
fn test_transaction(priority: u64) -> (SanitizedTransactionTTL, TransactionPriorityDetails) { fn test_transaction(
priority: u64,
) -> (
SanitizedTransactionTTL,
TransactionPriorityDetails,
TransactionCost,
) {
let from_keypair = Keypair::new(); let from_keypair = Keypair::new();
let ixs = vec![ let ixs = vec![
system_instruction::transfer( system_instruction::transfer(
@ -199,10 +213,14 @@ mod tests {
ComputeBudgetInstruction::set_compute_unit_price(priority), ComputeBudgetInstruction::set_compute_unit_price(priority),
]; ];
let message = Message::new(&ixs, Some(&from_keypair.pubkey())); let message = Message::new(&ixs, Some(&from_keypair.pubkey()));
let tx = Transaction::new(&[&from_keypair], message, Hash::default()); let tx = SanitizedTransaction::from_transaction_for_tests(Transaction::new(
&[&from_keypair],
message,
Hash::default(),
));
let transaction_cost = CostModel::calculate_cost(&tx, &FeatureSet::default());
let transaction_ttl = SanitizedTransactionTTL { let transaction_ttl = SanitizedTransactionTTL {
transaction: SanitizedTransaction::from_transaction_for_tests(tx), transaction: tx,
max_age_slot: Slot::MAX, max_age_slot: Slot::MAX,
}; };
( (
@ -211,17 +229,20 @@ mod tests {
priority, priority,
compute_unit_limit: 0, compute_unit_limit: 0,
}, },
transaction_cost,
) )
} }
fn push_to_container(container: &mut TransactionStateContainer, num: usize) { fn push_to_container(container: &mut TransactionStateContainer, num: usize) {
for id in 0..num as u64 { for id in 0..num as u64 {
let priority = id; let priority = id;
let (transaction_ttl, transaction_priority_details) = test_transaction(priority); let (transaction_ttl, transaction_priority_details, transaction_cost) =
test_transaction(priority);
container.insert_new_transaction( container.insert_new_transaction(
TransactionId::new(id), TransactionId::new(id),
transaction_ttl, transaction_ttl,
transaction_priority_details, transaction_priority_details,
transaction_cost,
); );
} }
} }