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}