Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Benchmarking code: ``` use std::cell::{Cell, RefCell, UnsafeCell}; use std::env::args_os; use std::ffi::OsStr; fn a() { thread_local! { static TLS: RefCell<Vec<usize>> = const { RefCell::new(Vec::new()) }; } for i in 0..10000 { TLS.with(|s| { s.borrow_mut().push(i); }); } TLS.with(|s| s.borrow_mut().clear()); } fn b() { thread_local! { static TLS: RefCell<Vec<usize>> = const { RefCell::new(Vec::new()) }; } for i in 0..10000 { TLS.with(|s| { unsafe { s.try_borrow_mut().unwrap_unchecked() }.push(i); }); } TLS.with(|s| unsafe { s.try_borrow_mut().unwrap_unchecked() }.clear()); } fn c() { thread_local! { static TLS: Cell<Vec<usize>> = const { Cell::new(Vec::new()) }; } for i in 0..10000 { TLS.with(|s| { let mut v = s.take(); v.push(i); s.set(v); }); } TLS.with(|s| { let mut v = s.take(); v.clear(); s.set(v); }); } fn d() { thread_local! { static TLS: UnsafeCell<Vec<usize>> = const { UnsafeCell::new(Vec::new()) }; } for i in 0..10000 { TLS.with(|s| { unsafe { &mut *s.get() }.push(i); }); } TLS.with(|s| unsafe { &mut *s.get() }.clear()); } fn e() { thread_local! { static TLS: UnsafeCell<Vec<usize>> = UnsafeCell::new(Vec::new()); } for i in 0..10000 { TLS.with(|s| { unsafe { &mut *s.get() }.push(i); }); } TLS.with(|s| unsafe { &mut *s.get() }.clear()); } fn f() { thread_local! { static TLS: RefCell<Vec<usize>> = RefCell::new(Vec::new()); } for i in 0..10000 { TLS.with(|s| { s.borrow_mut().push(i); }); } TLS.with(|s| s.borrow_mut().clear()); } fn main() { let cmd = args_os().nth(1).unwrap(); for _ in 0..1000 { if cmd == OsStr::new("refcell") { a(); } else if cmd == OsStr::new("refcell_unsafe") { b(); } else if cmd == OsStr::new("cell") { c(); } else if cmd == OsStr::new("unsafecell") { d(); } else if cmd == OsStr::new("unsafecell_non_const") { e(); } else if cmd == OsStr::new("refcell_non_const") { f(); } else { panic!(); } } } ``` Benchmarks: ``` > hyperfine -N "./foo refcell" "./foo refcell_unsafe" "./foo cell" "./foo unsafecell" "./foo unsafecell_non_const" "./foo refcell_non_const" Benchmark 1: ./foo refcell Time (mean ± σ): 17.2 ms ± 0.6 ms [User: 16.8 ms, System: 0.3 ms] Range (min … max): 15.0 ms … 21.3 ms 143 runs Benchmark 2: ./foo refcell_unsafe Time (mean ± σ): 18.1 ms ± 0.3 ms [User: 17.7 ms, System: 0.3 ms] Range (min … max): 16.6 ms … 21.0 ms 167 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Benchmark 3: ./foo cell Time (mean ± σ): 36.0 ms ± 0.9 ms [User: 35.9 ms, System: 0.1 ms] Range (min … max): 34.3 ms … 42.7 ms 81 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Benchmark 4: ./foo unsafecell Time (mean ± σ): 15.2 ms ± 1.1 ms [User: 14.7 ms, System: 0.3 ms] Range (min … max): 14.2 ms … 19.2 ms 210 runs Benchmark 5: ./foo unsafecell_non_const Time (mean ± σ): 15.5 ms ± 0.3 ms [User: 15.0 ms, System: 0.4 ms] Range (min … max): 15.0 ms … 16.3 ms 193 runs Benchmark 6: ./foo refcell_non_const Time (mean ± σ): 25.9 ms ± 5.3 ms [User: 25.5 ms, System: 0.3 ms] Range (min … max): 17.9 ms … 42.2 ms 146 runs Summary './foo unsafecell' ran 1.02 ± 0.08 times faster than './foo unsafecell_non_const' 1.13 ± 0.09 times faster than './foo refcell' 1.19 ± 0.09 times faster than './foo refcell_unsafe' 1.71 ± 0.37 times faster than './foo refcell_non_const' 2.37 ± 0.18 times faster than './foo cell' ``` Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
- Loading branch information