Skip to main content

priority_lfu/
builder.rs

1use crate::cache::Cache;
2
3/// Builder for configuring a Cache.
4///
5/// # Example
6///
7/// ```
8/// use priority_lfu::CacheBuilder;
9///
10/// let cache = CacheBuilder::new(1024 * 1024 * 512) // 512 MB
11///     .shards(128)
12///     .build();
13/// ```
14///
15/// # Automatic Shard Scaling
16///
17/// By default, the cache uses up to 64 shards, but automatically scales down
18/// for smaller caches to ensure each shard has at least 4KB capacity. This
19/// prevents premature eviction due to uneven hash distribution.
20///
21/// - 256KB+ capacity: 64 shards (4KB+ per shard)
22/// - 64KB capacity: 16 shards (4KB per shard)
23/// - 4KB capacity: 1 shard (4KB per shard)
24///
25/// You can override this with [`shards()`], but the count may still be reduced
26/// if the capacity is too small to support the requested number.
27pub struct CacheBuilder {
28	max_size: usize,
29	shard_count: Option<usize>,
30}
31
32impl CacheBuilder {
33	/// Create a new builder with the given maximum size in bytes.
34	pub fn new(max_size_bytes: usize) -> Self {
35		Self {
36			max_size: max_size_bytes,
37			shard_count: None,
38		}
39	}
40
41	/// Set the number of shards.
42	///
43	/// More shards reduce contention but increase memory overhead.
44	/// Will be rounded up to the next power of 2.
45	///
46	/// **Note**: The shard count may be reduced if the capacity is too small to
47	/// support the requested number of shards (minimum 4KB per shard). This prevents
48	/// premature eviction due to uneven hash distribution.
49	///
50	/// Default: up to 64 shards, scaled based on capacity
51	pub fn shards(mut self, count: usize) -> Self {
52		self.shard_count = Some(count);
53		self
54	}
55
56	/// Build the cache with the configured settings.
57	pub fn build(self) -> Cache {
58		match self.shard_count {
59			Some(count) => Cache::with_shards(self.max_size, count),
60			None => Cache::new(self.max_size),
61		}
62	}
63}
64
65impl Default for CacheBuilder {
66	/// Create a builder with default settings and 1GB capacity.
67	fn default() -> Self {
68		Self::new(1024 * 1024 * 1024) // 1 GB
69	}
70}
71
72#[cfg(test)]
73mod tests {
74	use super::*;
75
76	#[test]
77	fn test_builder_default() {
78		let cache = CacheBuilder::new(1024).build();
79		assert!(cache.is_empty());
80	}
81
82	#[test]
83	fn test_builder_with_shards() {
84		let cache = CacheBuilder::new(1024).shards(32).build();
85		assert!(cache.is_empty());
86	}
87
88	#[test]
89	fn test_builder_full_config() {
90		let cache = CacheBuilder::new(10240).shards(32).build();
91
92		assert!(cache.is_empty());
93		assert_eq!(cache.size(), 0);
94	}
95}