bench_lock_accounts.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. use {
  2. criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput},
  3. itertools::iproduct,
  4. solana_accounts_db::{accounts::Accounts, accounts_db::AccountsDb},
  5. solana_instruction::{AccountMeta, Instruction},
  6. solana_pubkey::Pubkey,
  7. solana_sdk_ids::system_program,
  8. solana_transaction::{
  9. sanitized::{SanitizedTransaction, MAX_TX_ACCOUNT_LOCKS},
  10. Transaction,
  11. },
  12. std::sync::Arc,
  13. };
  14. #[cfg(not(any(target_env = "msvc", target_os = "freebsd")))]
  15. #[global_allocator]
  16. static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
  17. // simultaneous transactions locked
  18. const BATCH_SIZES: [usize; 3] = [1, 32, 64];
  19. // locks acquired per transaction
  20. const LOCK_COUNTS: [usize; 2] = [2, 64];
  21. // total transactions per run
  22. const TOTAL_TRANSACTIONS: usize = 1024;
  23. fn create_test_transactions(lock_count: usize, read_conflicts: bool) -> Vec<SanitizedTransaction> {
  24. // keys available to be shared between transactions, depending on mode
  25. // currently, we test batches with no conflicts and batches with reader/reader conflicts
  26. // in the future with SIMD83, we will also test reader/writer and writer/writer conflicts
  27. let shared_pubkeys: Vec<_> = (0..lock_count).map(|_| Pubkey::new_unique()).collect();
  28. let mut transactions = vec![];
  29. for _ in 0..TOTAL_TRANSACTIONS {
  30. let mut account_metas = vec![];
  31. #[allow(clippy::needless_range_loop)]
  32. for i in 0..lock_count {
  33. // `lock_accounts()` distinguishes writable from readonly, so give transactions an even split
  34. // signer doesn't matter for locking but `sanitize()` expects to see at least one
  35. let account_meta = if i == 0 {
  36. AccountMeta::new(Pubkey::new_unique(), true)
  37. } else if i % 2 == 0 {
  38. AccountMeta::new(Pubkey::new_unique(), false)
  39. } else if read_conflicts {
  40. AccountMeta::new_readonly(shared_pubkeys[i], false)
  41. } else {
  42. AccountMeta::new_readonly(Pubkey::new_unique(), false)
  43. };
  44. account_metas.push(account_meta);
  45. }
  46. let instruction = Instruction::new_with_bincode(system_program::id(), &(), account_metas);
  47. let transaction = Transaction::new_with_payer(&[instruction], None);
  48. transactions.push(SanitizedTransaction::from_transaction_for_tests(
  49. transaction,
  50. ));
  51. }
  52. transactions
  53. }
  54. fn bench_entry_lock_accounts(c: &mut Criterion) {
  55. let mut group = c.benchmark_group("bench_lock_accounts");
  56. for (batch_size, lock_count, read_conflicts, relax_intrabatch_account_locks) in
  57. iproduct!(BATCH_SIZES, LOCK_COUNTS, [false, true], [false, true])
  58. {
  59. let name = format!(
  60. "batch_size_{batch_size}_locks_count_{lock_count}{}{}",
  61. if read_conflicts {
  62. "_read_conflicts"
  63. } else {
  64. ""
  65. },
  66. if relax_intrabatch_account_locks {
  67. "_simd83"
  68. } else {
  69. "_old"
  70. },
  71. );
  72. let accounts_db = AccountsDb::new_single_for_tests();
  73. let accounts = Accounts::new(Arc::new(accounts_db));
  74. let transactions = create_test_transactions(lock_count, read_conflicts);
  75. group.throughput(Throughput::Elements(transactions.len() as u64));
  76. let transaction_batches: Vec<_> = transactions.chunks(batch_size).collect();
  77. let batch_results = vec![Ok(()); batch_size].into_iter();
  78. group.bench_function(name.as_str(), move |b| {
  79. b.iter(|| {
  80. for batch in &transaction_batches {
  81. let results = accounts.lock_accounts(
  82. black_box(batch.iter()),
  83. batch_results.clone(),
  84. MAX_TX_ACCOUNT_LOCKS,
  85. relax_intrabatch_account_locks,
  86. );
  87. accounts.unlock_accounts(batch.iter().zip(&results));
  88. }
  89. })
  90. });
  91. }
  92. }
  93. criterion_group!(benches, bench_entry_lock_accounts);
  94. criterion_main!(benches);