TransactionState: add TransactionCost (#34881)
This commit is contained in:
parent
2f744f1639
commit
45a2a701de
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue