per-thread-object 0.6.1

Efficient per-object thread-local storage implementation
Documentation
use std::time::Instant;
use std::hint::black_box;
use rayon::prelude::*;
use criterion::{ criterion_main, criterion_group, Criterion };


const N: usize = 500;

fn bench_thread_local(c: &mut Criterion) {
    c.bench_function("std::thread_local!", |b| {
        thread_local!{
            static TL: u64 = 0x42;
        }

        b.iter_custom(|iters| {
            (0..iters)
                .into_par_iter()
                .map(|_| {
                    let start = Instant::now();
                    for _ in 0..N {
                        TL.with(|val| {
                            let _ = black_box(val);
                        });
                    }
                    start.elapsed()
                })
                .sum()
        });
    });

    c.bench_function("per-thread-object", |b| {
        use per_thread_object::ThreadLocal;

        let tl: ThreadLocal<u64> = ThreadLocal::new();

        b.iter_custom(|iters| {
            (0..iters)
                .into_par_iter()
                .map(|_| {
                    per_thread_object::stack_token!(token);

                    let start = Instant::now();
                    for _ in 0..N {
                        black_box(*tl.get_or_init(token, || 0x42));
                    }
                    start.elapsed()
                })
                .sum()
        });
    });

    c.bench_function("thread_local", |b| {
        use thread_local::ThreadLocal;

        let tl: ThreadLocal<u64> = ThreadLocal::new();

        b.iter_custom(|iters| {
            (0..iters)
                .into_par_iter()
                .map(|_| {
                    let start = Instant::now();
                    for _ in 0..N {
                        let val = tl.get_or(|| 0x42);
                        black_box(val);
                    }
                    start.elapsed()
                })
                .sum()
        });
    });

    c.bench_function("os-thread-local", |b| {
        use os_thread_local::ThreadLocal;

        let tl: ThreadLocal<u64> = ThreadLocal::new(|| 0x42);

        b.iter_custom(|iters| {
            (0..iters)
                .into_par_iter()
                .map(|_| {
                    let start = Instant::now();
                    for _ in 0..N {
                        tl.with(|val| {
                            let _ = black_box(val);
                        });
                    }
                    start.elapsed()
                })
                .sum()
        });
    });
}

criterion_group!(tls, bench_thread_local);
criterion_main!(tls);