Skip to content

Commit de80e15

Browse files
authored
block-prioritization-fee metrics update (#6967)
* clean up naming * accumulates and reports included transaction fees * only collect total prioritization fee
1 parent 8adcd5a commit de80e15

File tree

2 files changed

+103
-50
lines changed

2 files changed

+103
-50
lines changed

runtime/src/prioritization_fee.rs

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ struct PrioritizationFeeMetrics {
2323
// Count of attempted update on finalized PrioritizationFee
2424
attempted_update_on_finalized_fee_count: Saturating<u64>,
2525

26-
// Total prioritization fees included in this slot.
26+
// Total transaction fees of non-vote transactions included in this slot.
2727
total_prioritization_fee: Saturating<u64>,
2828

29-
// The minimum prioritization fee of prioritized transactions in this slot.
30-
min_prioritization_fee: Option<u64>,
29+
// The minimum compute unit price of prioritized transactions in this slot.
30+
min_compute_unit_price: Option<u64>,
3131

32-
// The maximum prioritization fee of prioritized transactions in this slot.
33-
max_prioritization_fee: u64,
32+
// The maximum compute unit price of prioritized transactions in this slot.
33+
max_compute_unit_price: u64,
3434

3535
// Accumulated time spent on tracking prioritization fee for each slot.
3636
total_update_elapsed_us: Saturating<u64>,
@@ -49,20 +49,20 @@ impl PrioritizationFeeMetrics {
4949
self.attempted_update_on_finalized_fee_count += val;
5050
}
5151

52-
fn update_prioritization_fee(&mut self, fee: u64) {
53-
if fee == 0 {
52+
fn update_compute_unit_price(&mut self, cu_price: u64) {
53+
if cu_price == 0 {
5454
self.non_prioritized_transactions_count += 1;
5555
return;
5656
}
5757

5858
// update prioritized transaction fee metrics.
5959
self.prioritized_transactions_count += 1;
6060

61-
self.max_prioritization_fee = self.max_prioritization_fee.max(fee);
61+
self.max_compute_unit_price = self.max_compute_unit_price.max(cu_price);
6262

63-
self.min_prioritization_fee = Some(
64-
self.min_prioritization_fee
65-
.map_or(fee, |min_fee| min_fee.min(fee)),
63+
self.min_compute_unit_price = Some(
64+
self.min_compute_unit_price
65+
.map_or(cu_price, |min_cu_price| min_cu_price.min(cu_price)),
6666
);
6767
}
6868

@@ -75,8 +75,8 @@ impl PrioritizationFeeMetrics {
7575
attempted_update_on_finalized_fee_count:
7676
Saturating(attempted_update_on_finalized_fee_count),
7777
total_prioritization_fee: Saturating(total_prioritization_fee),
78-
min_prioritization_fee,
79-
max_prioritization_fee,
78+
min_compute_unit_price,
79+
max_compute_unit_price,
8080
total_update_elapsed_us: Saturating(total_update_elapsed_us),
8181
} = self;
8282
datapoint_info!(
@@ -113,11 +113,11 @@ impl PrioritizationFeeMetrics {
113113
i64
114114
),
115115
(
116-
"min_prioritization_fee",
117-
min_prioritization_fee.unwrap_or(0) as i64,
116+
"min_compute_unit_price",
117+
min_compute_unit_price.unwrap_or(0) as i64,
118118
i64
119119
),
120-
("max_prioritization_fee", max_prioritization_fee as i64, i64),
120+
("max_compute_unit_price", max_compute_unit_price as i64, i64),
121121
(
122122
"total_update_elapsed_us",
123123
total_update_elapsed_us as i64,
@@ -144,11 +144,11 @@ pub enum PrioritizationFeeError {
144144
/// Block minimum prioritization fee stats, includes the minimum prioritization fee for a transaction in this
145145
/// block; and the minimum fee for each writable account in all transactions in this block. The only relevant
146146
/// write account minimum fees are those greater than the block minimum transaction fee, because the minimum fee needed to land
147-
/// a transaction is determined by Max( min_transaction_fee, min_writable_account_fees(key), ...)
147+
/// a transaction is determined by Max( min_compute_unit_price, min_writable_account_fees(key), ...)
148148
#[derive(Debug)]
149149
pub struct PrioritizationFee {
150150
// The minimum prioritization fee of transactions that landed in this block.
151-
min_transaction_fee: u64,
151+
min_compute_unit_price: u64,
152152

153153
// The minimum prioritization fee of each writable account in transactions in this block.
154154
min_writable_account_fees: HashMap<Pubkey, u64>,
@@ -164,7 +164,7 @@ pub struct PrioritizationFee {
164164
impl Default for PrioritizationFee {
165165
fn default() -> Self {
166166
PrioritizationFee {
167-
min_transaction_fee: u64::MAX,
167+
min_compute_unit_price: u64::MAX,
168168
min_writable_account_fees: HashMap::new(),
169169
is_finalized: false,
170170
metrics: PrioritizationFeeMetrics::default(),
@@ -174,25 +174,30 @@ impl Default for PrioritizationFee {
174174

175175
impl PrioritizationFee {
176176
/// Update self for minimum transaction fee in the block and minimum fee for each writable account.
177-
pub fn update(&mut self, transaction_fee: u64, writable_accounts: Vec<Pubkey>) {
177+
pub fn update(
178+
&mut self,
179+
compute_unit_price: u64,
180+
prioritization_fee: u64,
181+
writable_accounts: Vec<Pubkey>,
182+
) {
178183
let (_, update_us) = measure_us!({
179184
if !self.is_finalized {
180-
if transaction_fee < self.min_transaction_fee {
181-
self.min_transaction_fee = transaction_fee;
185+
if compute_unit_price < self.min_compute_unit_price {
186+
self.min_compute_unit_price = compute_unit_price;
182187
}
183188

184189
for write_account in writable_accounts {
185190
self.min_writable_account_fees
186191
.entry(write_account)
187192
.and_modify(|write_lock_fee| {
188-
*write_lock_fee = std::cmp::min(*write_lock_fee, transaction_fee)
193+
*write_lock_fee = std::cmp::min(*write_lock_fee, compute_unit_price)
189194
})
190-
.or_insert(transaction_fee);
195+
.or_insert(compute_unit_price);
191196
}
192197

193198
self.metrics
194-
.accumulate_total_prioritization_fee(transaction_fee);
195-
self.metrics.update_prioritization_fee(transaction_fee);
199+
.accumulate_total_prioritization_fee(prioritization_fee);
200+
self.metrics.update_compute_unit_price(compute_unit_price);
196201
} else {
197202
self.metrics
198203
.increment_attempted_update_on_finalized_fee_count(1);
@@ -207,7 +212,7 @@ impl PrioritizationFee {
207212
fn prune_irrelevant_writable_accounts(&mut self) {
208213
self.metrics.total_writable_accounts_count = self.get_writable_accounts_count() as u64;
209214
self.min_writable_account_fees
210-
.retain(|_, account_fee| account_fee > &mut self.min_transaction_fee);
215+
.retain(|_, account_fee| account_fee > &mut self.min_compute_unit_price);
211216
self.metrics.relevant_writable_accounts_count = self.get_writable_accounts_count() as u64;
212217
}
213218

@@ -220,8 +225,8 @@ impl PrioritizationFee {
220225
Ok(())
221226
}
222227

223-
pub fn get_min_transaction_fee(&self) -> Option<u64> {
224-
(self.min_transaction_fee != u64::MAX).then_some(self.min_transaction_fee)
228+
pub fn get_min_compute_unit_price(&self) -> Option<u64> {
229+
(self.min_compute_unit_price != u64::MAX).then_some(self.min_compute_unit_price)
225230
}
226231

227232
pub fn get_writable_account_fee(&self, key: &Pubkey) -> Option<u64> {
@@ -250,22 +255,23 @@ mod tests {
250255
use {super::*, solana_pubkey::Pubkey};
251256

252257
#[test]
253-
fn test_update_prioritization_fee() {
258+
fn test_update_compute_unit_price() {
254259
solana_logger::setup();
255260
let write_account_a = Pubkey::new_unique();
256261
let write_account_b = Pubkey::new_unique();
257262
let write_account_c = Pubkey::new_unique();
263+
let tx_fee = 10;
258264

259265
let mut prioritization_fee = PrioritizationFee::default();
260-
assert!(prioritization_fee.get_min_transaction_fee().is_none());
266+
assert!(prioritization_fee.get_min_compute_unit_price().is_none());
261267

262268
// Assert for 1st transaction
263-
// [fee, write_accounts...] --> [block, account_a, account_b, account_c]
269+
// [cu_px, write_accounts...] --> [block, account_a, account_b, account_c]
264270
// -----------------------------------------------------------------------
265271
// [5, a, b ] --> [5, 5, 5, nil ]
266272
{
267-
prioritization_fee.update(5, vec![write_account_a, write_account_b]);
268-
assert_eq!(5, prioritization_fee.get_min_transaction_fee().unwrap());
273+
prioritization_fee.update(5, tx_fee, vec![write_account_a, write_account_b]);
274+
assert_eq!(5, prioritization_fee.get_min_compute_unit_price().unwrap());
269275
assert_eq!(
270276
5,
271277
prioritization_fee
@@ -284,12 +290,12 @@ mod tests {
284290
}
285291

286292
// Assert for second transaction:
287-
// [fee, write_accounts...] --> [block, account_a, account_b, account_c]
293+
// [cu_px, write_accounts...] --> [block, account_a, account_b, account_c]
288294
// -----------------------------------------------------------------------
289295
// [9, b, c ] --> [5, 5, 5, 9 ]
290296
{
291-
prioritization_fee.update(9, vec![write_account_b, write_account_c]);
292-
assert_eq!(5, prioritization_fee.get_min_transaction_fee().unwrap());
297+
prioritization_fee.update(9, tx_fee, vec![write_account_b, write_account_c]);
298+
assert_eq!(5, prioritization_fee.get_min_compute_unit_price().unwrap());
293299
assert_eq!(
294300
5,
295301
prioritization_fee
@@ -311,12 +317,12 @@ mod tests {
311317
}
312318

313319
// Assert for third transaction:
314-
// [fee, write_accounts...] --> [block, account_a, account_b, account_c]
320+
// [cu_px, write_accounts...] --> [block, account_a, account_b, account_c]
315321
// -----------------------------------------------------------------------
316322
// [2, a, c ] --> [2, 2, 5, 2 ]
317323
{
318-
prioritization_fee.update(2, vec![write_account_a, write_account_c]);
319-
assert_eq!(2, prioritization_fee.get_min_transaction_fee().unwrap());
324+
prioritization_fee.update(2, tx_fee, vec![write_account_a, write_account_c]);
325+
assert_eq!(2, prioritization_fee.get_min_compute_unit_price().unwrap());
320326
assert_eq!(
321327
2,
322328
prioritization_fee
@@ -341,7 +347,7 @@ mod tests {
341347
{
342348
prioritization_fee.prune_irrelevant_writable_accounts();
343349
assert_eq!(1, prioritization_fee.min_writable_account_fees.len());
344-
assert_eq!(2, prioritization_fee.get_min_transaction_fee().unwrap());
350+
assert_eq!(2, prioritization_fee.get_min_compute_unit_price().unwrap());
345351
assert!(prioritization_fee
346352
.get_writable_account_fee(&write_account_a)
347353
.is_none());
@@ -357,6 +363,25 @@ mod tests {
357363
}
358364
}
359365

366+
#[test]
367+
fn test_total_prioritization_fee() {
368+
let mut prioritization_fee = PrioritizationFee::default();
369+
prioritization_fee.update(0, 10, vec![]);
370+
assert_eq!(10, prioritization_fee.metrics.total_prioritization_fee.0);
371+
372+
prioritization_fee.update(10, u64::MAX, vec![]);
373+
assert_eq!(
374+
u64::MAX,
375+
prioritization_fee.metrics.total_prioritization_fee.0
376+
);
377+
378+
prioritization_fee.update(10, 100, vec![]);
379+
assert_eq!(
380+
u64::MAX,
381+
prioritization_fee.metrics.total_prioritization_fee.0
382+
);
383+
}
384+
360385
#[test]
361386
fn test_mark_block_completed() {
362387
let mut prioritization_fee = PrioritizationFee::default();

runtime/src/prioritization_fee_cache.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{bank::Bank, prioritization_fee::*},
2+
crate::{bank::Bank, prioritization_fee::PrioritizationFee},
33
crossbeam_channel::{unbounded, Receiver, Sender, TryRecvError},
44
log::*,
55
solana_accounts_db::account_locks::validate_account_locks,
@@ -47,6 +47,9 @@ struct PrioritizationFeeCacheMetrics {
4747

4848
// Accumulated time spent on finalizing block prioritization fees.
4949
total_block_finalize_elapsed_us: AtomicU64,
50+
51+
// Accumulated time spent on calculate transaction fees.
52+
total_calculate_prioritization_fee_elapsed_us: AtomicU64,
5053
}
5154

5255
impl PrioritizationFeeCacheMetrics {
@@ -80,6 +83,11 @@ impl PrioritizationFeeCacheMetrics {
8083
.fetch_add(val, Ordering::Relaxed);
8184
}
8285

86+
fn accumulate_total_calculate_prioritization_fee_elapsed_us(&self, val: u64) {
87+
self.total_calculate_prioritization_fee_elapsed_us
88+
.fetch_add(val, Ordering::Relaxed);
89+
}
90+
8391
fn report(&self, slot: Slot) {
8492
datapoint_info!(
8593
"block_prioritization_fee_counters",
@@ -117,6 +125,12 @@ impl PrioritizationFeeCacheMetrics {
117125
.swap(0, Ordering::Relaxed) as i64,
118126
i64
119127
),
128+
(
129+
"total_calculate_prioritization_fee_elapsed_us",
130+
self.total_calculate_prioritization_fee_elapsed_us
131+
.swap(0, Ordering::Relaxed) as i64,
132+
i64
133+
),
120134
);
121135
}
122136
}
@@ -126,7 +140,8 @@ enum CacheServiceUpdate {
126140
TransactionUpdate {
127141
slot: Slot,
128142
bank_id: BankId,
129-
transaction_fee: u64,
143+
compute_unit_price: u64,
144+
prioritization_fee: u64,
130145
writable_accounts: Vec<Pubkey>,
131146
},
132147
BankFinalized {
@@ -233,11 +248,21 @@ impl PrioritizationFeeCache {
233248
.map(|(_, key)| *key)
234249
.collect();
235250

251+
let (prioritization_fee, calculate_prioritization_fee_us) = measure_us!({
252+
solana_fee_structure::FeeBudgetLimits::from(compute_budget_limits)
253+
.prioritization_fee
254+
});
255+
self.metrics
256+
.accumulate_total_calculate_prioritization_fee_elapsed_us(
257+
calculate_prioritization_fee_us,
258+
);
259+
236260
self.sender
237261
.send(CacheServiceUpdate::TransactionUpdate {
238262
slot: bank.slot(),
239263
bank_id: bank.bank_id(),
240-
transaction_fee: compute_budget_limits.compute_unit_price,
264+
compute_unit_price: compute_budget_limits.compute_unit_price,
265+
prioritization_fee,
241266
writable_accounts,
242267
})
243268
.unwrap_or_else(|err| {
@@ -271,7 +296,8 @@ impl PrioritizationFeeCache {
271296
unfinalized: &mut UnfinalizedPrioritizationFees,
272297
slot: Slot,
273298
bank_id: BankId,
274-
transaction_fee: u64,
299+
compute_unit_price: u64,
300+
prioritization_fee: u64,
275301
writable_accounts: Vec<Pubkey>,
276302
metrics: &PrioritizationFeeCacheMetrics,
277303
) {
@@ -280,7 +306,7 @@ impl PrioritizationFeeCache {
280306
.or_default()
281307
.entry(bank_id)
282308
.or_default()
283-
.update(transaction_fee, writable_accounts));
309+
.update(compute_unit_price, prioritization_fee, writable_accounts));
284310
metrics.accumulate_total_entry_update_elapsed_us(entry_update_us);
285311
metrics.accumulate_successful_transaction_update_count(1);
286312
}
@@ -374,13 +400,15 @@ impl PrioritizationFeeCache {
374400
CacheServiceUpdate::TransactionUpdate {
375401
slot,
376402
bank_id,
377-
transaction_fee,
403+
compute_unit_price,
404+
prioritization_fee,
378405
writable_accounts,
379406
} => Self::update_cache(
380407
&mut unfinalized,
381408
slot,
382409
bank_id,
383-
transaction_fee,
410+
compute_unit_price,
411+
prioritization_fee,
384412
writable_accounts,
385413
&metrics,
386414
),
@@ -414,7 +442,7 @@ impl PrioritizationFeeCache {
414442
.iter()
415443
.map(|(slot, slot_prioritization_fee)| {
416444
let mut fee = slot_prioritization_fee
417-
.get_min_transaction_fee()
445+
.get_min_compute_unit_price()
418446
.unwrap_or_default();
419447
for account_key in account_keys {
420448
if let Some(account_fee) =
@@ -549,7 +577,7 @@ mod tests {
549577
sync_finalize_priority_fee_for_test(&prioritization_fee_cache, slot, bank.bank_id());
550578
let lock = prioritization_fee_cache.cache.read().unwrap();
551579
let fee = lock.get(&slot).unwrap();
552-
assert_eq!(2, fee.get_min_transaction_fee().unwrap());
580+
assert_eq!(2, fee.get_min_compute_unit_price().unwrap());
553581
assert!(fee.get_writable_account_fee(&write_account_a).is_none());
554582
assert_eq!(5, fee.get_writable_account_fee(&write_account_b).unwrap());
555583
assert!(fee.get_writable_account_fee(&write_account_c).is_none());

0 commit comments

Comments
 (0)