| 
									
										
										
										
											2021-02-16 14:48:20 -07:00
										 |  |  | #![allow(clippy::integer_arithmetic)]
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | // Long-running ledger_cleanup tests
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[cfg(test)]
 | 
					
						
							|  |  |  | mod tests {
 | 
					
						
							| 
									
										
										
										
											2021-12-03 09:00:31 -08:00
										 |  |  |     use {
 | 
					
						
							| 
									
										
										
										
											2022-01-11 02:44:46 -08:00
										 |  |  |         crossbeam_channel::unbounded,
 | 
					
						
							| 
									
										
										
										
											2021-12-03 09:00:31 -08:00
										 |  |  |         log::*,
 | 
					
						
							|  |  |  |         solana_core::ledger_cleanup_service::LedgerCleanupService,
 | 
					
						
							|  |  |  |         solana_ledger::{
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |             blockstore::{make_many_slot_shreds, Blockstore},
 | 
					
						
							| 
									
										
										
										
											2022-03-11 15:17:34 -08:00
										 |  |  |             blockstore_db::{
 | 
					
						
							| 
									
										
										
										
											2022-03-18 11:13:35 -07:00
										 |  |  |                 BlockstoreOptions, BlockstoreRocksFifoOptions, LedgerColumnOptions,
 | 
					
						
							| 
									
										
										
										
											2022-03-11 15:17:34 -08:00
										 |  |  |                 ShredStorageType,
 | 
					
						
							|  |  |  |             },
 | 
					
						
							| 
									
										
										
										
											2021-12-03 09:00:31 -08:00
										 |  |  |             get_tmp_ledger_path,
 | 
					
						
							|  |  |  |         },
 | 
					
						
							|  |  |  |         solana_measure::measure::Measure,
 | 
					
						
							|  |  |  |         std::{
 | 
					
						
							|  |  |  |             collections::VecDeque,
 | 
					
						
							|  |  |  |             str::FromStr,
 | 
					
						
							|  |  |  |             sync::{
 | 
					
						
							|  |  |  |                 atomic::{AtomicBool, AtomicU64, Ordering},
 | 
					
						
							|  |  |  |                 Arc, Mutex, RwLock,
 | 
					
						
							|  |  |  |             },
 | 
					
						
							|  |  |  |             thread::{self, Builder, JoinHandle},
 | 
					
						
							|  |  |  |             time::{Duration, Instant},
 | 
					
						
							|  |  |  |         },
 | 
					
						
							|  |  |  |         systemstat::{CPULoad, Platform, System},
 | 
					
						
							|  |  |  |     };
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-03 12:05:14 -08:00
										 |  |  |     const DEFAULT_BENCHMARK_SLOTS: u64 = 50;
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |     const DEFAULT_BATCH_SIZE_SLOTS: u64 = 1;
 | 
					
						
							| 
									
										
										
										
											2020-03-31 17:21:19 -07:00
										 |  |  |     const DEFAULT_MAX_LEDGER_SHREDS: u64 = 50;
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |     const DEFAULT_SHREDS_PER_SLOT: u64 = 25;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |     const DEFAULT_STOP_SIZE_BYTES: u64 = 0;
 | 
					
						
							|  |  |  |     const DEFAULT_STOP_SIZE_ITERATIONS: u64 = 0;
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |     const DEFAULT_STOP_SIZE_CF_DATA_BYTES: u64 = 0;
 | 
					
						
							| 
									
										
										
										
											2022-02-12 00:43:25 -08:00
										 |  |  |     const DEFAULT_SHRED_DATA_CF_SIZE_BYTES: u64 = 125 * 1024 * 1024 * 1024;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const ROCKSDB_FLUSH_GRACE_PERIOD_SECS: u64 = 20;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[derive(Debug)]
 | 
					
						
							|  |  |  |     struct BenchmarkConfig {
 | 
					
						
							| 
									
										
										
										
											2021-10-05 22:24:48 -07:00
										 |  |  |         benchmark_slots: u64,
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         batch_size_slots: u64,
 | 
					
						
							| 
									
										
										
										
											2021-10-05 22:24:48 -07:00
										 |  |  |         max_ledger_shreds: u64,
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         shreds_per_slot: u64,
 | 
					
						
							| 
									
										
										
										
											2021-10-05 22:24:48 -07:00
										 |  |  |         stop_size_bytes: u64,
 | 
					
						
							|  |  |  |         stop_size_iterations: u64,
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |         stop_size_cf_data_bytes: u64,
 | 
					
						
							| 
									
										
										
										
											2021-10-05 22:24:48 -07:00
										 |  |  |         pre_generate_data: bool,
 | 
					
						
							|  |  |  |         cleanup_blockstore: bool,
 | 
					
						
							|  |  |  |         assert_compaction: bool,
 | 
					
						
							|  |  |  |         compaction_interval: Option<u64>,
 | 
					
						
							|  |  |  |         no_compaction: bool,
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |         num_writers: u64,
 | 
					
						
							| 
									
										
										
										
											2022-01-05 21:46:02 -10:00
										 |  |  |         cleanup_service: bool,
 | 
					
						
							| 
									
										
										
										
											2022-02-12 00:43:25 -08:00
										 |  |  |         fifo_compaction: bool,
 | 
					
						
							|  |  |  |         shred_data_cf_size: u64,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[derive(Clone, Copy, Debug)]
 | 
					
						
							|  |  |  |     struct CpuStatsInner {
 | 
					
						
							| 
									
										
										
										
											2021-10-05 22:24:48 -07:00
										 |  |  |         cpu_user: f32,
 | 
					
						
							|  |  |  |         cpu_system: f32,
 | 
					
						
							|  |  |  |         cpu_idle: f32,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     impl From<CPULoad> for CpuStatsInner {
 | 
					
						
							|  |  |  |         fn from(cpu: CPULoad) -> Self {
 | 
					
						
							|  |  |  |             Self {
 | 
					
						
							|  |  |  |                 cpu_user: cpu.user * 100.0,
 | 
					
						
							|  |  |  |                 cpu_system: cpu.system * 100.0,
 | 
					
						
							|  |  |  |                 cpu_idle: cpu.idle * 100.0,
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     impl Default for CpuStatsInner {
 | 
					
						
							|  |  |  |         fn default() -> Self {
 | 
					
						
							|  |  |  |             Self {
 | 
					
						
							|  |  |  |                 cpu_user: 0.0,
 | 
					
						
							|  |  |  |                 cpu_system: 0.0,
 | 
					
						
							|  |  |  |                 cpu_idle: 0.0,
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     struct CpuStats {
 | 
					
						
							|  |  |  |         stats: RwLock<CpuStatsInner>,
 | 
					
						
							|  |  |  |         sys: System,
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     impl Default for CpuStats {
 | 
					
						
							|  |  |  |         fn default() -> Self {
 | 
					
						
							|  |  |  |             Self {
 | 
					
						
							|  |  |  |                 stats: RwLock::new(CpuStatsInner::default()),
 | 
					
						
							|  |  |  |                 sys: System::new(),
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     impl CpuStats {
 | 
					
						
							|  |  |  |         fn update(&self) {
 | 
					
						
							| 
									
										
										
										
											2020-05-15 17:35:43 +01:00
										 |  |  |             if let Ok(cpu) = self.sys.cpu_load_aggregate() {
 | 
					
						
							|  |  |  |                 std::thread::sleep(Duration::from_millis(400));
 | 
					
						
							|  |  |  |                 let cpu_new = CpuStatsInner::from(cpu.done().unwrap());
 | 
					
						
							|  |  |  |                 *self.stats.write().unwrap() = cpu_new;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fn get_stats(&self) -> CpuStatsInner {
 | 
					
						
							| 
									
										
										
										
											2020-05-15 17:35:43 +01:00
										 |  |  |             *self.stats.read().unwrap()
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     struct CpuStatsUpdater {
 | 
					
						
							|  |  |  |         cpu_stats: Arc<CpuStats>,
 | 
					
						
							|  |  |  |         t_cleanup: JoinHandle<()>,
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     impl CpuStatsUpdater {
 | 
					
						
							|  |  |  |         pub fn new(exit: &Arc<AtomicBool>) -> Self {
 | 
					
						
							|  |  |  |             let exit = exit.clone();
 | 
					
						
							|  |  |  |             let cpu_stats = Arc::new(CpuStats::default());
 | 
					
						
							|  |  |  |             let cpu_stats_clone = cpu_stats.clone();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             let t_cleanup = Builder::new()
 | 
					
						
							|  |  |  |                 .name("cpu_info".to_string())
 | 
					
						
							|  |  |  |                 .spawn(move || loop {
 | 
					
						
							|  |  |  |                     if exit.load(Ordering::Relaxed) {
 | 
					
						
							|  |  |  |                         break;
 | 
					
						
							|  |  |  |                     }
 | 
					
						
							|  |  |  |                     cpu_stats_clone.update();
 | 
					
						
							|  |  |  |                 })
 | 
					
						
							|  |  |  |                 .unwrap();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Self {
 | 
					
						
							| 
									
										
										
										
											2020-05-15 17:35:43 +01:00
										 |  |  |                 cpu_stats,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |                 t_cleanup,
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pub fn get_stats(&self) -> CpuStatsInner {
 | 
					
						
							|  |  |  |             self.cpu_stats.get_stats()
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pub fn join(self) -> std::thread::Result<()> {
 | 
					
						
							|  |  |  |             self.t_cleanup.join()
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn read_env<T>(key: &str, default: T) -> T
 | 
					
						
							|  |  |  |     where
 | 
					
						
							|  |  |  |         T: FromStr,
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         match std::env::var(key) {
 | 
					
						
							|  |  |  |             Ok(val) => val.parse().unwrap_or(default),
 | 
					
						
							|  |  |  |             Err(_e) => default,
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-04 23:35:55 -10:00
										 |  |  |     /// Obtains the benchmark config from the following environmental arguments:
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Basic benchmark settings:
 | 
					
						
							|  |  |  |     /// - `BENCHMARK_SLOTS`: the number of slots in the benchmark.
 | 
					
						
							|  |  |  |     /// - `BATCH_SIZE`: the number of slots in each write batch.
 | 
					
						
							|  |  |  |     /// - `SHREDS_PER_SLOT`: the number of shreds in each slot.  Together with
 | 
					
						
							|  |  |  |     ///   the `BATCH_SIZE` and `BENCHMARK_SLOTS`, it means:
 | 
					
						
							|  |  |  |     ///    - the number of shreds in one write batch is `BATCH_SIZE` * `SHREDS_PER_SLOT`.
 | 
					
						
							|  |  |  |     ///    - the total number of batches is `BENCHMARK_SLOTS` / `BATCH_SIZE`.
 | 
					
						
							|  |  |  |     ///    - the total number of shreds is `BENCHMARK_SLOTS` * `SHREDS_PER_SLOT`.
 | 
					
						
							|  |  |  |     /// - `NUM_WRITERS`: controls the number of concurrent threads performing
 | 
					
						
							|  |  |  |     ///   shred insertion.  Default: 1.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Advanced benchmark settings:
 | 
					
						
							|  |  |  |     /// - `STOP_SIZE_BYTES`: if specified, the benchmark will count how
 | 
					
						
							|  |  |  |     ///   many times the ledger store size exceeds the specified threshold.
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |     /// - `STOP_SIZE_CF_DATA_BYTES`: if specified, the benchmark will count how
 | 
					
						
							|  |  |  |     ///   many times the storage size of `cf::ShredData` which stores data shred
 | 
					
						
							|  |  |  |     ///   exceeds the specified threshold.
 | 
					
						
							|  |  |  |     /// - `STOP_SIZE_ITERATIONS`: when any of the stop size is specified, the
 | 
					
						
							|  |  |  |     ///   benchmark will stop immediately when the number of consecutive times
 | 
					
						
							|  |  |  |     ///   where the ledger store size exceeds the configured `STOP_SIZE_BYTES`.
 | 
					
						
							|  |  |  |     ///   These configs are used to make sure the benchmark runs successfully
 | 
					
						
							|  |  |  |     ///   under the storage limitation.
 | 
					
						
							| 
									
										
										
										
											2022-01-04 23:35:55 -10:00
										 |  |  |     /// - `CLEANUP_BLOCKSTORE`: if true, the ledger store created in the current
 | 
					
						
							|  |  |  |     ///   benchmark run will be deleted.  Default: true.
 | 
					
						
							|  |  |  |     /// - `NO_COMPACTION`: whether to stop rocksdb's background compaction
 | 
					
						
							|  |  |  |     ///   completely.  Default: false.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Cleanup-service related settings:
 | 
					
						
							|  |  |  |     /// - `MAX_LEDGER_SHREDS`: when the clean-up service is on, the service will
 | 
					
						
							|  |  |  |     ///   clean up the ledger store when the number of shreds exceeds this value.
 | 
					
						
							|  |  |  |     /// - `COMPACTION_INTERVAL`: if set, the clean-up service will compact all
 | 
					
						
							|  |  |  |     ///   slots that are older than the specified interval.  The interval is
 | 
					
						
							|  |  |  |     ///   measured by slots.
 | 
					
						
							|  |  |  |     ///   Default: the number of slots per day (`TICKS_PER_DAY` / `DEFAULT_TICKS_PER_SLOT`)
 | 
					
						
							|  |  |  |     /// - `ASSERT_COMPACTION`: if true, then the benchmark will perform a sanity check
 | 
					
						
							|  |  |  |     ///   on whether clean-up service triggers the expected compaction at the end of
 | 
					
						
							|  |  |  |     ///   the benchmark run.  Default: false.
 | 
					
						
							| 
									
										
										
										
											2022-01-05 21:46:02 -10:00
										 |  |  |     /// - `CLEANUP_SERVICE`: whether to enable the background cleanup service.
 | 
					
						
							|  |  |  |     ///   If set to false, the ledger store in the benchmark will be purely relied
 | 
					
						
							|  |  |  |     ///   on RocksDB's compaction.  Default: true.
 | 
					
						
							| 
									
										
										
										
											2022-02-12 00:43:25 -08:00
										 |  |  |     ///
 | 
					
						
							|  |  |  |     /// Fifo-compaction settings:
 | 
					
						
							|  |  |  |     /// - `FIFO_COMPACTION`: if true, then RocksDB's Fifo compaction will be
 | 
					
						
							|  |  |  |     ///   used for storing data shreds.  Default: false.
 | 
					
						
							|  |  |  |     /// - `SHRED_DATA_CF_SIZE_BYTES`: the maximum size of the data-shred column family.
 | 
					
						
							|  |  |  |     ///   Default: 125 * 1024 * 1024 * 1024.
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |     fn get_benchmark_config() -> BenchmarkConfig {
 | 
					
						
							|  |  |  |         let benchmark_slots = read_env("BENCHMARK_SLOTS", DEFAULT_BENCHMARK_SLOTS);
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         let batch_size_slots = read_env("BATCH_SIZE", DEFAULT_BATCH_SIZE_SLOTS);
 | 
					
						
							| 
									
										
										
										
											2020-03-31 17:21:19 -07:00
										 |  |  |         let max_ledger_shreds = read_env("MAX_LEDGER_SHREDS", DEFAULT_MAX_LEDGER_SHREDS);
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         let shreds_per_slot = read_env("SHREDS_PER_SLOT", DEFAULT_SHREDS_PER_SLOT);
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let stop_size_bytes = read_env("STOP_SIZE_BYTES", DEFAULT_STOP_SIZE_BYTES);
 | 
					
						
							|  |  |  |         let stop_size_iterations = read_env("STOP_SIZE_ITERATIONS", DEFAULT_STOP_SIZE_ITERATIONS);
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |         let stop_size_cf_data_bytes =
 | 
					
						
							|  |  |  |             read_env("STOP_SIZE_CF_DATA_BYTES", DEFAULT_STOP_SIZE_CF_DATA_BYTES);
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let pre_generate_data = read_env("PRE_GENERATE_DATA", false);
 | 
					
						
							| 
									
										
										
										
											2020-01-13 14:13:52 -07:00
										 |  |  |         let cleanup_blockstore = read_env("CLEANUP_BLOCKSTORE", true);
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         // set default to `true` once compaction is merged
 | 
					
						
							|  |  |  |         let assert_compaction = read_env("ASSERT_COMPACTION", false);
 | 
					
						
							| 
									
										
										
										
											2021-05-28 16:42:56 +09:00
										 |  |  |         let compaction_interval = match read_env("COMPACTION_INTERVAL", 0) {
 | 
					
						
							|  |  |  |             maybe_zero if maybe_zero == 0 => None,
 | 
					
						
							|  |  |  |             non_zero => Some(non_zero),
 | 
					
						
							|  |  |  |         };
 | 
					
						
							|  |  |  |         let no_compaction = read_env("NO_COMPACTION", false);
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |         let num_writers = read_env("NUM_WRITERS", 1);
 | 
					
						
							| 
									
										
										
										
											2022-01-05 21:46:02 -10:00
										 |  |  |         // A flag indicating whether to have a background clean-up service.
 | 
					
						
							|  |  |  |         // If set to false, the ledger store will purely rely on RocksDB's
 | 
					
						
							|  |  |  |         // compaction to perform the clean-up.
 | 
					
						
							|  |  |  |         let cleanup_service = read_env("CLEANUP_SERVICE", true);
 | 
					
						
							| 
									
										
										
										
											2022-02-12 00:43:25 -08:00
										 |  |  |         let fifo_compaction = read_env("FIFO_COMPACTION", false);
 | 
					
						
							|  |  |  |         let shred_data_cf_size =
 | 
					
						
							|  |  |  |             read_env("SHRED_DATA_CF_SIZE_BYTES", DEFAULT_SHRED_DATA_CF_SIZE_BYTES);
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         BenchmarkConfig {
 | 
					
						
							|  |  |  |             benchmark_slots,
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |             batch_size_slots,
 | 
					
						
							| 
									
										
										
										
											2020-03-31 17:21:19 -07:00
										 |  |  |             max_ledger_shreds,
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |             shreds_per_slot,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             stop_size_bytes,
 | 
					
						
							|  |  |  |             stop_size_iterations,
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |             stop_size_cf_data_bytes,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             pre_generate_data,
 | 
					
						
							| 
									
										
										
										
											2020-01-13 14:13:52 -07:00
										 |  |  |             cleanup_blockstore,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             assert_compaction,
 | 
					
						
							| 
									
										
										
										
											2021-05-28 16:42:56 +09:00
										 |  |  |             compaction_interval,
 | 
					
						
							|  |  |  |             no_compaction,
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |             num_writers,
 | 
					
						
							| 
									
										
										
										
											2022-01-05 21:46:02 -10:00
										 |  |  |             cleanup_service,
 | 
					
						
							| 
									
										
										
										
											2022-02-12 00:43:25 -08:00
										 |  |  |             fifo_compaction,
 | 
					
						
							|  |  |  |             shred_data_cf_size,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn emit_header() {
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |         println!("TIME_MS,DELTA_MS,START_SLOT,BATCH_SIZE,SHREDS,MAX,SIZE,DELTA_SIZE,DATA_SHRED_SIZE,DATA_SHRED_SIZE_DELTA,CPU_USER,CPU_SYSTEM,CPU_IDLE");
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |     #[allow(clippy::too_many_arguments)]
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |     fn emit_stats(
 | 
					
						
							| 
									
										
										
										
											2020-07-28 02:33:27 -07:00
										 |  |  |         time_initial: Instant,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         time_previous: &mut Instant,
 | 
					
						
							|  |  |  |         storage_previous: &mut u64,
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |         data_shred_storage_previous: &mut u64,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         start_slot: u64,
 | 
					
						
							|  |  |  |         batch_size: u64,
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         num_shreds: u64,
 | 
					
						
							|  |  |  |         max_shreds: i64,
 | 
					
						
							| 
									
										
										
										
											2020-01-13 14:13:52 -07:00
										 |  |  |         blockstore: &Blockstore,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         cpu: &CpuStatsInner,
 | 
					
						
							|  |  |  |     ) {
 | 
					
						
							|  |  |  |         let time_now = Instant::now();
 | 
					
						
							| 
									
										
										
										
											2020-01-13 14:13:52 -07:00
										 |  |  |         let storage_now = blockstore.storage_size().unwrap_or(0);
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |         let data_shred_storage_now = blockstore.total_data_shred_storage_size().unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let (cpu_user, cpu_system, cpu_idle) = (cpu.cpu_user, cpu.cpu_system, cpu.cpu_idle);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |         info!(
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |             "{},{},{},{},{},{},{},{},{},{},{:.2},{:.2},{:.2}",
 | 
					
						
							| 
									
										
										
										
											2020-07-28 02:33:27 -07:00
										 |  |  |             time_now.duration_since(time_initial).as_millis(),
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             time_now.duration_since(*time_previous).as_millis(),
 | 
					
						
							|  |  |  |             start_slot,
 | 
					
						
							|  |  |  |             batch_size,
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |             num_shreds,
 | 
					
						
							|  |  |  |             max_shreds,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             storage_now,
 | 
					
						
							|  |  |  |             storage_now as i64 - *storage_previous as i64,
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |             data_shred_storage_now,
 | 
					
						
							|  |  |  |             data_shred_storage_now as i64 - *data_shred_storage_previous as i64,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             cpu_user,
 | 
					
						
							|  |  |  |             cpu_system,
 | 
					
						
							|  |  |  |             cpu_idle,
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *time_previous = time_now;
 | 
					
						
							|  |  |  |         *storage_previous = storage_now;
 | 
					
						
							| 
									
										
										
										
											2022-03-05 16:13:03 -08:00
										 |  |  |         *data_shred_storage_previous = data_shred_storage_now.try_into().unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |     /// Helper function of the benchmark `test_ledger_cleanup_compaction` which
 | 
					
						
							|  |  |  |     /// returns true if the benchmark fails the size limitation check.
 | 
					
						
							|  |  |  |     fn is_exceeded_stop_size_iterations(
 | 
					
						
							|  |  |  |         storage_size: u64,
 | 
					
						
							|  |  |  |         stop_size: u64,
 | 
					
						
							|  |  |  |         exceeded_iterations: &mut u64,
 | 
					
						
							|  |  |  |         iteration_limit: u64,
 | 
					
						
							|  |  |  |         storage_desc: &str,
 | 
					
						
							|  |  |  |     ) -> bool {
 | 
					
						
							|  |  |  |         if stop_size > 0 {
 | 
					
						
							|  |  |  |             if storage_size >= stop_size {
 | 
					
						
							|  |  |  |                 *exceeded_iterations += 1;
 | 
					
						
							|  |  |  |                 warn!(
 | 
					
						
							|  |  |  |                     "{} size {} exceeds the stop size {} for {} times!",
 | 
					
						
							|  |  |  |                     storage_desc, storage_size, stop_size, exceeded_iterations
 | 
					
						
							|  |  |  |                 );
 | 
					
						
							|  |  |  |             } else {
 | 
					
						
							|  |  |  |                 *exceeded_iterations = 0;
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if *exceeded_iterations >= iteration_limit {
 | 
					
						
							|  |  |  |                 error!(
 | 
					
						
							|  |  |  |                     "{} size exceeds the configured limit {} for {} times",
 | 
					
						
							|  |  |  |                     storage_desc, stop_size, exceeded_iterations,
 | 
					
						
							|  |  |  |                 );
 | 
					
						
							|  |  |  |                 return true;
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         false
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-04 23:35:55 -10:00
										 |  |  |     /// The ledger cleanup compaction test which can also be used as a benchmark
 | 
					
						
							|  |  |  |     /// measuring shred insertion performance of the blockstore.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// The benchmark is controlled by several environmental arguments.
 | 
					
						
							|  |  |  |     /// Check [`get_benchmark_config`] for the full list of arguments.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Example command:
 | 
					
						
							|  |  |  |     /// BENCHMARK_SLOTS=1000000 BATCH_SIZE=1 SHREDS_PER_SLOT=25 NUM_WRITERS=8 \
 | 
					
						
							|  |  |  |     /// PRE_GENERATE_DATA=false cargo test --release tests::test_ledger_cleanup_compaction \
 | 
					
						
							|  |  |  |     /// -- --exact --nocapture
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_ledger_cleanup_compaction() {
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |         solana_logger::setup_with("error,ledger_cleanup::tests=info");
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let ledger_path = get_tmp_ledger_path!();
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let config = get_benchmark_config();
 | 
					
						
							| 
									
										
										
										
											2022-02-12 00:43:25 -08:00
										 |  |  |         let mut blockstore = Blockstore::open_with_options(
 | 
					
						
							|  |  |  |             &ledger_path,
 | 
					
						
							|  |  |  |             if config.fifo_compaction {
 | 
					
						
							|  |  |  |                 BlockstoreOptions {
 | 
					
						
							| 
									
										
										
										
											2022-03-18 11:13:35 -07:00
										 |  |  |                     column_options: LedgerColumnOptions {
 | 
					
						
							| 
									
										
										
										
											2022-03-11 15:17:34 -08:00
										 |  |  |                         shred_storage_type: ShredStorageType::RocksFifo(
 | 
					
						
							|  |  |  |                             BlockstoreRocksFifoOptions {
 | 
					
						
							|  |  |  |                                 shred_data_cf_size: config.shred_data_cf_size,
 | 
					
						
							|  |  |  |                                 ..BlockstoreRocksFifoOptions::default()
 | 
					
						
							|  |  |  |                             },
 | 
					
						
							|  |  |  |                         ),
 | 
					
						
							|  |  |  |                     },
 | 
					
						
							| 
									
										
										
										
											2022-02-12 00:43:25 -08:00
										 |  |  |                     ..BlockstoreOptions::default()
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  |             } else {
 | 
					
						
							|  |  |  |                 BlockstoreOptions::default()
 | 
					
						
							|  |  |  |             },
 | 
					
						
							|  |  |  |         )
 | 
					
						
							|  |  |  |         .unwrap();
 | 
					
						
							| 
									
										
										
										
											2021-05-28 16:42:56 +09:00
										 |  |  |         if config.no_compaction {
 | 
					
						
							|  |  |  |             blockstore.set_no_compaction(true);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         let blockstore = Arc::new(blockstore);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |         info!("Benchmark configuration: {:#?}", config);
 | 
					
						
							|  |  |  |         info!("Ledger path: {:?}", &ledger_path);
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let benchmark_slots = config.benchmark_slots;
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         let batch_size_slots = config.batch_size_slots;
 | 
					
						
							| 
									
										
										
										
											2020-03-31 17:21:19 -07:00
										 |  |  |         let max_ledger_shreds = config.max_ledger_shreds;
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         let shreds_per_slot = config.shreds_per_slot;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let stop_size_bytes = config.stop_size_bytes;
 | 
					
						
							|  |  |  |         let stop_size_iterations = config.stop_size_iterations;
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |         let stop_size_cf_data_bytes = config.stop_size_cf_data_bytes;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let pre_generate_data = config.pre_generate_data;
 | 
					
						
							| 
									
										
										
										
											2021-05-28 16:42:56 +09:00
										 |  |  |         let compaction_interval = config.compaction_interval;
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |         let num_writers = config.num_writers;
 | 
					
						
							| 
									
										
										
										
											2022-01-05 21:46:02 -10:00
										 |  |  |         let cleanup_service = config.cleanup_service;
 | 
					
						
							| 
									
										
										
										
											2021-05-28 16:42:56 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         let num_batches = benchmark_slots / batch_size_slots;
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |         let num_shreds_total = benchmark_slots * shreds_per_slot;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-11 02:44:46 -08:00
										 |  |  |         let (sender, receiver) = unbounded();
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let exit = Arc::new(AtomicBool::new(false));
 | 
					
						
							| 
									
										
										
										
											2022-01-05 21:46:02 -10:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let cleaner = if cleanup_service {
 | 
					
						
							|  |  |  |             Some(LedgerCleanupService::new(
 | 
					
						
							|  |  |  |                 receiver,
 | 
					
						
							|  |  |  |                 blockstore.clone(),
 | 
					
						
							|  |  |  |                 max_ledger_shreds,
 | 
					
						
							|  |  |  |                 &exit,
 | 
					
						
							|  |  |  |                 compaction_interval,
 | 
					
						
							|  |  |  |                 None,
 | 
					
						
							|  |  |  |             ))
 | 
					
						
							|  |  |  |         } else {
 | 
					
						
							|  |  |  |             None
 | 
					
						
							|  |  |  |         };
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let exit_cpu = Arc::new(AtomicBool::new(false));
 | 
					
						
							|  |  |  |         let sys = CpuStatsUpdater::new(&exit_cpu);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |         let mut shreds = VecDeque::new();
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if pre_generate_data {
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |             let mut pre_generate_data_timer = Measure::start("Pre-generate data");
 | 
					
						
							|  |  |  |             info!("Pre-generate data ... this may take a while");
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |             for i in 0..num_batches {
 | 
					
						
							|  |  |  |                 let start_slot = i * batch_size_slots;
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                 let (new_shreds, _) =
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |                     make_many_slot_shreds(start_slot, batch_size_slots, shreds_per_slot);
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                 shreds.push_back(new_shreds);
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             }
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |             pre_generate_data_timer.stop();
 | 
					
						
							|  |  |  |             info!("{}", pre_generate_data_timer);
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |         let shreds = Arc::new(Mutex::new(shreds));
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         info!(
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |             "Bench info num_batches: {}, batch size (slots): {}, shreds_per_slot: {}, num_shreds_total: {}",
 | 
					
						
							|  |  |  |             num_batches,
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |             batch_size_slots,
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |             shreds_per_slot,
 | 
					
						
							|  |  |  |             num_shreds_total
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let time_initial = Instant::now();
 | 
					
						
							|  |  |  |         let mut time_previous = time_initial;
 | 
					
						
							|  |  |  |         let mut storage_previous = 0;
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |         let mut data_shred_storage_previous = 0;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let mut stop_size_bytes_exceeded_iterations = 0;
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |         let mut stop_size_cf_data_exceeded_iterations = 0;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         emit_header();
 | 
					
						
							|  |  |  |         emit_stats(
 | 
					
						
							| 
									
										
										
										
											2020-07-28 02:33:27 -07:00
										 |  |  |             time_initial,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             &mut time_previous,
 | 
					
						
							|  |  |  |             &mut storage_previous,
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |             &mut data_shred_storage_previous,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             0,
 | 
					
						
							|  |  |  |             0,
 | 
					
						
							|  |  |  |             0,
 | 
					
						
							|  |  |  |             0,
 | 
					
						
							| 
									
										
										
										
											2020-01-13 14:13:52 -07:00
										 |  |  |             &blockstore,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             &sys.get_stats(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |         let mut insert_threads = vec![];
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |         let insert_exit = Arc::new(AtomicBool::new(false));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         info!("Begin inserting shreds ...");
 | 
					
						
							|  |  |  |         let mut insert_timer = Measure::start("Shred insertion");
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |         let current_batch_id = Arc::new(AtomicU64::new(0));
 | 
					
						
							|  |  |  |         let finished_batch_count = Arc::new(AtomicU64::new(0));
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for i in 0..num_writers {
 | 
					
						
							|  |  |  |             let cloned_insert_exit = insert_exit.clone();
 | 
					
						
							|  |  |  |             let cloned_blockstore = blockstore.clone();
 | 
					
						
							|  |  |  |             let cloned_shreds = shreds.clone();
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |             let shared_batch_id = current_batch_id.clone();
 | 
					
						
							|  |  |  |             let shared_finished_count = finished_batch_count.clone();
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |             let insert_thread = Builder::new()
 | 
					
						
							|  |  |  |                 .name(format!("insert_shreds-{}", i))
 | 
					
						
							|  |  |  |                 .spawn(move || {
 | 
					
						
							|  |  |  |                     let start = Instant::now();
 | 
					
						
							|  |  |  |                     let mut now = Instant::now();
 | 
					
						
							|  |  |  |                     let mut total = 0;
 | 
					
						
							|  |  |  |                     let mut total_batches = 0;
 | 
					
						
							|  |  |  |                     let mut total_inserted_shreds = 0;
 | 
					
						
							|  |  |  |                     let mut num_shreds = 0;
 | 
					
						
							|  |  |  |                     let mut max_speed = 0f32;
 | 
					
						
							|  |  |  |                     let mut min_speed = f32::MAX;
 | 
					
						
							| 
									
										
										
										
											2022-01-04 15:29:43 -10:00
										 |  |  |                     let (mut shreds_with_parent, _) = make_many_slot_shreds(
 | 
					
						
							|  |  |  |                         1, batch_size_slots, shreds_per_slot);
 | 
					
						
							|  |  |  |                     let (first_shreds, _) = make_many_slot_shreds(
 | 
					
						
							|  |  |  |                         0, batch_size_slots, shreds_per_slot);
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                     loop {
 | 
					
						
							| 
									
										
										
										
											2022-01-04 15:29:43 -10:00
										 |  |  |                         let batch_id = shared_batch_id.fetch_add(1, Ordering::Relaxed);
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |                         let start_slot = batch_id * batch_size_slots;
 | 
					
						
							|  |  |  |                         if start_slot >= benchmark_slots {
 | 
					
						
							|  |  |  |                             break;
 | 
					
						
							|  |  |  |                         }
 | 
					
						
							| 
									
										
										
										
											2022-01-04 15:29:43 -10:00
										 |  |  |                         let len = batch_id;
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-04 15:29:43 -10:00
										 |  |  |                         let br = if pre_generate_data {
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                             let mut sl = cloned_shreds.lock().unwrap();
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |                             if let Some(shreds_from_queue) = sl.pop_front() {
 | 
					
						
							| 
									
										
										
										
											2022-01-04 15:29:43 -10:00
										 |  |  |                                 total += shreds_from_queue.len();
 | 
					
						
							|  |  |  |                                 cloned_blockstore.insert_shreds(
 | 
					
						
							|  |  |  |                                     shreds_from_queue, None, false).unwrap()
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |                             } else {
 | 
					
						
							| 
									
										
										
										
											2022-01-04 15:29:43 -10:00
										 |  |  |                                 // If the queue is empty, we're done!
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |                                 break;
 | 
					
						
							|  |  |  |                             }
 | 
					
						
							|  |  |  |                         } else {
 | 
					
						
							| 
									
										
										
										
											2022-01-04 15:29:43 -10:00
										 |  |  |                             let mut slot_id = start_slot;
 | 
					
						
							|  |  |  |                             if slot_id > 0 {
 | 
					
						
							|  |  |  |                                 for shred in shreds_with_parent.iter_mut() {
 | 
					
						
							|  |  |  |                                     shred.set_slot(slot_id);
 | 
					
						
							|  |  |  |                                     if shred.index() as u64 == shreds_per_slot - 1 {
 | 
					
						
							|  |  |  |                                         slot_id += 1;
 | 
					
						
							|  |  |  |                                     }
 | 
					
						
							|  |  |  |                                 }
 | 
					
						
							|  |  |  |                                 total += shreds_with_parent.len();
 | 
					
						
							|  |  |  |                                 cloned_blockstore.insert_shreds(
 | 
					
						
							|  |  |  |                                     shreds_with_parent.clone(), None, false).unwrap()
 | 
					
						
							|  |  |  |                             } else {
 | 
					
						
							|  |  |  |                                 total += first_shreds.len();
 | 
					
						
							|  |  |  |                                 cloned_blockstore.insert_shreds(
 | 
					
						
							|  |  |  |                                     first_shreds.clone(), None, false).unwrap()
 | 
					
						
							|  |  |  |                             }
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                         };
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-04 15:29:43 -10:00
										 |  |  |                         total_batches += 1;
 | 
					
						
							|  |  |  |                         total_inserted_shreds += br.1.len();
 | 
					
						
							|  |  |  |                         num_shreds += br.1.len();
 | 
					
						
							|  |  |  |                         shared_finished_count.fetch_add(1, Ordering::Relaxed);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |                         // as_secs() returns whole number of seconds, so this runs every second
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                         if now.elapsed().as_secs() > 0 {
 | 
					
						
							|  |  |  |                             let shreds_per_second = num_shreds as f32 / now.elapsed().as_secs() as f32;
 | 
					
						
							|  |  |  |                             warn!(
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |                                 "insert-{} tried: {} inserted: {} batches: {} len: {} shreds_per_second: {}",
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                                 i, total, total_inserted_shreds, total_batches, len, shreds_per_second,
 | 
					
						
							|  |  |  |                             );
 | 
					
						
							|  |  |  |                             let average_speed =
 | 
					
						
							|  |  |  |                                 total_inserted_shreds as f32 / start.elapsed().as_secs() as f32;
 | 
					
						
							|  |  |  |                             max_speed = max_speed.max(shreds_per_second);
 | 
					
						
							|  |  |  |                             min_speed = min_speed.min(shreds_per_second);
 | 
					
						
							|  |  |  |                             warn!(
 | 
					
						
							|  |  |  |                                 "highest: {} lowest: {} avg: {}",
 | 
					
						
							|  |  |  |                                 max_speed, min_speed, average_speed
 | 
					
						
							|  |  |  |                             );
 | 
					
						
							|  |  |  |                             now = Instant::now();
 | 
					
						
							|  |  |  |                             num_shreds = 0;
 | 
					
						
							|  |  |  |                         }
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                         if cloned_insert_exit.load(Ordering::Relaxed) {
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |                             if max_speed > 0.0 {
 | 
					
						
							|  |  |  |                                 info!(
 | 
					
						
							|  |  |  |                                     "insert-{} exiting highest shreds/s: {}, lowest shreds/s: {}",
 | 
					
						
							|  |  |  |                                     i, max_speed, min_speed
 | 
					
						
							|  |  |  |                                 );
 | 
					
						
							|  |  |  |                             } else {
 | 
					
						
							|  |  |  |                                 // Not enough time elapsed to sample
 | 
					
						
							|  |  |  |                                 info!(
 | 
					
						
							|  |  |  |                                     "insert-{} exiting",
 | 
					
						
							|  |  |  |                                     i
 | 
					
						
							|  |  |  |                                 );
 | 
					
						
							|  |  |  |                             }
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                             break;
 | 
					
						
							|  |  |  |                         }
 | 
					
						
							| 
									
										
										
										
											2021-02-17 08:59:25 -08:00
										 |  |  |                     }
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |                 })
 | 
					
						
							|  |  |  |                 .unwrap();
 | 
					
						
							|  |  |  |             insert_threads.push(insert_thread);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |         loop {
 | 
					
						
							|  |  |  |             let finished_batch = finished_batch_count.load(Ordering::Relaxed);
 | 
					
						
							|  |  |  |             let finished_slot = (finished_batch + 1) * batch_size_slots - 1;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 21:46:02 -10:00
										 |  |  |             if cleanup_service {
 | 
					
						
							|  |  |  |                 sender.send(finished_slot).unwrap();
 | 
					
						
							|  |  |  |             }
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             emit_stats(
 | 
					
						
							| 
									
										
										
										
											2020-07-28 02:33:27 -07:00
										 |  |  |                 time_initial,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |                 &mut time_previous,
 | 
					
						
							|  |  |  |                 &mut storage_previous,
 | 
					
						
							| 
									
										
										
										
											2022-01-19 19:33:08 -08:00
										 |  |  |                 &mut data_shred_storage_previous,
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |                 finished_slot,
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |                 batch_size_slots,
 | 
					
						
							|  |  |  |                 shreds_per_slot,
 | 
					
						
							| 
									
										
										
										
											2020-03-31 17:21:19 -07:00
										 |  |  |                 max_ledger_shreds as i64,
 | 
					
						
							| 
									
										
										
										
											2020-01-13 14:13:52 -07:00
										 |  |  |                 &blockstore,
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |                 &sys.get_stats(),
 | 
					
						
							|  |  |  |             );
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |             if is_exceeded_stop_size_iterations(
 | 
					
						
							|  |  |  |                 storage_previous,
 | 
					
						
							|  |  |  |                 stop_size_bytes,
 | 
					
						
							|  |  |  |                 &mut stop_size_bytes_exceeded_iterations,
 | 
					
						
							|  |  |  |                 stop_size_iterations,
 | 
					
						
							|  |  |  |                 "Storage",
 | 
					
						
							|  |  |  |             ) {
 | 
					
						
							|  |  |  |                 break;
 | 
					
						
							|  |  |  |             }
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-18 19:35:28 -08:00
										 |  |  |             if is_exceeded_stop_size_iterations(
 | 
					
						
							|  |  |  |                 data_shred_storage_previous,
 | 
					
						
							|  |  |  |                 stop_size_cf_data_bytes,
 | 
					
						
							|  |  |  |                 &mut stop_size_cf_data_exceeded_iterations,
 | 
					
						
							|  |  |  |                 stop_size_iterations,
 | 
					
						
							|  |  |  |                 "cf::ShredData",
 | 
					
						
							|  |  |  |             ) {
 | 
					
						
							|  |  |  |                 break;
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |             }
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if finished_batch >= num_batches {
 | 
					
						
							| 
									
										
										
										
											2021-02-17 08:59:25 -08:00
										 |  |  |                 break;
 | 
					
						
							|  |  |  |             } else {
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |                 thread::sleep(Duration::from_millis(500));
 | 
					
						
							| 
									
										
										
										
											2021-02-17 08:59:25 -08:00
										 |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2021-12-30 20:18:47 -10:00
										 |  |  |         // Send exit signal to stop all the writer threads.
 | 
					
						
							| 
									
										
										
										
											2021-02-17 08:59:25 -08:00
										 |  |  |         insert_exit.store(true, Ordering::Relaxed);
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  |         while let Some(thread) = insert_threads.pop() {
 | 
					
						
							|  |  |  |             thread.join().unwrap();
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |         insert_timer.stop();
 | 
					
						
							| 
									
										
										
										
											2021-12-10 09:42:51 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |         info!(
 | 
					
						
							|  |  |  |             "Done inserting shreds: {}, {} shreds/s",
 | 
					
						
							|  |  |  |             insert_timer,
 | 
					
						
							|  |  |  |             num_shreds_total as f32 / insert_timer.as_s(),
 | 
					
						
							| 
									
										
										
										
											2021-02-17 08:59:25 -08:00
										 |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         let u1 = storage_previous;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-03 12:05:14 -08:00
										 |  |  |         // Poll on some compaction happening
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |         info!("Begin polling for compaction ...");
 | 
					
						
							| 
									
										
										
										
											2020-01-03 12:05:14 -08:00
										 |  |  |         let start_poll = Instant::now();
 | 
					
						
							| 
									
										
										
										
											2020-01-13 14:13:52 -07:00
										 |  |  |         while blockstore.storage_size().unwrap_or(0) >= u1 {
 | 
					
						
							| 
									
										
										
										
											2020-01-03 12:05:14 -08:00
										 |  |  |             if start_poll.elapsed().as_secs() > ROCKSDB_FLUSH_GRACE_PERIOD_SECS {
 | 
					
						
							|  |  |  |                 break;
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |             std::thread::sleep(Duration::from_millis(200));
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |         info!(
 | 
					
						
							|  |  |  |             "Done polling for compaction after {}s",
 | 
					
						
							|  |  |  |             start_poll.elapsed().as_secs_f32()
 | 
					
						
							|  |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let u2 = storage_previous;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         exit.store(true, Ordering::SeqCst);
 | 
					
						
							| 
									
										
										
										
											2022-01-05 21:46:02 -10:00
										 |  |  |         if cleanup_service {
 | 
					
						
							|  |  |  |             cleaner.unwrap().join().unwrap();
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         exit_cpu.store(true, Ordering::SeqCst);
 | 
					
						
							|  |  |  |         sys.join().unwrap();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if config.assert_compaction {
 | 
					
						
							|  |  |  |             assert!(u2 < u1, "expected compaction! pre={},post={}", u1, u2);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-13 14:13:52 -07:00
										 |  |  |         if config.cleanup_blockstore {
 | 
					
						
							|  |  |  |             drop(blockstore);
 | 
					
						
							| 
									
										
										
										
											2021-12-16 11:24:29 -06:00
										 |  |  |             Blockstore::destroy(&ledger_path).expect("Expected successful database destruction");
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-04-15 11:54:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_compaction() {
 | 
					
						
							|  |  |  |         let blockstore_path = get_tmp_ledger_path!();
 | 
					
						
							|  |  |  |         let blockstore = Arc::new(Blockstore::open(&blockstore_path).unwrap());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let n = 10_000;
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         let batch_size_slots = 100;
 | 
					
						
							|  |  |  |         let num_batches = n / batch_size_slots;
 | 
					
						
							| 
									
										
										
										
											2020-04-15 11:54:03 -07:00
										 |  |  |         let max_ledger_shreds = 100;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 23:34:43 -06:00
										 |  |  |         for i in 0..num_batches {
 | 
					
						
							|  |  |  |             let start_slot = i * batch_size_slots;
 | 
					
						
							|  |  |  |             let (shreds, _) = make_many_slot_shreds(start_slot, batch_size_slots, 1);
 | 
					
						
							| 
									
										
										
										
											2020-04-15 11:54:03 -07:00
										 |  |  |             blockstore.insert_shreds(shreds, None, false).unwrap();
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let u1 = blockstore.storage_size().unwrap() as f64;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // send signal to cleanup slots
 | 
					
						
							| 
									
										
										
										
											2022-01-11 02:44:46 -08:00
										 |  |  |         let (sender, receiver) = unbounded();
 | 
					
						
							| 
									
										
										
										
											2020-04-15 11:54:03 -07:00
										 |  |  |         sender.send(n).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-06-04 21:06:06 -07:00
										 |  |  |         let mut last_purge_slot = 0;
 | 
					
						
							| 
									
										
										
										
											2021-02-14 10:16:30 -08:00
										 |  |  |         let highest_compact_slot = Arc::new(AtomicU64::new(0));
 | 
					
						
							| 
									
										
										
										
											2020-04-15 11:54:03 -07:00
										 |  |  |         LedgerCleanupService::cleanup_ledger(
 | 
					
						
							|  |  |  |             &receiver,
 | 
					
						
							|  |  |  |             &blockstore,
 | 
					
						
							|  |  |  |             max_ledger_shreds,
 | 
					
						
							| 
									
										
										
										
											2020-06-04 21:06:06 -07:00
										 |  |  |             &mut last_purge_slot,
 | 
					
						
							| 
									
										
										
										
											2020-04-15 11:54:03 -07:00
										 |  |  |             10,
 | 
					
						
							| 
									
										
										
										
											2021-02-14 10:16:30 -08:00
										 |  |  |             &highest_compact_slot,
 | 
					
						
							| 
									
										
										
										
											2020-04-15 11:54:03 -07:00
										 |  |  |         )
 | 
					
						
							|  |  |  |         .unwrap();
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-14 10:16:30 -08:00
										 |  |  |         let mut compaction_jitter = 0;
 | 
					
						
							|  |  |  |         let mut last_compaction_slot = 0;
 | 
					
						
							|  |  |  |         LedgerCleanupService::compact_ledger(
 | 
					
						
							|  |  |  |             &blockstore,
 | 
					
						
							|  |  |  |             &mut last_compaction_slot,
 | 
					
						
							|  |  |  |             10,
 | 
					
						
							|  |  |  |             &highest_compact_slot,
 | 
					
						
							|  |  |  |             &mut compaction_jitter,
 | 
					
						
							|  |  |  |             None,
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 11:54:03 -07:00
										 |  |  |         thread::sleep(Duration::from_secs(2));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let u2 = blockstore.storage_size().unwrap() as f64;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert!(u2 < u1, "insufficient compaction! pre={},post={}", u1, u2,);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // check that early slots don't exist
 | 
					
						
							|  |  |  |         let max_slot = n - max_ledger_shreds - 1;
 | 
					
						
							|  |  |  |         blockstore
 | 
					
						
							|  |  |  |             .slot_meta_iterator(0)
 | 
					
						
							|  |  |  |             .unwrap()
 | 
					
						
							|  |  |  |             .for_each(|(slot, _)| assert!(slot > max_slot));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         drop(blockstore);
 | 
					
						
							|  |  |  |         Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2019-12-18 18:31:04 -05:00
										 |  |  | }
 |