diff --git a/Cargo.lock b/Cargo.lock index 21344c24..9d8b6185 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "ar_archive_writer" -version = "0.2.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" +checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" dependencies = [ "object", ] @@ -1070,9 +1070,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -1273,9 +1273,8 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" +version = "0.1.29" +source = "git+https://github.com/rust-lang/stacker#017540a8f1f151e6c2e48422571402fbe43d0edb" dependencies = [ "ar_archive_writer", "cc", @@ -1656,8 +1655,7 @@ dependencies = [ [[package]] name = "stacker" version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1f8b29fb42aafcea4edeeb6b2f2d7ecd0d969c48b4cf0d2e64aafc471dd6e59" +source = "git+https://github.com/rust-lang/stacker#017540a8f1f151e6c2e48422571402fbe43d0edb" dependencies = [ "cc", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 85716c86..e1e6b450 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/ferritedb/ferrite" -keywords = ["database", "dbms", "rust", "sql", "storage-engine"] +keywords = ["database", "dbms", "sql", "storage-engine", "oltp"] categories = ["database-implementations", "asynchronous", "concurrency"] [dependencies] @@ -162,3 +162,10 @@ mocking = ["dep:mockall"] # Development and testing features dev = ["server", "mocking"] full = ["cli", "client", "server"] + +# Patch section to fix Windows compilation issues +# Issue: https://github.com/rust-lang/stacker/issues/87 (fixed but not yet released) +[patch.crates-io] +# Override stacker 0.1.22 which has a broken Windows backend +# Using a commit with the fix until a new version is published +stacker = { git = "https://github.com/rust-lang/stacker" } diff --git a/benches/fifo_cache_benchmarking.rs b/benches/fifo_cache_benchmarking.rs index d7d7f8c4..f99bcc7a 100644 --- a/benches/fifo_cache_benchmarking.rs +++ b/benches/fifo_cache_benchmarking.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use std::fs::{OpenOptions, create_dir_all}; use std::hash::Hash; use std::hint::black_box; @@ -636,7 +637,7 @@ fn build_random_ops(total_ops: usize, working_set: usize, insert_every: usize) - ops } -fn prefill_cache( +fn prefill_cache( cache: &mut FIFOCache, keys: &[K], values: &[V], @@ -648,7 +649,7 @@ fn prefill_cache( } } -fn run_ops_once( +fn run_ops_once( cache: &mut FIFOCache, keys: &[K], ops: &[Op], diff --git a/benches/fifo_complexity_benchmarks.rs b/benches/fifo_complexity_benchmarks.rs index 96d8992b..c2cc6072 100644 --- a/benches/fifo_complexity_benchmarks.rs +++ b/benches/fifo_complexity_benchmarks.rs @@ -182,7 +182,7 @@ fn benchmark_eviction_time_complexity(c: &mut Criterion) { cache.insert(key, value); black_box(cache) }, - criterion::BatchSize::SmallInput, + BatchSize::SmallInput, ); }, ); diff --git a/src/storage/disk/async_disk/cache/fifo.rs b/src/storage/disk/async_disk/cache/fifo.rs index 26d229f0..193c7ad9 100644 --- a/src/storage/disk/async_disk/cache/fifo.rs +++ b/src/storage/disk/async_disk/cache/fifo.rs @@ -271,7 +271,9 @@ //! - **Update Semantics**: Updating existing key preserves insertion position //! - **Zero Capacity**: Supported - rejects all insertions -use std::collections::{HashMap, VecDeque}; +use std::cell::Cell; +use std::collections::{HashMap, VecDeque, hash_map}; +use std::fmt::Debug; use std::hash::Hash; use std::sync::Arc; @@ -283,6 +285,15 @@ use crate::storage::disk::async_disk::cache::cache_traits::{CoreCache, FIFOCache /// See module-level documentation for details. #[derive(Debug)] pub struct FIFOCache +where + K: Eq + Hash, +{ + inner: FIFOCacheInner, + metrics: FifoMetrics, +} + +#[derive(Debug)] +pub struct FIFOCacheInner where K: Eq + Hash, { @@ -291,41 +302,193 @@ where insertion_order: VecDeque>, // Tracks the order of insertion } -impl FIFOCache +#[derive(Debug, Default, Clone, Copy)] +pub struct FifoMetricsSnapshot { + pub get_calls: u64, + pub get_hits: u64, + pub get_misses: u64, + + pub insert_calls: u64, + pub insert_updates: u64, + pub insert_new: u64, + + pub evict_calls: u64, + pub evicted_entries: u64, + pub stale_skips: u64, // queue entries popped that were already removed from map + pub evict_scan_steps: u64, // how many pop_front iterations inside eviction + + pub pop_oldest_calls: u64, + pub pop_oldest_found: u64, + pub pop_oldest_empty_or_stale: u64, + + pub peek_oldest_calls: u64, + pub peek_oldest_found: u64, + + pub age_rank_calls: u64, + pub age_rank_found: u64, + pub age_rank_scan_steps: u64, + + // gauges captured at snapshot time + pub cache_len: usize, + pub insertion_order_len: usize, + pub capacity: usize, +} + +#[derive(Debug)] +struct FifoMetrics { + get_calls: u64, + get_hits: u64, + get_misses: u64, + insert_calls: u64, + insert_updates: u64, + insert_new: u64, + evict_calls: u64, + evicted_entries: u64, + stale_skips: u64, + evict_scan_steps: u64, + pop_oldest_calls: u64, + pop_oldest_found: u64, + pop_oldest_empty_or_stale: u64, + peek_oldest_calls: MetricsCell, + peek_oldest_found: MetricsCell, + age_rank_calls: MetricsCell, + age_rank_scan_steps: MetricsCell, + age_rank_found: MetricsCell, +} + +impl FifoMetrics { + fn new() -> FifoMetrics { + Self { + get_calls: 0, + get_hits: 0, + get_misses: 0, + insert_calls: 0, + insert_updates: 0, + insert_new: 0, + evict_calls: 0, + evicted_entries: 0, + stale_skips: 0, + evict_scan_steps: 0, + pop_oldest_calls: 0, + pop_oldest_found: 0, + pop_oldest_empty_or_stale: 0, + peek_oldest_calls: MetricsCell::new(), + peek_oldest_found: MetricsCell::new(), + age_rank_calls: MetricsCell::new(), + age_rank_scan_steps: MetricsCell::new(), + age_rank_found: MetricsCell::new(), + } + } +} + +/// A metrics-only cell. +/// +/// # Safety +/// This type is only safe if all accesses are externally synchronized. +/// In this system, it is protected by an RwLock at a higher level. +#[repr(transparent)] +#[derive(Debug)] +struct MetricsCell(Cell); + +impl MetricsCell { + #[inline] + fn new() -> Self { + Self(Cell::new(0)) + } + + #[inline] + fn get(&self) -> u64 { + self.0.get() + } + + #[inline] + fn incr(&self) { + self.0.set(self.0.get() + 1); + } +} + +// SAFETY: +// All access to MetricsCell is externally synchronized by an RwLock. +// Metrics are observational and do not affect correctness. +unsafe impl Sync for MetricsCell {} +unsafe impl Send for MetricsCell {} + +impl FIFOCacheInner where K: Eq + Hash, { - /// Creates a new FIFO cache with the given capacity - pub fn new(capacity: usize) -> Self { - FIFOCache { + fn new(capacity: usize) -> Self { + Self { capacity, cache: HashMap::with_capacity(capacity), insertion_order: VecDeque::with_capacity(capacity), } } +} + +impl FIFOCache +where + K: Eq + Hash, + V: Debug, +{ + /// Creates a new FIFO cache with the given capacity + pub fn new(capacity: usize) -> Self { + Self { + inner: FIFOCacheInner::new(capacity), + metrics: FifoMetrics::new(), + } + } /// Returns the number of items currently in the cache. /// This is a duplicate of the CoreCache::len() method but provides direct access. pub fn current_size(&self) -> usize { - self.cache.len() + self.inner.cache.len() } /// Returns the insertion order length (may include stale entries). /// This is primarily for testing and debugging purposes. pub fn insertion_order_len(&self) -> usize { - self.insertion_order.len() + self.inner.insertion_order.len() } /// Checks if the internal cache HashMap contains a specific `Arc`. /// This is primarily for testing stale entry behavior. pub fn cache_contains_key(&self, key: &Arc) -> bool { - self.cache.contains_key(key) + self.inner.cache.contains_key(key) } /// Returns an iterator over the insertion order keys. /// This is primarily for testing and debugging purposes. pub fn insertion_order_iter(&self) -> impl Iterator> { - self.insertion_order.iter() + self.inner.insertion_order.iter() + } + + /// Returns snapshot metrics from the cache + /// Can be used to help understand the state of the cache + pub fn metrics_snapshot(&self) -> FifoMetricsSnapshot { + FifoMetricsSnapshot { + get_calls: self.metrics.get_calls, + get_hits: self.metrics.get_hits, + get_misses: self.metrics.get_misses, + insert_calls: self.metrics.insert_calls, + insert_updates: self.metrics.insert_updates, + insert_new: self.metrics.insert_new, + evict_calls: self.metrics.evict_calls, + evicted_entries: self.metrics.evicted_entries, + stale_skips: self.metrics.stale_skips, + evict_scan_steps: self.metrics.evict_scan_steps, + pop_oldest_calls: self.metrics.pop_oldest_calls, + pop_oldest_found: self.metrics.pop_oldest_found, + pop_oldest_empty_or_stale: self.metrics.pop_oldest_empty_or_stale, + peek_oldest_calls: self.metrics.peek_oldest_calls.get(), + peek_oldest_found: self.metrics.peek_oldest_found.get(), + age_rank_calls: self.metrics.age_rank_calls.get(), + age_rank_found: self.metrics.age_rank_found.get(), + age_rank_scan_steps: self.metrics.age_rank_scan_steps.get(), + cache_len: self.inner.cache.len(), + insertion_order_len: self.inner.insertion_order.len(), + capacity: self.inner.capacity, + } } /// Manually removes a key from the cache HashMap only (for testing stale entries). @@ -334,10 +497,10 @@ where #[cfg(test)] pub fn remove_from_cache_only(&mut self, key: &K) -> Option> { // Find the Arc that matches this key - let arc_key = self.cache.keys().find(|k| k.as_ref() == key).cloned(); + let arc_key = self.inner.cache.keys().find(|k| k.as_ref() == key).cloned(); if let Some(arc_key) = arc_key { - self.cache.remove(&arc_key) + self.inner.cache.remove(&arc_key) } else { None } @@ -346,26 +509,31 @@ where /// Returns the current cache HashMap capacity (for testing memory usage). #[cfg(test)] pub fn cache_capacity(&self) -> usize { - self.cache.capacity() + self.inner.cache.capacity() } /// Returns the current insertion order VecDeque capacity (for testing memory usage). #[cfg(test)] pub fn insertion_order_capacity(&self) -> usize { - self.insertion_order.capacity() + self.inner.insertion_order.capacity() } /// Evicts the oldest valid entry from the cache. /// Skips over any stale entries (keys that were lazily deleted). fn evict_oldest(&mut self) { + self.metrics.evict_calls += 1; // Keep popping from the front until we find a valid key or the queue is empty - while let Some(oldest_key) = self.insertion_order.pop_front() { - if self.cache.contains_key(&oldest_key) { + while let Some(oldest_key) = self.inner.insertion_order.pop_front() { + self.metrics.evict_scan_steps += 1; + + if self.inner.cache.contains_key(&oldest_key) { // Found a valid key, remove it and stop - self.cache.remove(&oldest_key); + self.inner.cache.remove(&oldest_key); + self.metrics.evicted_entries += 1; break; } // Skip stale entries (keys that were already removed from the cache) + self.metrics.stale_skips += 1; } } } @@ -373,10 +541,14 @@ where impl CoreCache for FIFOCache where K: Eq + Hash, + V: Debug, { fn insert(&mut self, key: K, value: V) -> Option { + // Update cache metrics + self.metrics.insert_calls += 1; + // If capacity is 0, cannot store anything - if self.capacity == 0 { + if self.inner.capacity == 0 { return None; } @@ -384,93 +556,85 @@ where let value_arc = Arc::new(value); // If the key already exists, update the value - if let std::collections::hash_map::Entry::Occupied(mut e) = - self.cache.entry(key_arc.clone()) - { - return Some(e.insert(value_arc)) - .map(|old_value_arc| { - // Try to unwrap the Arc to get the original value - match Arc::try_unwrap(old_value_arc) { - Ok(old_value) => old_value, - Err(_) => { - // If unwrap fails, there are external references to this Arc - // This violates our cache's ownership model - panic!("Failed to unwrap Arc in insert - there are external references to the value"); - } - } - }); + if let hash_map::Entry::Occupied(mut e) = self.inner.cache.entry(key_arc.clone()) { + self.metrics.insert_updates += 1; + + return Some(e.insert(value_arc)).map(|old_value_arc| { + Arc::try_unwrap(old_value_arc).expect("external Arc references detected") + }); } + self.metrics.insert_new += 1; + // If the cache is at capacity, remove the oldest valid item (FIFO) - if self.cache.len() >= self.capacity { + if self.inner.cache.len() >= self.inner.capacity { self.evict_oldest(); } // Add the new key to the insertion order and cache // Only the Arc pointers are cloned (8 bytes each), not the actual data - self.insertion_order.push_back(key_arc.clone()); - self.cache.insert(key_arc, value_arc); + self.inner.insertion_order.push_back(key_arc.clone()); + self.inner.cache.insert(key_arc, value_arc); None } fn get(&mut self, key: &K) -> Option<&V> { + self.metrics.get_calls += 1; + // In FIFO, getting an item doesn't change its position // Use HashMap's O(1) lookup by leveraging Borrow trait // HashMap, V> supports lookups with &K when K implements Borrow - self.cache.get(key).map(|v| v.as_ref()) + match self.inner.cache.get(key) { + Some(v) => { + self.metrics.get_hits += 1; + Some(v.as_ref()) + }, + None => { + self.metrics.get_misses += 1; + None + }, + } } fn contains(&self, key: &K) -> bool { // Use HashMap's O(1) lookup by leveraging Borrow trait // HashMap, V> supports lookups with &K when K implements Borrow - self.cache.contains_key(key) + self.inner.cache.contains_key(key) } fn len(&self) -> usize { - self.cache.len() + self.inner.cache.len() } fn capacity(&self) -> usize { - self.capacity + self.inner.capacity } fn clear(&mut self) { - self.cache.clear(); - self.insertion_order.clear(); + self.inner.cache.clear(); + self.inner.insertion_order.clear(); } } impl FIFOCacheTrait for FIFOCache where - K: Eq + Hash, + K: Eq + Hash + Debug, + V: Debug, { fn pop_oldest(&mut self) -> Option<(K, V)> { + self.metrics.pop_oldest_calls += 1; + // Use the existing evict_oldest logic but return the key-value pair - while let Some(oldest_key_arc) = self.insertion_order.pop_front() { - if let Some(value_arc) = self.cache.remove(&oldest_key_arc) { + while let Some(oldest_key_arc) = self.inner.insertion_order.pop_front() { + if let Some(value_arc) = self.inner.cache.remove(&oldest_key_arc) { + self.metrics.pop_oldest_found += 1; + // Try to unwrap both Arcs to get the original key and value // This should succeed since we just removed them from the cache - let key = match Arc::try_unwrap(oldest_key_arc) { - Ok(key) => key, - Err(_) => { - // If unwrap fails, it means there are external references to this Arc - // This violates our cache's ownership model and shouldn't happen in normal usage - panic!( - "Failed to unwrap Arc in pop_oldest - there are external references to the key" - ); - }, - }; - - let value = match Arc::try_unwrap(value_arc) { - Ok(value) => value, - Err(_) => { - // If unwrap fails, it means there are external references to this Arc - // This violates our cache's ownership model and shouldn't happen in normal usage - panic!( - "Failed to unwrap Arc in pop_oldest - there are external references to the value" - ); - }, - }; + let key = + Arc::try_unwrap(oldest_key_arc).expect("external Arc references detected"); + let value = + Arc::try_unwrap(value_arc).expect("external Arc references detected"); return Some((key, value)); } @@ -480,9 +644,11 @@ where } fn peek_oldest(&self) -> Option<(&K, &V)> { + self.metrics.peek_oldest_calls.incr(); + // Find the first valid entry in the insertion order - for key_arc in &self.insertion_order { - if let Some(value_arc) = self.cache.get(key_arc) { + for key_arc in &self.inner.insertion_order { + if let Some(value_arc) = self.inner.cache.get(key_arc) { return Some((key_arc.as_ref(), value_arc.as_ref())); } } @@ -504,8 +670,8 @@ where fn age_rank(&self, key: &K) -> Option { // Find position in insertion order, accounting for stale entries let mut rank = 0; - for insertion_key_arc in &self.insertion_order { - if self.cache.contains_key(insertion_key_arc) { + for insertion_key_arc in &self.inner.insertion_order { + if self.inner.cache.contains_key(insertion_key_arc) { if insertion_key_arc.as_ref() == key { return Some(rank); } @@ -518,10 +684,9 @@ where #[cfg(test)] mod tests { - use std::collections::HashSet; - - use super::*; use crate::storage::disk::async_disk::cache::cache_traits::{CoreCache, FIFOCacheTrait}; + use crate::storage::disk::async_disk::cache::fifo::FIFOCache; + use std::collections::HashSet; // Basic FIFO Behavior Tests mod basic_behavior { @@ -708,6 +873,24 @@ mod tests { assert_eq!(cache.peek_oldest(), None); assert_eq!(cache.pop_oldest(), None); } + + #[test] + fn test_basic_fifo_metrics() { + let mut cache = FIFOCache::new(3); + + // Test basic insertion and retrieval + assert_eq!(cache.insert("key1", "value1"), None); + assert_eq!(cache.insert("key2", "value2"), None); + assert_eq!(cache.insert("key3", "value3"), None); + + assert_eq!(cache.get(&"key1"), Some(&"value1")); + assert_eq!(cache.get(&"key2"), Some(&"value2")); + assert_eq!(cache.get(&"key3"), Some(&"value3")); + assert_eq!(cache.len(), 3); + + assert_eq!(cache.metrics.insert_new, 3); + assert_eq!(cache.metrics.get_calls, 3); + } } // Edge Cases Tests diff --git a/src/storage/disk/async_disk/io/io_impl.rs b/src/storage/disk/async_disk/io/io_impl.rs index 51c707a4..1773e43d 100644 --- a/src/storage/disk/async_disk/io/io_impl.rs +++ b/src/storage/disk/async_disk/io/io_impl.rs @@ -682,6 +682,8 @@ mod tests { File::options() .read(true) .write(true) + .create(true) + .truncate(true) .open(&db_path) .await .unwrap(), @@ -690,6 +692,8 @@ mod tests { File::options() .read(true) .write(true) + .create(true) + .truncate(true) .open(&log_path) .await .unwrap(), diff --git a/tests/concurrency/concurrent_transactions.rs b/tests/concurrency/concurrent_transactions.rs index e13ed1d3..fb3c7115 100644 --- a/tests/concurrency/concurrent_transactions.rs +++ b/tests/concurrency/concurrent_transactions.rs @@ -107,6 +107,7 @@ impl ConcurrentTestContext { } } +#[cfg_attr(miri, ignore)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_concurrent_inserts() { let ctx = Arc::new(ConcurrentTestContext::new("concurrent_inserts").await); @@ -183,6 +184,7 @@ async fn test_concurrent_inserts() { ctx.transaction_factory.commit_transaction(txn_ctx).await; } +#[cfg_attr(miri, ignore)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_concurrent_updates() { let ctx = Arc::new(ConcurrentTestContext::new("concurrent_updates").await); @@ -260,6 +262,7 @@ async fn test_concurrent_updates() { ); } +#[cfg_attr(miri, ignore)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_deadlock_detection() { let ctx = Arc::new(ConcurrentTestContext::new("deadlock_detection").await); diff --git a/tests/execution/engine_group_by.rs b/tests/execution/engine_group_by.rs index da2655e7..66f6f969 100644 --- a/tests/execution/engine_group_by.rs +++ b/tests/execution/engine_group_by.rs @@ -620,6 +620,7 @@ async fn test_group_by_empty_table() { assert_eq!(schema.get_columns()[1].get_name(), "count"); } +#[cfg_attr(miri, ignore)] #[tokio::test(flavor = "multi_thread", worker_threads = 5)] async fn test_group_by_performance_large_dataset() { init_test_logger(); diff --git a/tests/execution/engine_join.rs b/tests/execution/engine_join.rs index 1c0d9e68..5708b461 100644 --- a/tests/execution/engine_join.rs +++ b/tests/execution/engine_join.rs @@ -219,6 +219,7 @@ async fn test_full_outer_join_operations() { assert!(success, "Full outer join query execution failed"); } +#[cfg_attr(miri, ignore)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[ignore] // Marked as ignore in original implementation async fn test_cross_join_operations() { diff --git a/tests/recovery/db_instance_recovery.rs b/tests/recovery/db_instance_recovery.rs index 9973802c..7929a1f8 100644 --- a/tests/recovery/db_instance_recovery.rs +++ b/tests/recovery/db_instance_recovery.rs @@ -5,6 +5,7 @@ use ferrite::concurrency::transaction::IsolationLevel; use crate::common::logger::init_test_logger; use crate::common::tempdb::temp_db_config; +#[cfg_attr(miri, ignore)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn db_instance_recovery_integration() { init_test_logger(); diff --git a/tests/storage/fifo_concurrency.rs b/tests/storage/fifo_concurrency.rs index 740ce3e4..0e7fe406 100644 --- a/tests/storage/fifo_concurrency.rs +++ b/tests/storage/fifo_concurrency.rs @@ -1,6 +1,8 @@ // ============================================== // FIFO CONCURRENCY TESTS (integration) // ============================================== +#![cfg(not(miri))] + use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::thread; diff --git a/tests/storage/lfu_concurrency.rs b/tests/storage/lfu_concurrency.rs index 8a220f04..58bc4396 100644 --- a/tests/storage/lfu_concurrency.rs +++ b/tests/storage/lfu_concurrency.rs @@ -1,6 +1,7 @@ // ============================================== // LFU CONCURRENCY TESTS (integration) // ============================================== +#![cfg(not(miri))] use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; diff --git a/tests/storage/lfu_performance.rs b/tests/storage/lfu_performance.rs index 0a0e494d..fd9fe5a9 100644 --- a/tests/storage/lfu_performance.rs +++ b/tests/storage/lfu_performance.rs @@ -1,6 +1,8 @@ // ============================================== // LFU PERFORMANCE TESTS (integration) // ============================================== +#![cfg(not(miri))] + use std::time::{Duration, Instant}; use ferrite::storage::disk::async_disk::cache::cache_traits::{ diff --git a/tests/storage/lru_concurrency.rs b/tests/storage/lru_concurrency.rs index 08a5aa4c..373006ee 100644 --- a/tests/storage/lru_concurrency.rs +++ b/tests/storage/lru_concurrency.rs @@ -1,3 +1,8 @@ +// ============================================== +// LRU CONCURRENCY TESTS (integration) +// ============================================== +#![cfg(not(miri))] + use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::thread; @@ -5,10 +10,6 @@ use std::time::{Duration, Instant}; use ferrite::storage::disk::async_disk::cache::lru::ConcurrentLRUCache; -// ============================================== -// LRU CONCURRENCY TESTS (integration) -// ============================================== - mod thread_safety { use super::*; diff --git a/tests/storage/lru_k_concurrency.rs b/tests/storage/lru_k_concurrency.rs index e9557730..aa4b3c1e 100644 --- a/tests/storage/lru_k_concurrency.rs +++ b/tests/storage/lru_k_concurrency.rs @@ -1,3 +1,8 @@ +// ============================================== +// LRU-K CONCURRENCY TESTS (integration) +// ============================================== +#![cfg(not(miri))] + use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::thread; @@ -6,10 +11,6 @@ use std::time::Duration; use ferrite::storage::disk::async_disk::cache::cache_traits::{CoreCache, LRUKCacheTrait}; use ferrite::storage::disk::async_disk::cache::lru_k::LRUKCache; -// ============================================== -// LRU-K CONCURRENCY TESTS (integration) -// ============================================== - // Thread Safety Tests mod thread_safety { use super::*; diff --git a/tests/storage/lru_k_performance.rs b/tests/storage/lru_k_performance.rs index 00d1a595..f1222316 100644 --- a/tests/storage/lru_k_performance.rs +++ b/tests/storage/lru_k_performance.rs @@ -1,6 +1,7 @@ // ============================================== // LRU-K PERFORMANCE TESTS (integration) // ============================================== +#![cfg(not(miri))] // Lookup Performance Tests mod lookup_performance { diff --git a/tests/storage/lru_performance.rs b/tests/storage/lru_performance.rs index a51ce68c..91daab85 100644 --- a/tests/storage/lru_performance.rs +++ b/tests/storage/lru_performance.rs @@ -1,6 +1,7 @@ // ============================================== // LRU PERFORMANCE TESTS (integration) // ============================================== +#![cfg(not(miri))] mod lookup_performance { #[test]