Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
335
third-party/vendor/arc-swap/benches/background.rs
vendored
Normal file
335
third-party/vendor/arc-swap/benches/background.rs
vendored
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use arc_swap::{ArcSwap, ArcSwapOption, Cache};
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use crossbeam_utils::thread;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
// Mostly a leftover from earlier times, but it still allows one to tweak the number of ops per one
|
||||
// iteration of the benchmark easily, so it's left in here.
|
||||
const ITERS: usize = 1;
|
||||
|
||||
macro_rules! method {
|
||||
($c: expr, $name:ident) => {{
|
||||
let mut g = $c.benchmark_group(&format!("{}_{}", NAME, stringify!($name)));
|
||||
noise(&mut g, "r1", 1, 0, 0, $name);
|
||||
noise(&mut g, "r3", 3, 0, 0, $name);
|
||||
noise(&mut g, "l1", 0, 1, 0, $name);
|
||||
noise(&mut g, "l3", 0, 3, 0, $name);
|
||||
noise(&mut g, "rw", 1, 0, 1, $name);
|
||||
noise(&mut g, "lw", 0, 1, 1, $name);
|
||||
noise(&mut g, "w2", 0, 0, 2, $name);
|
||||
g.bench_function("uncontended", |b| b.iter($name));
|
||||
g.finish();
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! noise {
|
||||
() => {
|
||||
use criterion::measurement::Measurement;
|
||||
use criterion::BenchmarkGroup;
|
||||
|
||||
use super::{thread, Arc, AtomicBool, Ordering, ITERS};
|
||||
|
||||
fn noise<M: Measurement, F: Fn()>(
|
||||
g: &mut BenchmarkGroup<M>,
|
||||
name: &str,
|
||||
readers: usize,
|
||||
leasers: usize,
|
||||
writers: usize,
|
||||
f: F,
|
||||
) {
|
||||
let flag = Arc::new(AtomicBool::new(true));
|
||||
thread::scope(|s| {
|
||||
for _ in 0..readers {
|
||||
s.spawn(|_| {
|
||||
while flag.load(Ordering::Relaxed) {
|
||||
read();
|
||||
}
|
||||
});
|
||||
}
|
||||
for _ in 0..leasers {
|
||||
s.spawn(|_| {
|
||||
while flag.load(Ordering::Relaxed) {
|
||||
lease();
|
||||
}
|
||||
});
|
||||
}
|
||||
for _ in 0..writers {
|
||||
s.spawn(|_| {
|
||||
while flag.load(Ordering::Relaxed) {
|
||||
write();
|
||||
}
|
||||
});
|
||||
}
|
||||
g.bench_function(name, |b| b.iter(&f));
|
||||
flag.store(false, Ordering::Relaxed);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! strategy {
|
||||
($name: ident, $type: ty) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
|
||||
static A: Lazy<$type> = Lazy::new(|| <$type>::from_pointee(0));
|
||||
const NAME: &str = stringify!($name);
|
||||
|
||||
fn lease() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(**A.load());
|
||||
}
|
||||
}
|
||||
|
||||
// Leases kind of degrade in performance if there are multiple on the same thread.
|
||||
fn four_leases() {
|
||||
for _ in 0..ITERS {
|
||||
let l1 = A.load();
|
||||
let l2 = A.load();
|
||||
let l3 = A.load();
|
||||
let l4 = A.load();
|
||||
black_box((**l1, **l2, **l3, **l4));
|
||||
}
|
||||
}
|
||||
|
||||
fn read() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(A.load_full());
|
||||
}
|
||||
}
|
||||
|
||||
fn write() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(A.store(Arc::new(0)));
|
||||
}
|
||||
}
|
||||
|
||||
noise!();
|
||||
|
||||
pub fn run_all(c: &mut Criterion) {
|
||||
method!(c, read);
|
||||
method!(c, write);
|
||||
method!(c, lease);
|
||||
method!(c, four_leases);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
strategy!(arc_swap_b, ArcSwap::<usize>);
|
||||
|
||||
mod arc_swap_option {
|
||||
use super::{black_box, ArcSwapOption, Criterion, Lazy};
|
||||
|
||||
static A: Lazy<ArcSwapOption<usize>> = Lazy::new(|| ArcSwapOption::from(None));
|
||||
const NAME: &str = "arc_swap_option";
|
||||
|
||||
fn lease() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(A.load().as_ref().map(|l| **l).unwrap_or(0));
|
||||
}
|
||||
}
|
||||
|
||||
fn read() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(A.load_full().map(|a| -> usize { *a }).unwrap_or(0));
|
||||
}
|
||||
}
|
||||
|
||||
fn write() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(A.store(Some(Arc::new(0))));
|
||||
}
|
||||
}
|
||||
|
||||
noise!();
|
||||
|
||||
pub fn run_all(c: &mut Criterion) {
|
||||
method!(c, read);
|
||||
method!(c, write);
|
||||
method!(c, lease);
|
||||
}
|
||||
}
|
||||
|
||||
mod arc_swap_cached {
|
||||
use super::{black_box, ArcSwap, Cache, Criterion, Lazy};
|
||||
|
||||
static A: Lazy<ArcSwap<usize>> = Lazy::new(|| ArcSwap::from_pointee(0));
|
||||
const NAME: &str = "arc_swap_cached";
|
||||
|
||||
fn read() {
|
||||
let mut cache = Cache::from(&A as &ArcSwap<usize>);
|
||||
for _ in 0..ITERS {
|
||||
black_box(Arc::clone(cache.load()));
|
||||
}
|
||||
}
|
||||
|
||||
fn lease() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(**A.load());
|
||||
}
|
||||
}
|
||||
|
||||
fn write() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(A.store(Arc::new(0)));
|
||||
}
|
||||
}
|
||||
|
||||
noise!();
|
||||
|
||||
pub fn run_all(c: &mut Criterion) {
|
||||
method!(c, read);
|
||||
method!(c, write);
|
||||
}
|
||||
}
|
||||
|
||||
mod mutex {
|
||||
use super::{black_box, Criterion, Lazy, Mutex};
|
||||
|
||||
static M: Lazy<Mutex<Arc<usize>>> = Lazy::new(|| Mutex::new(Arc::new(0)));
|
||||
const NAME: &str = "mutex";
|
||||
|
||||
fn lease() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(**M.lock().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
fn read() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(Arc::clone(&*M.lock().unwrap()));
|
||||
}
|
||||
}
|
||||
|
||||
fn write() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(*M.lock().unwrap() = Arc::new(42));
|
||||
}
|
||||
}
|
||||
|
||||
noise!();
|
||||
|
||||
pub fn run_all(c: &mut Criterion) {
|
||||
method!(c, read);
|
||||
method!(c, write);
|
||||
}
|
||||
}
|
||||
|
||||
mod parking_mutex {
|
||||
use parking_lot::Mutex as ParkingMutex;
|
||||
|
||||
use super::{black_box, Criterion, Lazy};
|
||||
|
||||
static M: Lazy<ParkingMutex<Arc<usize>>> = Lazy::new(|| ParkingMutex::new(Arc::new(0)));
|
||||
const NAME: &str = "parking_mutex";
|
||||
|
||||
fn lease() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(**M.lock());
|
||||
}
|
||||
}
|
||||
|
||||
fn read() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(Arc::clone(&*M.lock()));
|
||||
}
|
||||
}
|
||||
|
||||
fn write() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(*M.lock() = Arc::new(42));
|
||||
}
|
||||
}
|
||||
|
||||
noise!();
|
||||
|
||||
pub fn run_all(c: &mut Criterion) {
|
||||
method!(c, read);
|
||||
method!(c, write);
|
||||
}
|
||||
}
|
||||
|
||||
mod rwlock {
|
||||
use std::sync::RwLock;
|
||||
|
||||
use super::{black_box, Criterion, Lazy};
|
||||
|
||||
static L: Lazy<RwLock<Arc<usize>>> = Lazy::new(|| RwLock::new(Arc::new(0)));
|
||||
const NAME: &str = "rwlock";
|
||||
|
||||
fn lease() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(**L.read().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
fn read() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(Arc::clone(&*L.read().unwrap()));
|
||||
}
|
||||
}
|
||||
|
||||
fn write() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(*L.write().unwrap() = Arc::new(42));
|
||||
}
|
||||
}
|
||||
|
||||
noise!();
|
||||
|
||||
pub fn run_all(c: &mut Criterion) {
|
||||
method!(c, read);
|
||||
method!(c, write);
|
||||
}
|
||||
}
|
||||
|
||||
mod parking_rwlock {
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use super::{black_box, Criterion, Lazy};
|
||||
|
||||
static L: Lazy<RwLock<Arc<usize>>> = Lazy::new(|| RwLock::new(Arc::new(0)));
|
||||
const NAME: &str = "parking_rwlock";
|
||||
|
||||
fn lease() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(**L.read());
|
||||
}
|
||||
}
|
||||
|
||||
fn read() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(Arc::clone(&*L.read()));
|
||||
}
|
||||
}
|
||||
|
||||
fn write() {
|
||||
for _ in 0..ITERS {
|
||||
black_box(*L.write() = Arc::new(42));
|
||||
}
|
||||
}
|
||||
|
||||
noise!();
|
||||
|
||||
pub fn run_all(c: &mut Criterion) {
|
||||
method!(c, read);
|
||||
method!(c, write);
|
||||
}
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
arc_swap_b::run_all,
|
||||
arc_swap_option::run_all,
|
||||
arc_swap_cached::run_all,
|
||||
mutex::run_all,
|
||||
parking_mutex::run_all,
|
||||
rwlock::run_all,
|
||||
parking_rwlock::run_all,
|
||||
);
|
||||
criterion_main!(benches);
|
||||
130
third-party/vendor/arc-swap/benches/int-access.rs
vendored
Normal file
130
third-party/vendor/arc-swap/benches/int-access.rs
vendored
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
//! These are very minimal benchmarks ‒ reading and writing an integer shared in
|
||||
//! different ways. You can compare the times and see the characteristics.
|
||||
|
||||
use std::io::{self, Write};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::time::Instant;
|
||||
|
||||
use arc_swap::ArcSwap;
|
||||
use criterion::black_box;
|
||||
use crossbeam_utils::thread;
|
||||
|
||||
fn test_run<R, W>(
|
||||
name: &str,
|
||||
read_threads: usize,
|
||||
write_threads: usize,
|
||||
iterations: usize,
|
||||
r: R,
|
||||
w: W,
|
||||
) where
|
||||
R: Fn() -> usize + Sync + Send,
|
||||
W: Fn(usize) + Sync + Send,
|
||||
{
|
||||
print!(
|
||||
"{:20} ({} + {}) x {}: ",
|
||||
name, read_threads, write_threads, iterations
|
||||
);
|
||||
io::stdout().flush().unwrap();
|
||||
let before = Instant::now();
|
||||
thread::scope(|scope| {
|
||||
for _ in 0..read_threads {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..iterations {
|
||||
black_box(r());
|
||||
}
|
||||
});
|
||||
}
|
||||
for _ in 0..write_threads {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..iterations {
|
||||
black_box(w(i));
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
let duration = Instant::now() - before;
|
||||
println!(
|
||||
"{:03}.{:03}s",
|
||||
duration.as_secs(),
|
||||
duration.subsec_nanos() / 100_000
|
||||
);
|
||||
}
|
||||
|
||||
fn test_round<R, W>(name: &str, iterations: usize, r: R, w: W)
|
||||
where
|
||||
R: Fn() -> usize + Sync + Send,
|
||||
W: Fn(usize) + Sync + Send,
|
||||
{
|
||||
test_run(name, 1, 0, iterations, &r, &w);
|
||||
test_run(name, 2, 0, iterations, &r, &w);
|
||||
test_run(name, 4, 0, iterations, &r, &w);
|
||||
test_run(name, 8, 0, iterations, &r, &w);
|
||||
test_run(name, 1, 1, iterations, &r, &w);
|
||||
test_run(name, 4, 1, iterations, &r, &w);
|
||||
test_run(name, 4, 2, iterations, &r, &w);
|
||||
test_run(name, 4, 4, iterations, &r, &w);
|
||||
test_run(name, 8, 1, iterations, &r, &w);
|
||||
test_run(name, 8, 2, iterations, &r, &w);
|
||||
test_run(name, 8, 4, iterations, &r, &w);
|
||||
test_run(name, 0, 1, iterations, &r, &w);
|
||||
test_run(name, 0, 4, iterations, &r, &w);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mutex = Mutex::new(42);
|
||||
test_round(
|
||||
"mutex",
|
||||
100_000,
|
||||
|| *mutex.lock().unwrap(),
|
||||
|i| *mutex.lock().unwrap() = i,
|
||||
);
|
||||
let mutex = Mutex::new(Arc::new(42));
|
||||
test_round(
|
||||
"mutex-arc",
|
||||
100_000,
|
||||
|| **mutex.lock().unwrap(),
|
||||
|i| *mutex.lock().unwrap() = Arc::new(i),
|
||||
);
|
||||
test_round(
|
||||
"mutex-arc-clone",
|
||||
100_000,
|
||||
|| *Arc::clone(&*mutex.lock().unwrap()),
|
||||
|i| *mutex.lock().unwrap() = Arc::new(i),
|
||||
);
|
||||
let lock = RwLock::new(42);
|
||||
test_round(
|
||||
"rw",
|
||||
100_000,
|
||||
|| *lock.read().unwrap(),
|
||||
|i| *lock.write().unwrap() = i,
|
||||
);
|
||||
let lock = RwLock::new(Arc::new(42));
|
||||
test_round(
|
||||
"rw-arc",
|
||||
100_000,
|
||||
|| **lock.read().unwrap(),
|
||||
|i| *lock.write().unwrap() = Arc::new(i),
|
||||
);
|
||||
test_round(
|
||||
"rw-arc-clone",
|
||||
100_000,
|
||||
|| *Arc::clone(&*lock.read().unwrap()),
|
||||
|i| *lock.write().unwrap() = Arc::new(i),
|
||||
);
|
||||
let arc = ArcSwap::from(Arc::new(42));
|
||||
test_round(
|
||||
"arc-load-store",
|
||||
100_000,
|
||||
|| **arc.load(),
|
||||
|i| arc.store(Arc::new(i)),
|
||||
);
|
||||
test_round(
|
||||
"arc-rcu",
|
||||
100_000,
|
||||
|| *arc.load_full(),
|
||||
|i| {
|
||||
arc.rcu(|_| Arc::new(i));
|
||||
},
|
||||
);
|
||||
}
|
||||
113
third-party/vendor/arc-swap/benches/track.rs
vendored
Normal file
113
third-party/vendor/arc-swap/benches/track.rs
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
//! Benchmarks to track basic performance across changes.
|
||||
//!
|
||||
//! Slightly based on the <background.rs> benchmarks, but simplified and stripped down to run
|
||||
//! reasonably fast.
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use arc_swap::access::{Access, Map};
|
||||
use arc_swap::cache::Cache;
|
||||
use arc_swap::ArcSwap;
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use crossbeam_utils::thread;
|
||||
|
||||
/// Execute a group of measurements
|
||||
///
|
||||
/// It expects any kind of „environment“ is already in place for it.
|
||||
fn batch(c: &mut Criterion, name: &str, shared_number: &ArcSwap<usize>) {
|
||||
let mut g = c.benchmark_group(name);
|
||||
|
||||
g.bench_function("load", |b| {
|
||||
b.iter(|| {
|
||||
black_box(shared_number.load());
|
||||
})
|
||||
});
|
||||
g.bench_function("load_full", |b| {
|
||||
b.iter(|| {
|
||||
black_box(shared_number.load_full());
|
||||
})
|
||||
});
|
||||
g.bench_function("load_many", |b| {
|
||||
// Here we simulate running out of the debt slots scenario
|
||||
const MANY: usize = 32;
|
||||
let mut guards = Vec::with_capacity(MANY);
|
||||
b.iter(|| {
|
||||
guards.push(black_box(shared_number.load()));
|
||||
if guards.len() == MANY {
|
||||
guards.clear();
|
||||
}
|
||||
})
|
||||
});
|
||||
g.bench_function("store", |b| {
|
||||
b.iter(|| {
|
||||
black_box(shared_number.store(Arc::new(42)));
|
||||
})
|
||||
});
|
||||
g.bench_function("cache", |b| {
|
||||
let mut cache = Cache::new(shared_number);
|
||||
b.iter(|| {
|
||||
black_box(cache.load());
|
||||
})
|
||||
});
|
||||
|
||||
g.finish();
|
||||
}
|
||||
|
||||
fn with_background<F: Fn(&ArcSwap<usize>) + Sync>(
|
||||
c: &mut Criterion,
|
||||
name: &str,
|
||||
cnt: usize,
|
||||
noise: F,
|
||||
) {
|
||||
let stop = AtomicBool::new(false);
|
||||
let shared_number = ArcSwap::from_pointee(42);
|
||||
thread::scope(|s| {
|
||||
// Start some background noise threads, to contend the arc swap.
|
||||
for _ in 0..cnt {
|
||||
s.spawn(|_| {
|
||||
while !stop.load(Ordering::Relaxed) {
|
||||
noise(&shared_number);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Perform the benchmarks
|
||||
batch(c, name, &shared_number);
|
||||
|
||||
// Ask the threads to terminate, so they don't disturb any other banchmarks
|
||||
stop.store(true, Ordering::Relaxed);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn utilities(c: &mut Criterion) {
|
||||
let mut g = c.benchmark_group("utilities");
|
||||
|
||||
struct Composed {
|
||||
val: i32,
|
||||
}
|
||||
|
||||
g.bench_function("access-map", |b| {
|
||||
let a = Arc::new(ArcSwap::from_pointee(Composed { val: 42 }));
|
||||
let m = Map::new(Arc::clone(&a), |c: &Composed| &c.val);
|
||||
b.iter(|| {
|
||||
let g = black_box(m.load());
|
||||
assert_eq!(42, *g);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn benchmark(c: &mut Criterion) {
|
||||
batch(c, "uncontended", &ArcSwap::from_pointee(42));
|
||||
with_background(c, "concurrent_loads", 2, |s| {
|
||||
black_box(s.load());
|
||||
});
|
||||
with_background(c, "concurrent_store", 1, |s| {
|
||||
black_box(s.store(Arc::new(42)));
|
||||
});
|
||||
utilities(c);
|
||||
}
|
||||
|
||||
criterion_group!(benches, benchmark);
|
||||
criterion_main!(benches);
|
||||
Loading…
Add table
Add a link
Reference in a new issue