scope_bench/
scope_bench.rs1use std::cell::RefCell;
5use std::rc::Rc;
6use std::time::Instant;
7
8use auralis_task::{init_flush_scheduler, Priority, ScheduleFlush, TaskScope};
9
10struct BenchScheduleFlush;
15impl ScheduleFlush for BenchScheduleFlush {
16 fn schedule(&self, callback: Box<dyn FnOnce()>) {
17 callback();
18 }
19}
20fn init() {
21 init_flush_scheduler(Rc::new(BenchScheduleFlush));
22}
23
24struct BatchedFlush {
29 callbacks: RefCell<Vec<Box<dyn FnOnce()>>>,
30}
31impl BatchedFlush {
32 fn new() -> Rc<Self> {
33 Rc::new(Self {
34 callbacks: RefCell::new(Vec::new()),
35 })
36 }
37 fn drain(&self) {
38 while let Some(cb) = self.callbacks.borrow_mut().pop() {
39 cb();
40 }
41 }
42}
43impl ScheduleFlush for BatchedFlush {
44 fn schedule(&self, callback: Box<dyn FnOnce()>) {
45 self.callbacks.borrow_mut().push(callback);
46 }
47}
48
49fn time<R>(label: &str, iterations: u64, mut f: impl FnMut() -> R) {
54 for _ in 0..(iterations / 10).max(1) {
56 f();
57 }
58 let start = Instant::now();
59 for _ in 0..iterations {
60 f();
61 }
62 let elapsed = start.elapsed().as_secs_f64() * 1_000_000.0 / iterations as f64;
63 println!(" {:<42} {:>8.2} µs/iter", label, elapsed);
64}
65
66fn main() {
69 println!("=== Auralis Task Scope Benchmarks ===\n");
70
71 let iterations = 50_000;
73 init();
74 time("scope_100_tasks_create_destroy", iterations, || {
75 let scope = TaskScope::new();
76 for _ in 0..100 {
77 scope.spawn(async {});
78 }
79 drop(scope);
80 });
81
82 init();
84 time("scope_200_levels_deep_drop", 5_000, || {
85 let root = TaskScope::new();
86 {
87 let mut current = TaskScope::new_child(&root);
88 for _ in 0..199 {
89 current.spawn(async {});
90 current = TaskScope::new_child(¤t);
91 }
92 }
93 drop(root);
94 });
95
96 {
98 let order: Rc<RefCell<Vec<String>>> = Rc::new(RefCell::new(Vec::new()));
99 let min_iterations = 5_000;
100 for _ in 0..500 {
102 let sched = BatchedFlush::new();
103 init_flush_scheduler(Rc::clone(&sched) as Rc<dyn ScheduleFlush>);
104 order.borrow_mut().clear();
105 for i in 0..1000 {
106 let o = Rc::clone(&order);
107 auralis_task::spawn_global_with_priority(Priority::Low, async move {
108 o.borrow_mut().push(format!("low_{i}"));
109 });
110 }
111 for i in 0..10 {
112 let o = Rc::clone(&order);
113 auralis_task::spawn_global_with_priority(Priority::High, async move {
114 o.borrow_mut().push(format!("high_{i}"));
115 });
116 }
117 sched.drain();
118 }
119
120 let start = Instant::now();
121 for _ in 0..min_iterations {
122 let sched = BatchedFlush::new();
123 init_flush_scheduler(Rc::clone(&sched) as Rc<dyn ScheduleFlush>);
124 order.borrow_mut().clear();
125 for i in 0..1000 {
126 let o = Rc::clone(&order);
127 auralis_task::spawn_global_with_priority(Priority::Low, async move {
128 o.borrow_mut().push(format!("low_{i}"));
129 });
130 }
131 for i in 0..10 {
132 let o = Rc::clone(&order);
133 auralis_task::spawn_global_with_priority(Priority::High, async move {
134 o.borrow_mut().push(format!("high_{i}"));
135 });
136 }
137 sched.drain();
138 let result = order.borrow().clone();
140 debug_assert_eq!(result.len(), 1010);
141 }
142 let elapsed = start.elapsed().as_secs_f64() * 1_000_000.0 / min_iterations as f64;
143 println!(
144 " {:<42} {:>8.2} µs/iter",
145 "priority_1000_low_10_high", elapsed
146 );
147 init(); }
149
150 init();
152 time("scope_churn_100x10_batch_drop", 5_000, || {
153 let scopes: Vec<TaskScope> = (0..100)
154 .map(|_| {
155 let s = TaskScope::new();
156 for _ in 0..10 {
157 s.spawn(async {});
158 }
159 s
160 })
161 .collect();
162 drop(scopes);
163 });
164
165 init();
167 let scope = TaskScope::new();
168 for _ in 0..1000 {
169 scope.spawn(async {});
170 }
171 time("scope_suspend_resume_1000_tasks", 500_000, || {
172 scope.suspend();
173 scope.resume();
174 });
175
176 init();
178 time("scope_wide_tree_50x3_drop", 500, || {
179 let root = TaskScope::new();
180 for _ in 0..50 {
181 let child = TaskScope::new_child(&root);
182 child.spawn(async {});
183 for _ in 0..50 {
184 let grandchild = TaskScope::new_child(&child);
185 grandchild.spawn(async {});
186 }
187 }
188 drop(root);
189 });
190
191 println!("\n=== Done ===");
192}