Skip to content

Instantly share code, notes, and snippets.

@songzhi
Last active August 23, 2021 08:37
Show Gist options
  • Save songzhi/2ee513c175905e6dcb3fb9d12036128b to your computer and use it in GitHub Desktop.
Save songzhi/2ee513c175905e6dcb3fb9d12036128b to your computer and use it in GitHub Desktop.
Distributed Cache Line Counter
//! 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