subms_mpsc_queue/
recipe.rs1use std::sync::Arc;
4use std::thread;
5
6use subms::{SubMsBenchParams, SubMsPerfHarness, SubMsRecipe, SubMsStageKind, SubMsTimer};
7
8use crate::{MpscQueue, PopResult};
9
10pub struct MpscQueueRecipe;
13
14impl SubMsRecipe for MpscQueueRecipe {
15 fn name(&self) -> &str {
16 "mpsc-queue"
17 }
18
19 fn run(&self, h: &mut SubMsPerfHarness, params: &SubMsBenchParams) {
20 let entries = params.entries;
21 let warmup = params.warmup;
22 let producers = 4usize;
23 let per_producer = entries / producers;
24
25 let q: Arc<MpscQueue<u64>> = Arc::new(MpscQueue::new());
26
27 {
29 let q_ptr = Arc::as_ptr(&q) as *mut MpscQueue<u64>;
30 let q_mut = unsafe { &mut *q_ptr };
31 for i in 0..warmup as u64 {
32 q.push(i);
33 loop {
34 match q_mut.try_pop() {
35 PopResult::Some(_) => break,
36 _ => std::hint::spin_loop(),
37 }
38 }
39 }
40 }
41
42 let mut producer_handles = Vec::with_capacity(producers);
45 for tid in 0..producers as u64 {
46 let q = q.clone();
47 producer_handles.push(thread::spawn(move || {
48 let mut samples = Vec::with_capacity(per_producer);
49 for i in 0..per_producer as u64 {
50 let t0 = SubMsTimer::tick();
51 q.push((tid << 32) | i);
52 samples.push(t0.elapsed_ns());
53 }
54 samples
55 }));
56 }
57
58 let consumer_q = q.clone();
59 let total = producers * per_producer;
60 let consumer = thread::spawn(move || {
61 let q_ptr = Arc::as_ptr(&consumer_q) as *mut MpscQueue<u64>;
62 let q_mut = unsafe { &mut *q_ptr };
63 let mut samples = Vec::with_capacity(total);
64 let mut count = 0usize;
65 while count < total {
66 let t0 = SubMsTimer::tick();
67 match q_mut.try_pop() {
68 PopResult::Some(_) => {
69 samples.push(t0.elapsed_ns());
70 count += 1;
71 }
72 _ => std::hint::spin_loop(),
73 }
74 }
75 samples
76 });
77
78 let s_offer = h.stage("offer", total).with_kind(SubMsStageKind::HotPath);
79 for handle in producer_handles {
80 for ns in handle.join().expect("producer joined") {
81 s_offer.record(ns);
82 }
83 }
84 let poll_samples = consumer.join().expect("consumer joined");
85 let s_poll = h
86 .stage("poll", poll_samples.len())
87 .with_kind(SubMsStageKind::HotPath);
88 for ns in poll_samples {
89 s_poll.record(ns);
90 }
91 h.add_meta("producers", &producers.to_string());
92 }
93}