summaryrefslogtreecommitdiffstats
path: root/third_party/rust/once_cell/examples
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/once_cell/examples
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/once_cell/examples')
-rw-r--r--third_party/rust/once_cell/examples/bench.rs28
-rw-r--r--third_party/rust/once_cell/examples/bench_acquire.rs39
-rw-r--r--third_party/rust/once_cell/examples/bench_vs_lazy_static.rs51
-rw-r--r--third_party/rust/once_cell/examples/lazy_static.rs36
-rw-r--r--third_party/rust/once_cell/examples/reentrant_init_deadlocks.rs14
-rw-r--r--third_party/rust/once_cell/examples/regex.rs49
-rw-r--r--third_party/rust/once_cell/examples/test_synchronization.rs38
7 files changed, 255 insertions, 0 deletions
diff --git a/third_party/rust/once_cell/examples/bench.rs b/third_party/rust/once_cell/examples/bench.rs
new file mode 100644
index 0000000000..e6801258a1
--- /dev/null
+++ b/third_party/rust/once_cell/examples/bench.rs
@@ -0,0 +1,28 @@
+use std::mem::size_of;
+
+use once_cell::sync::OnceCell;
+
+const N_THREADS: usize = 32;
+const N_ROUNDS: usize = 100_000_000;
+
+static CELL: OnceCell<usize> = OnceCell::new();
+
+fn main() {
+ let start = std::time::Instant::now();
+ let threads =
+ (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::<Vec<_>>();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+ println!("{:?}", start.elapsed());
+ println!("size_of::<OnceCell<()>>() = {:?}", size_of::<OnceCell<()>>());
+ println!("size_of::<OnceCell<bool>>() = {:?}", size_of::<OnceCell<bool>>());
+ println!("size_of::<OnceCell<u32>>() = {:?}", size_of::<OnceCell<u32>>());
+}
+
+fn thread_main(i: usize) {
+ for _ in 0..N_ROUNDS {
+ let &value = CELL.get_or_init(|| i);
+ assert!(value < N_THREADS)
+ }
+}
diff --git a/third_party/rust/once_cell/examples/bench_acquire.rs b/third_party/rust/once_cell/examples/bench_acquire.rs
new file mode 100644
index 0000000000..1518047460
--- /dev/null
+++ b/third_party/rust/once_cell/examples/bench_acquire.rs
@@ -0,0 +1,39 @@
+//! Benchmark the overhead that the synchronization of `OnceCell::get` causes.
+//! We do some other operations that write to memory to get an imprecise but somewhat realistic
+//! measurement.
+
+use once_cell::sync::OnceCell;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+const N_THREADS: usize = 16;
+const N_ROUNDS: usize = 1_000_000;
+
+static CELL: OnceCell<usize> = OnceCell::new();
+static OTHER: AtomicUsize = AtomicUsize::new(0);
+
+fn main() {
+ let start = std::time::Instant::now();
+ let threads =
+ (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::<Vec<_>>();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+ println!("{:?}", start.elapsed());
+ println!("{:?}", OTHER.load(Ordering::Relaxed));
+}
+
+#[inline(never)]
+fn thread_main(i: usize) {
+ // The operations we do here don't really matter, as long as we do multiple writes, and
+ // everything is messy enough to prevent the compiler from optimizing the loop away.
+ let mut data = [i; 128];
+ let mut accum = 0usize;
+ for _ in 0..N_ROUNDS {
+ let _value = CELL.get_or_init(|| i + 1);
+ let k = OTHER.fetch_add(data[accum & 0x7F] as usize, Ordering::Relaxed);
+ for j in data.iter_mut() {
+ *j = (*j).wrapping_add(accum);
+ accum = accum.wrapping_add(k);
+ }
+ }
+}
diff --git a/third_party/rust/once_cell/examples/bench_vs_lazy_static.rs b/third_party/rust/once_cell/examples/bench_vs_lazy_static.rs
new file mode 100644
index 0000000000..c23b0124e4
--- /dev/null
+++ b/third_party/rust/once_cell/examples/bench_vs_lazy_static.rs
@@ -0,0 +1,51 @@
+use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
+
+const N_THREADS: usize = 32;
+const N_ROUNDS: usize = 100_000_000;
+
+static ONCE_CELL: Lazy<Vec<String>> = Lazy::new(|| vec!["Spica".to_string(), "Hoyten".to_string()]);
+
+lazy_static! {
+ static ref LAZY_STATIC: Vec<String> = vec!["Spica".to_string(), "Hoyten".to_string()];
+}
+
+fn main() {
+ let once_cell = {
+ let start = std::time::Instant::now();
+ let threads = (0..N_THREADS)
+ .map(|_| std::thread::spawn(move || thread_once_cell()))
+ .collect::<Vec<_>>();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+ start.elapsed()
+ };
+ let lazy_static = {
+ let start = std::time::Instant::now();
+ let threads = (0..N_THREADS)
+ .map(|_| std::thread::spawn(move || thread_lazy_static()))
+ .collect::<Vec<_>>();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+ start.elapsed()
+ };
+
+ println!("once_cell: {:?}", once_cell);
+ println!("lazy_static: {:?}", lazy_static);
+}
+
+fn thread_once_cell() {
+ for _ in 0..N_ROUNDS {
+ let len = ONCE_CELL.len();
+ assert_eq!(len, 2)
+ }
+}
+
+fn thread_lazy_static() {
+ for _ in 0..N_ROUNDS {
+ let len = LAZY_STATIC.len();
+ assert_eq!(len, 2)
+ }
+}
diff --git a/third_party/rust/once_cell/examples/lazy_static.rs b/third_party/rust/once_cell/examples/lazy_static.rs
new file mode 100644
index 0000000000..3cdb19f2a5
--- /dev/null
+++ b/third_party/rust/once_cell/examples/lazy_static.rs
@@ -0,0 +1,36 @@
+extern crate once_cell;
+
+use once_cell::sync::{Lazy, OnceCell};
+use std::collections::HashMap;
+
+static HASHMAP: Lazy<HashMap<u32, &'static str>> = Lazy::new(|| {
+ let mut m = HashMap::new();
+ m.insert(0, "foo");
+ m.insert(1, "bar");
+ m.insert(2, "baz");
+ m
+});
+
+// Same, but completely without macros
+fn hashmap() -> &'static HashMap<u32, &'static str> {
+ static INSTANCE: OnceCell<HashMap<u32, &'static str>> = OnceCell::new();
+ INSTANCE.get_or_init(|| {
+ let mut m = HashMap::new();
+ m.insert(0, "foo");
+ m.insert(1, "bar");
+ m.insert(2, "baz");
+ m
+ })
+}
+
+fn main() {
+ // First access to `HASHMAP` initializes it
+ println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
+
+ // Any further access to `HASHMAP` just returns the computed value
+ println!("The entry for `1` is \"{}\".", HASHMAP.get(&1).unwrap());
+
+ // The same works for function-style:
+ assert_eq!(hashmap().get(&0), Some(&"foo"));
+ assert_eq!(hashmap().get(&1), Some(&"bar"));
+}
diff --git a/third_party/rust/once_cell/examples/reentrant_init_deadlocks.rs b/third_party/rust/once_cell/examples/reentrant_init_deadlocks.rs
new file mode 100644
index 0000000000..af4b5b7d0e
--- /dev/null
+++ b/third_party/rust/once_cell/examples/reentrant_init_deadlocks.rs
@@ -0,0 +1,14 @@
+fn main() {
+ let cell = once_cell::sync::OnceCell::<u32>::new();
+ cell.get_or_init(|| {
+ cell.get_or_init(|| 1);
+ 2
+ });
+}
+
+/// Dummy test to make it seem hang when compiled as `--test`
+/// See https://github.com/matklad/once_cell/issues/79
+#[test]
+fn dummy_test() {
+ std::thread::sleep(std::time::Duration::from_secs(4));
+}
diff --git a/third_party/rust/once_cell/examples/regex.rs b/third_party/rust/once_cell/examples/regex.rs
new file mode 100644
index 0000000000..4c4c2ea6b8
--- /dev/null
+++ b/third_party/rust/once_cell/examples/regex.rs
@@ -0,0 +1,49 @@
+use std::{str::FromStr, time::Instant};
+
+use regex::Regex;
+
+macro_rules! regex {
+ ($re:literal $(,)?) => {{
+ static RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new();
+ RE.get_or_init(|| regex::Regex::new($re).unwrap())
+ }};
+}
+
+fn slow() {
+ let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##;
+
+ let mut total = 0;
+ for _ in 0..1000 {
+ let re = Regex::new(
+ r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##,
+ )
+ .unwrap();
+ let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap();
+ total += size;
+ }
+ println!("{}", total);
+}
+
+fn fast() {
+ let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##;
+
+ let mut total = 0;
+ for _ in 0..1000 {
+ let re: &Regex = regex!(
+ r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##,
+ );
+ let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap();
+ total += size;
+ }
+ println!("{}", total);
+}
+
+fn main() {
+ let t = Instant::now();
+ slow();
+ println!("slow: {:?}", t.elapsed());
+
+ let t = Instant::now();
+ fast();
+ println!("fast: {:?}", t.elapsed());
+}
diff --git a/third_party/rust/once_cell/examples/test_synchronization.rs b/third_party/rust/once_cell/examples/test_synchronization.rs
new file mode 100644
index 0000000000..0d54f9827e
--- /dev/null
+++ b/third_party/rust/once_cell/examples/test_synchronization.rs
@@ -0,0 +1,38 @@
+//! Test if the OnceCell properly synchronizes.
+//! Needs to be run in release mode.
+//!
+//! We create a `Vec` with `N_ROUNDS` of `OnceCell`s. All threads will walk the `Vec`, and race to
+//! be the first one to initialize a cell.
+//! Every thread adds the results of the cells it sees to an accumulator, which is compared at the
+//! end.
+//! All threads should end up with the same result.
+
+use once_cell::sync::OnceCell;
+
+const N_THREADS: usize = 32;
+const N_ROUNDS: usize = 1_000_000;
+
+static CELLS: OnceCell<Vec<OnceCell<usize>>> = OnceCell::new();
+static RESULT: OnceCell<usize> = OnceCell::new();
+
+fn main() {
+ let start = std::time::Instant::now();
+ CELLS.get_or_init(|| vec![OnceCell::new(); N_ROUNDS]);
+ let threads =
+ (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::<Vec<_>>();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+ println!("{:?}", start.elapsed());
+ println!("No races detected");
+}
+
+fn thread_main(i: usize) {
+ let cells = CELLS.get().unwrap();
+ let mut accum = 0;
+ for cell in cells.iter() {
+ let &value = cell.get_or_init(|| i);
+ accum += value;
+ }
+ assert_eq!(RESULT.get_or_init(|| accum), &accum);
+}