diff --git a/Cargo.lock b/Cargo.lock index 9bf7b1c7b3..940fa25843 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5036,6 +5036,7 @@ dependencies = [ "chrono", "clap", "console", + "core_affinity", "libc", "log 0.4.8", "rand 0.7.3", diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index 92025524dc..ae593f61c3 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -4,7 +4,7 @@ use crate::{ cluster_info::ClusterInfo, poh_recorder::{PohRecorder, PohRecorderError, WorkingBankEntry}, - poh_service::PohService, + poh_service::{self, PohService}, }; use crossbeam_channel::{Receiver as CrossbeamReceiver, RecvTimeoutError}; use itertools::Itertools; @@ -1077,6 +1077,7 @@ pub fn create_test_recorder( &poh_config, &exit, bank.ticks_per_slot(), + poh_service::DEFAULT_PINNED_CPU_CORE, ); (exit, poh_recorder, poh_service, entry_receiver) diff --git a/core/src/poh_service.rs b/core/src/poh_service.rs index 07bf38dbc9..c104a4c74d 100644 --- a/core/src/poh_service.rs +++ b/core/src/poh_service.rs @@ -19,12 +19,15 @@ pub struct PohService { // See benches/poh.rs for some benchmarks that attempt to justify this magic number. pub const NUM_HASHES_PER_BATCH: u64 = 1; +pub const DEFAULT_PINNED_CPU_CORE: usize = 0; + impl PohService { pub fn new( poh_recorder: Arc>, poh_config: &Arc, poh_exit: &Arc, ticks_per_slot: u64, + pinned_cpu_core: usize, ) -> Self { let poh_exit_ = poh_exit.clone(); let poh_config = poh_config.clone(); @@ -47,7 +50,7 @@ impl PohService { // Let's dedicate one of the CPU cores to this thread so that it can gain // from cache performance. if let Some(cores) = core_affinity::get_core_ids() { - core_affinity::set_for_current(cores[0]); + core_affinity::set_for_current(cores[pinned_cpu_core]); } Self::tick_producer( poh_recorder, @@ -215,7 +218,13 @@ mod tests { .unwrap() }; - let poh_service = PohService::new(poh_recorder.clone(), &poh_config, &exit, 0); + let poh_service = PohService::new( + poh_recorder.clone(), + &poh_config, + &exit, + 0, + DEFAULT_PINNED_CPU_CORE, + ); poh_recorder.lock().unwrap().set_working_bank(working_bank); // get some events diff --git a/core/src/validator.rs b/core/src/validator.rs index 499ff4999e..0cb18a1fa2 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -13,7 +13,7 @@ use crate::{ OptimisticallyConfirmedBank, OptimisticallyConfirmedBankTracker, }, poh_recorder::{PohRecorder, GRACE_TICKS_FACTOR, MAX_GRACE_SLOTS}, - poh_service::PohService, + poh_service::{self, PohService}, rewards_recorder_service::{RewardsRecorderSender, RewardsRecorderService}, rpc::JsonRpcConfig, rpc_pubsub_service::{PubSubConfig, PubSubService}, @@ -108,6 +108,7 @@ pub struct ValidatorConfig { pub send_transaction_retry_ms: u64, pub send_transaction_leader_forward_count: u64, pub no_poh_speed_test: bool, + pub poh_pinned_cpu_core: usize, } impl Default for ValidatorConfig { @@ -147,6 +148,7 @@ impl Default for ValidatorConfig { send_transaction_retry_ms: 2000, send_transaction_leader_forward_count: 2, no_poh_speed_test: true, + poh_pinned_cpu_core: poh_service::DEFAULT_PINNED_CPU_CORE, } } } @@ -531,6 +533,7 @@ impl Validator { &poh_config, &exit, bank.ticks_per_slot(), + config.poh_pinned_cpu_core, ); assert_eq!( blockstore.new_shreds_signals.len(), @@ -757,7 +760,7 @@ fn check_poh_speed(genesis_config: &GenesisConfig, maybe_hash_samples: Option max_index { + return Err(format!("core index must be in the range [0, {}]", max_index)); + } + Ok(()) + }) + .help("EXPERIMENTAL: Specify which CPU core PoH is pinned to") + ) .get_matches(); let identity_keypair = Arc::new(keypair_of(&matches, "identity").unwrap_or_else(Keypair::new)); @@ -1609,6 +1626,8 @@ pub fn main() { u64 ), no_poh_speed_test: matches.is_present("no_poh_speed_test"), + poh_pinned_cpu_core: value_of(&matches, "poh_pinned_cpu_core") + .unwrap_or(poh_service::DEFAULT_PINNED_CPU_CORE), ..ValidatorConfig::default() };