Last active
August 23, 2021 08:37
-
-
Save songzhi/2ee513c175905e6dcb3fb9d12036128b to your computer and use it in GitHub Desktop.
Distributed Cache Line Counter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! Inspired by [this](http://concurrencyfreaks.blogspot.com/2013/08/concurrency-pattern-distributed-cache.html). | |
use cache_padded::CachePadded; | |
use std::sync::atomic::{AtomicUsize, Ordering}; | |
pub struct DistributedCacheLineCounter { | |
counters: Box<[CachePadded<AtomicUsize>]>, | |
num_counters: usize, | |
} | |
impl Default for DistributedCacheLineCounter { | |
fn default() -> Self { | |
let num_counters = num_cpus::get() * 3; | |
let mut counters = Vec::with_capacity(num_counters); | |
counters.resize_with(num_counters, || CachePadded::new(AtomicUsize::new(0))); | |
let counters = counters.into_boxed_slice(); | |
Self { | |
counters, | |
num_counters, | |
} | |
} | |
} | |
impl DistributedCacheLineCounter { | |
pub fn new() -> Self { | |
Self::default() | |
} | |
pub fn increment(&self) { | |
self.counters[self.hashed_tid()].fetch_add(1, Ordering::Relaxed); | |
} | |
pub fn get(&self) -> usize { | |
self.counters | |
.iter() | |
.fold(0usize, |acc, x| acc + x.load(Ordering::Relaxed)) | |
} | |
pub fn clear(&self) { | |
for counter in self.counters.iter() { | |
counter.store(0, Ordering::Relaxed); | |
} | |
} | |
fn hashed_tid(&self) -> usize { | |
let mut x = std::thread::current().id().as_u64().get(); | |
x ^= x << 21; | |
x ^= x >> 35; | |
x ^= x << 4; | |
x as usize % self.num_counters | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment