Skip to content

Instantly share code, notes, and snippets.

@divi255

divi255/main.rs Secret

Created August 14, 2021 19:46
Show Gist options
  • Save divi255/a464b1024e06aa9f85578137f33acf20 to your computer and use it in GitHub Desktop.
Save divi255/a464b1024e06aa9f85578137f33acf20 to your computer and use it in GitHub Desktop.
Test Rust shared resource guards
#[macro_use]
extern crate lazy_static;
use std::cell::RefCell;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Instant;
use tokio::sync::Mutex;
use tokio::sync::RwLock;
static X: AtomicU64 = AtomicU64::new(0);
lazy_static! {
static ref X_MUTEX: Mutex<u64> = Mutex::new(0);
static ref X_RWLOCK: RwLock<u64> = RwLock::new(0);
static ref S_MUTEX: std::sync::Mutex<u64> = std::sync::Mutex::new(0);
static ref S_RWLOCK: std::sync::RwLock<u64> = std::sync::RwLock::new(0);
}
thread_local! {
static S_CELL: RefCell<u64> = RefCell::new(0);
}
macro_rules! print_stat {
($title: expr, $duration: expr) => {
println!(
"{} spent: {} sec",
$title,
$duration.as_nanos() as f64 / 1000_000_000.0
);
};
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut c = 0;
for mutable in 0..2 {
let n = 100_000_000;
if mutable == 0 {
println!("WRITE");
} else {
println!("READ");
}
// local
let start = Instant::now();
for _ in 0..n {
if mutable == 0 {
c += 1;
} else {
let _a = c;
}
}
let spent = Instant::now() - start;
assert_eq!(c, n);
print_stat!("LOCAL", spent);
// atomic
let start = Instant::now();
for _ in 0..n {
let mut a = X.load(Ordering::SeqCst);
if mutable == 0 {
a += 1;
X.store(a, Ordering::SeqCst);
}
}
let spent = Instant::now() - start;
assert_eq!(X.load(Ordering::SeqCst), n);
print_stat!("ATOMIC", spent);
// mutex
let start = Instant::now();
for _ in 0..n {
let mut a = X_MUTEX.lock().await;
if mutable == 0 {
*a += 1;
}
}
let spent = Instant::now() - start;
assert_eq!(*X_MUTEX.lock().await, n);
print_stat!("TOKIO MUTEX", spent);
// rwlock
let start = Instant::now();
for _ in 0..n {
if mutable == 0 {
let mut a = X_RWLOCK.write().await;
*a += 1;
} else {
let _a = X_RWLOCK.read().await;
}
}
let spent = Instant::now() - start;
assert_eq!(*X_RWLOCK.read().await, n);
print_stat!("TOKIO RWLOCK", spent);
// s mutex
let start = Instant::now();
for _ in 0..n {
let mut a = S_MUTEX.lock().unwrap();
if mutable == 0 {
*a += 1;
}
}
let spent = Instant::now() - start;
assert_eq!(*S_MUTEX.lock().unwrap(), n);
print_stat!("SYNC MUTEX", spent);
// s rwlock
let start = Instant::now();
for _ in 0..n {
if mutable == 0 {
let mut a = S_RWLOCK.write().unwrap();
*a += 1;
} else {
let _a = S_RWLOCK.read().unwrap();
}
}
let spent = Instant::now() - start;
assert_eq!(*S_RWLOCK.write().unwrap(), n);
print_stat!("SYNC RWLOCK", spent);
// s refcell
let start = Instant::now();
for _ in 0..n {
if mutable == 0 {
S_CELL.with(|cell| {
let mut a = cell.borrow_mut();
*a += 1;
});
} else {
S_CELL.with(|cell| {
let _a = cell.borrow();
});
}
}
let spent = Instant::now() - start;
assert_eq!(
S_CELL.with(|cell| {
let x = cell.borrow();
*x
}),
n
);
print_stat!("SYNC REFCELL", spent);
}
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment