#![feature(test)] extern crate test; use test::Bencher; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::Relaxed; use std::sync::{mpsc, Arc}; use std::thread; use async_std::task; use crossbeam_channel::{bounded, Sender}; use futures::channel::oneshot; #[derive(Clone)] struct AtomicCounter(Sender<()>); impl Drop for AtomicCounter { fn drop(&mut self) { let _ = self.0.send(()); //通知执行完成 } } #[bench] fn async_std_spawn_empty_many(b: &mut Bencher) { let (send, recv) = bounded(1); b.iter(move || { { let counter = Arc::new(AtomicCounter(send.clone())); let counter0 = counter.clone(); let counter1 = counter.clone(); let counter2 = counter.clone(); let counter3 = counter.clone(); thread::spawn(move || { for _ in 0..2500 { let counter_copy = counter0.clone(); let _ = task::spawn(async move { drop(counter_copy); }); } }); thread::spawn(move || { for _ in 2500..5000 { let counter_copy = counter1.clone(); let _ = task::spawn(async move { drop(counter_copy); }); } }); thread::spawn(move || { for _ in 5000..7500 { let counter_copy = counter2.clone(); let _ = task::spawn(async move { drop(counter_copy); }); } }); thread::spawn(move || { for _ in 7500..10000 { let counter_copy = counter3.clone(); let _ = task::spawn(async move { drop(counter_copy); }); } }); } let _ = recv.clone().recv().unwrap(); }); } #[bench] fn async_std_await_empty_many(b: &mut Bencher) { let (send, recv) = bounded(1); b.iter(move || { { let counter = Arc::new(AtomicCounter(send.clone())); let counter0 = counter.clone(); let counter1 = counter.clone(); let counter2 = counter.clone(); let counter3 = counter.clone(); task::spawn(async move { for _ in 0..2500 { let counter_copy = counter0.clone(); async move { drop(counter_copy); } .await; } }); task::spawn(async move { for _ in 2500..5000 { let counter_copy = counter1.clone(); async move { drop(counter_copy); } .await; } }); task::spawn(async move { for _ in 5000..7500 { let counter_copy = counter2.clone(); async move { drop(counter_copy); } .await; } }); task::spawn(async move { for _ in 7500..10000 { let counter_copy = counter3.clone(); async move { drop(counter_copy); } .await; } }); } let _ = recv.clone().recv().unwrap(); }); } #[bench] fn async_std_spawn_many(b: &mut Bencher) { let (send, recv) = bounded(1); b.iter(move || { { let counter = Arc::new(AtomicCounter(send.clone())); let counter0 = counter.clone(); let counter1 = counter.clone(); let counter2 = counter.clone(); let counter3 = counter.clone(); task::spawn(async move { for _ in 0..2500 { let counter_copy = counter0.clone(); let _ = task::spawn(async move { drop(counter_copy); }); } }); task::spawn(async move { for _ in 2500..5000 { let counter_copy = counter1.clone(); let _ = task::spawn(async move { drop(counter_copy); }); } }); task::spawn(async move { for _ in 5000..7500 { let counter_copy = counter2.clone(); let _ = task::spawn(async move { drop(counter_copy); }); } }); task::spawn(async move { for _ in 7500..10000 { let counter_copy = counter3.clone(); let _ = task::spawn(async move { drop(counter_copy); }); } }); } let _ = recv.clone().recv().unwrap(); }); } #[bench] fn async_std_yield_many(b: &mut Bencher) { const NUM_YIELD: usize = 1_000; const TASKS: usize = 200; let (tx, rx) = mpsc::sync_channel(TASKS); b.iter(move || { for _ in 0..TASKS { let tx = tx.clone(); task::spawn(async move { for _ in 0..NUM_YIELD { task::yield_now().await; } tx.send(()).unwrap(); }); } for _ in 0..TASKS { let _ = rx.recv().unwrap(); } }); } #[bench] fn async_std_ping_pong(b: &mut Bencher) { const NUM_PINGS: usize = 1_000; let rem = Arc::new(AtomicUsize::new(0)); b.iter(|| { let (done_tx, done_rx) = bounded(1); let rem = rem.clone(); rem.store(NUM_PINGS, Relaxed); task::spawn(async { task::spawn(async move { for _ in 0..NUM_PINGS { let rem = rem.clone(); let done_tx = done_tx.clone(); task::spawn(async move { let (tx1, rx1) = oneshot::channel(); let (tx2, rx2) = oneshot::channel(); task::spawn(async move { rx1.await.unwrap(); tx2.send(()).unwrap(); }); tx1.send(()).unwrap(); rx2.await.unwrap(); if 1 == rem.fetch_sub(1, Relaxed) { done_tx.send(()).unwrap(); } }); } }); }); let _ = done_rx.recv().unwrap(); }); } #[bench] fn async_std_chained_spawn(b: &mut Bencher) { const ITER: usize = 1_000; fn iter(done_tx: mpsc::SyncSender<()>, n: usize) { if n == 0 { done_tx.send(()).unwrap(); } else { task::spawn(async move { iter(done_tx, n - 1); }); } } let (done_tx, done_rx) = mpsc::sync_channel(1000); b.iter(move || { let done_tx = done_tx.clone(); task::block_on(async { task::spawn(async move { iter(done_tx, ITER); }); done_rx.recv().unwrap(); }); }); } #[bench] fn async_std_spawn_one_to_one(b: &mut Bencher) { let (send, recv) = bounded(1); b.iter(move || { { let counter = Arc::new(AtomicCounter(send.clone())); let counter0 = counter.clone(); let counter1 = counter.clone(); let counter2 = counter.clone(); let counter3 = counter.clone(); thread::spawn(move || { for _ in 0..2500 { let counter_copy = counter0.clone(); let _ = task::spawn(async move { let _ = task::spawn(async move { drop(counter_copy); }); }); } }); thread::spawn(move || { for _ in 2500..5000 { let counter_copy = counter1.clone(); let _ = task::spawn(async move { let _ = task::spawn(async move { drop(counter_copy); }); }); } }); thread::spawn(move || { for _ in 5000..7500 { let counter_copy = counter2.clone(); let _ = task::spawn(async move { let _ = task::spawn(async move { drop(counter_copy); }); }); } }); thread::spawn(move || { for _ in 7500..10000 { let counter_copy = counter3.clone(); let _ = task::spawn(async move { let _ = task::spawn(async move { drop(counter_copy); }); }); } }); } let _ = recv.clone().recv().unwrap(); }); }