sync_utils/
cpu.rs

1extern crate lazy_static;
2extern crate num_cpus;
3use super::bithacks::round_up_to_power2;
4
5const DEFAULT_CPUS: u32 = 4;
6
7/// Determine the right sharding by cpu,
8/// and minimise the cost of hashing function of remainder calculation.
9///
10/// ## example:
11///
12/// ``` rust
13/// use sync_utils::cpu::CpuShard;
14/// let cpu_shard = CpuShard::new(Some(32));
15/// let mut caches = Vec::with_capacity(cpu_shard.shards() as usize);
16/// for _i in 0..caches.capacity() {
17///     caches = Cache::new();
18///     caches.push(cache);
19/// }
20/// let file_id = 111;
21/// let shard_id = file_id & (caches.len() - 1 );
22/// caches[shard_id].get(file_id);
23/// ```
24pub struct CpuShard(u32, u32);
25
26impl CpuShard {
27    /// `max_shard_limit`: limit the maximum shard number when cpu_num is too large.
28    #[inline]
29    pub fn new(max_shard_limit: Option<u32>) -> Self {
30        let mut cpus = num_cpus::get() as u32;
31        if cpus < DEFAULT_CPUS {
32            cpus = DEFAULT_CPUS;
33        }
34        if let Some(limit) = max_shard_limit {
35            if cpus > limit {
36                cpus = limit;
37            }
38        }
39        let (shard, shift) = round_up_to_power2(cpus);
40        Self(shard, shift)
41    }
42
43    /// return the shard number. ( shards() == 1<<shift() )
44    #[inline]
45    pub fn shards(&self) -> u32 {
46        self.0
47    }
48
49    /// return the shift ( shards() == 1<<shift() )
50    #[inline]
51    pub fn shift(&self) -> u32 {
52        self.1
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn test_static_shards() {
62        let cpu_shard = CpuShard::new(None);
63        let cpus = num_cpus::get();
64        println!("cpus={}", cpus);
65        if cpus <= 4 {
66            assert_eq!(cpu_shard.shards(), 4);
67            assert_eq!(cpu_shard.shift(), 2);
68        } else if cpus <= 8 {
69            assert_eq!(cpu_shard.shards(), 8);
70            assert_eq!(cpu_shard.shift(), 3);
71        }
72    }
73
74    #[test]
75    fn test_shards_limit() {
76        let cpu_shard = CpuShard::new(Some(2));
77        assert_eq!(cpu_shard.shards(), 2);
78        assert_eq!(cpu_shard.shift(), 1);
79    }
80}