blob: 1c05222947dc9d8c9c80b39c06cbe9e425b559d7 [file] [log] [blame]
Jakub Kotur2b588ff2020-12-21 17:28:14 +01001#![feature(test)]
2
3extern crate test;
4
5use crossbeam_channel::{bounded, unbounded};
6use crossbeam_utils::thread::scope;
7use test::Bencher;
8
9const TOTAL_STEPS: usize = 40_000;
10
11mod unbounded {
12 use super::*;
13
14 #[bench]
15 fn create(b: &mut Bencher) {
David LeGare54fc8482022-03-01 18:58:39 +000016 b.iter(unbounded::<i32>);
Jakub Kotur2b588ff2020-12-21 17:28:14 +010017 }
18
19 #[bench]
20 fn oneshot(b: &mut Bencher) {
21 b.iter(|| {
22 let (s, r) = unbounded::<i32>();
23 s.send(0).unwrap();
24 r.recv().unwrap();
25 });
26 }
27
28 #[bench]
29 fn inout(b: &mut Bencher) {
30 let (s, r) = unbounded::<i32>();
31 b.iter(|| {
32 s.send(0).unwrap();
33 r.recv().unwrap();
34 });
35 }
36
37 #[bench]
38 fn par_inout(b: &mut Bencher) {
39 let threads = num_cpus::get();
40 let steps = TOTAL_STEPS / threads;
41 let (s, r) = unbounded::<i32>();
42
43 let (s1, r1) = bounded(0);
44 let (s2, r2) = bounded(0);
45 scope(|scope| {
46 for _ in 0..threads {
47 scope.spawn(|_| {
48 while r1.recv().is_ok() {
49 for i in 0..steps {
50 s.send(i as i32).unwrap();
51 r.recv().unwrap();
52 }
53 s2.send(()).unwrap();
54 }
55 });
56 }
57
58 b.iter(|| {
59 for _ in 0..threads {
60 s1.send(()).unwrap();
61 }
62 for _ in 0..threads {
63 r2.recv().unwrap();
64 }
65 });
66 drop(s1);
67 })
68 .unwrap();
69 }
70
71 #[bench]
72 fn spsc(b: &mut Bencher) {
73 let steps = TOTAL_STEPS;
74 let (s, r) = unbounded::<i32>();
75
76 let (s1, r1) = bounded(0);
77 let (s2, r2) = bounded(0);
78 scope(|scope| {
79 scope.spawn(|_| {
80 while r1.recv().is_ok() {
81 for i in 0..steps {
82 s.send(i as i32).unwrap();
83 }
84 s2.send(()).unwrap();
85 }
86 });
87
88 b.iter(|| {
89 s1.send(()).unwrap();
90 for _ in 0..steps {
91 r.recv().unwrap();
92 }
93 r2.recv().unwrap();
94 });
95 drop(s1);
96 })
97 .unwrap();
98 }
99
100 #[bench]
101 fn spmc(b: &mut Bencher) {
102 let threads = num_cpus::get() - 1;
103 let steps = TOTAL_STEPS / threads;
104 let (s, r) = unbounded::<i32>();
105
106 let (s1, r1) = bounded(0);
107 let (s2, r2) = bounded(0);
108 scope(|scope| {
109 for _ in 0..threads {
110 scope.spawn(|_| {
111 while r1.recv().is_ok() {
112 for _ in 0..steps {
113 r.recv().unwrap();
114 }
115 s2.send(()).unwrap();
116 }
117 });
118 }
119
120 b.iter(|| {
121 for _ in 0..threads {
122 s1.send(()).unwrap();
123 }
124 for i in 0..steps * threads {
125 s.send(i as i32).unwrap();
126 }
127 for _ in 0..threads {
128 r2.recv().unwrap();
129 }
130 });
131 drop(s1);
132 })
133 .unwrap();
134 }
135
136 #[bench]
137 fn mpsc(b: &mut Bencher) {
138 let threads = num_cpus::get() - 1;
139 let steps = TOTAL_STEPS / threads;
140 let (s, r) = unbounded::<i32>();
141
142 let (s1, r1) = bounded(0);
143 let (s2, r2) = bounded(0);
144 scope(|scope| {
145 for _ in 0..threads {
146 scope.spawn(|_| {
147 while r1.recv().is_ok() {
148 for i in 0..steps {
149 s.send(i as i32).unwrap();
150 }
151 s2.send(()).unwrap();
152 }
153 });
154 }
155
156 b.iter(|| {
157 for _ in 0..threads {
158 s1.send(()).unwrap();
159 }
160 for _ in 0..steps * threads {
161 r.recv().unwrap();
162 }
163 for _ in 0..threads {
164 r2.recv().unwrap();
165 }
166 });
167 drop(s1);
168 })
169 .unwrap();
170 }
171
172 #[bench]
173 fn mpmc(b: &mut Bencher) {
174 let threads = num_cpus::get();
175 let steps = TOTAL_STEPS / threads;
176 let (s, r) = unbounded::<i32>();
177
178 let (s1, r1) = bounded(0);
179 let (s2, r2) = bounded(0);
180 scope(|scope| {
181 for _ in 0..threads / 2 {
182 scope.spawn(|_| {
183 while r1.recv().is_ok() {
184 for i in 0..steps {
185 s.send(i as i32).unwrap();
186 }
187 s2.send(()).unwrap();
188 }
189 });
190 }
191 for _ in 0..threads / 2 {
192 scope.spawn(|_| {
193 while r1.recv().is_ok() {
194 for _ in 0..steps {
195 r.recv().unwrap();
196 }
197 s2.send(()).unwrap();
198 }
199 });
200 }
201
202 b.iter(|| {
203 for _ in 0..threads {
204 s1.send(()).unwrap();
205 }
206 for _ in 0..threads {
207 r2.recv().unwrap();
208 }
209 });
210 drop(s1);
211 })
212 .unwrap();
213 }
214}
215
216mod bounded_n {
217 use super::*;
218
219 #[bench]
220 fn spsc(b: &mut Bencher) {
221 let steps = TOTAL_STEPS;
222 let (s, r) = bounded::<i32>(steps);
223
224 let (s1, r1) = bounded(0);
225 let (s2, r2) = bounded(0);
226 scope(|scope| {
227 scope.spawn(|_| {
228 while r1.recv().is_ok() {
229 for i in 0..steps {
230 s.send(i as i32).unwrap();
231 }
232 s2.send(()).unwrap();
233 }
234 });
235
236 b.iter(|| {
237 s1.send(()).unwrap();
238 for _ in 0..steps {
239 r.recv().unwrap();
240 }
241 r2.recv().unwrap();
242 });
243 drop(s1);
244 })
245 .unwrap();
246 }
247
248 #[bench]
249 fn spmc(b: &mut Bencher) {
250 let threads = num_cpus::get() - 1;
251 let steps = TOTAL_STEPS / threads;
252 let (s, r) = bounded::<i32>(steps * threads);
253
254 let (s1, r1) = bounded(0);
255 let (s2, r2) = bounded(0);
256 scope(|scope| {
257 for _ in 0..threads {
258 scope.spawn(|_| {
259 while r1.recv().is_ok() {
260 for _ in 0..steps {
261 r.recv().unwrap();
262 }
263 s2.send(()).unwrap();
264 }
265 });
266 }
267
268 b.iter(|| {
269 for _ in 0..threads {
270 s1.send(()).unwrap();
271 }
272 for i in 0..steps * threads {
273 s.send(i as i32).unwrap();
274 }
275 for _ in 0..threads {
276 r2.recv().unwrap();
277 }
278 });
279 drop(s1);
280 })
281 .unwrap();
282 }
283
284 #[bench]
285 fn mpsc(b: &mut Bencher) {
286 let threads = num_cpus::get() - 1;
287 let steps = TOTAL_STEPS / threads;
288 let (s, r) = bounded::<i32>(steps * threads);
289
290 let (s1, r1) = bounded(0);
291 let (s2, r2) = bounded(0);
292 scope(|scope| {
293 for _ in 0..threads {
294 scope.spawn(|_| {
295 while r1.recv().is_ok() {
296 for i in 0..steps {
297 s.send(i as i32).unwrap();
298 }
299 s2.send(()).unwrap();
300 }
301 });
302 }
303
304 b.iter(|| {
305 for _ in 0..threads {
306 s1.send(()).unwrap();
307 }
308 for _ in 0..steps * threads {
309 r.recv().unwrap();
310 }
311 for _ in 0..threads {
312 r2.recv().unwrap();
313 }
314 });
315 drop(s1);
316 })
317 .unwrap();
318 }
319
320 #[bench]
321 fn par_inout(b: &mut Bencher) {
322 let threads = num_cpus::get();
323 let steps = TOTAL_STEPS / threads;
324 let (s, r) = bounded::<i32>(threads);
325
326 let (s1, r1) = bounded(0);
327 let (s2, r2) = bounded(0);
328 scope(|scope| {
329 for _ in 0..threads {
330 scope.spawn(|_| {
331 while r1.recv().is_ok() {
332 for i in 0..steps {
333 s.send(i as i32).unwrap();
334 r.recv().unwrap();
335 }
336 s2.send(()).unwrap();
337 }
338 });
339 }
340
341 b.iter(|| {
342 for _ in 0..threads {
343 s1.send(()).unwrap();
344 }
345 for _ in 0..threads {
346 r2.recv().unwrap();
347 }
348 });
349 drop(s1);
350 })
351 .unwrap();
352 }
353
354 #[bench]
355 fn mpmc(b: &mut Bencher) {
356 let threads = num_cpus::get();
357 assert_eq!(threads % 2, 0);
358 let steps = TOTAL_STEPS / threads;
359 let (s, r) = bounded::<i32>(steps * threads);
360
361 let (s1, r1) = bounded(0);
362 let (s2, r2) = bounded(0);
363 scope(|scope| {
364 for _ in 0..threads / 2 {
365 scope.spawn(|_| {
366 while r1.recv().is_ok() {
367 for i in 0..steps {
368 s.send(i as i32).unwrap();
369 }
370 s2.send(()).unwrap();
371 }
372 });
373 }
374 for _ in 0..threads / 2 {
375 scope.spawn(|_| {
376 while r1.recv().is_ok() {
377 for _ in 0..steps {
378 r.recv().unwrap();
379 }
380 s2.send(()).unwrap();
381 }
382 });
383 }
384
385 b.iter(|| {
386 for _ in 0..threads {
387 s1.send(()).unwrap();
388 }
389 for _ in 0..threads {
390 r2.recv().unwrap();
391 }
392 });
393 drop(s1);
394 })
395 .unwrap();
396 }
397}
398
399mod bounded_1 {
400 use super::*;
401
402 #[bench]
403 fn create(b: &mut Bencher) {
404 b.iter(|| bounded::<i32>(1));
405 }
406
407 #[bench]
408 fn oneshot(b: &mut Bencher) {
409 b.iter(|| {
410 let (s, r) = bounded::<i32>(1);
411 s.send(0).unwrap();
412 r.recv().unwrap();
413 });
414 }
415
416 #[bench]
417 fn spsc(b: &mut Bencher) {
418 let steps = TOTAL_STEPS;
419 let (s, r) = bounded::<i32>(1);
420
421 let (s1, r1) = bounded(0);
422 let (s2, r2) = bounded(0);
423 scope(|scope| {
424 scope.spawn(|_| {
425 while r1.recv().is_ok() {
426 for i in 0..steps {
427 s.send(i as i32).unwrap();
428 }
429 s2.send(()).unwrap();
430 }
431 });
432
433 b.iter(|| {
434 s1.send(()).unwrap();
435 for _ in 0..steps {
436 r.recv().unwrap();
437 }
438 r2.recv().unwrap();
439 });
440 drop(s1);
441 })
442 .unwrap();
443 }
444
445 #[bench]
446 fn spmc(b: &mut Bencher) {
447 let threads = num_cpus::get() - 1;
448 let steps = TOTAL_STEPS / threads;
449 let (s, r) = bounded::<i32>(1);
450
451 let (s1, r1) = bounded(0);
452 let (s2, r2) = bounded(0);
453 scope(|scope| {
454 for _ in 0..threads {
455 scope.spawn(|_| {
456 while r1.recv().is_ok() {
457 for _ in 0..steps {
458 r.recv().unwrap();
459 }
460 s2.send(()).unwrap();
461 }
462 });
463 }
464
465 b.iter(|| {
466 for _ in 0..threads {
467 s1.send(()).unwrap();
468 }
469 for i in 0..steps * threads {
470 s.send(i as i32).unwrap();
471 }
472 for _ in 0..threads {
473 r2.recv().unwrap();
474 }
475 });
476 drop(s1);
477 })
478 .unwrap();
479 }
480
481 #[bench]
482 fn mpsc(b: &mut Bencher) {
483 let threads = num_cpus::get() - 1;
484 let steps = TOTAL_STEPS / threads;
485 let (s, r) = bounded::<i32>(1);
486
487 let (s1, r1) = bounded(0);
488 let (s2, r2) = bounded(0);
489 scope(|scope| {
490 for _ in 0..threads {
491 scope.spawn(|_| {
492 while r1.recv().is_ok() {
493 for i in 0..steps {
494 s.send(i as i32).unwrap();
495 }
496 s2.send(()).unwrap();
497 }
498 });
499 }
500
501 b.iter(|| {
502 for _ in 0..threads {
503 s1.send(()).unwrap();
504 }
505 for _ in 0..steps * threads {
506 r.recv().unwrap();
507 }
508 for _ in 0..threads {
509 r2.recv().unwrap();
510 }
511 });
512 drop(s1);
513 })
514 .unwrap();
515 }
516
517 #[bench]
518 fn mpmc(b: &mut Bencher) {
519 let threads = num_cpus::get();
520 let steps = TOTAL_STEPS / threads;
521 let (s, r) = bounded::<i32>(1);
522
523 let (s1, r1) = bounded(0);
524 let (s2, r2) = bounded(0);
525 scope(|scope| {
526 for _ in 0..threads / 2 {
527 scope.spawn(|_| {
528 while r1.recv().is_ok() {
529 for i in 0..steps {
530 s.send(i as i32).unwrap();
531 }
532 s2.send(()).unwrap();
533 }
534 });
535 }
536 for _ in 0..threads / 2 {
537 scope.spawn(|_| {
538 while r1.recv().is_ok() {
539 for _ in 0..steps {
540 r.recv().unwrap();
541 }
542 s2.send(()).unwrap();
543 }
544 });
545 }
546
547 b.iter(|| {
548 for _ in 0..threads {
549 s1.send(()).unwrap();
550 }
551 for _ in 0..threads {
552 r2.recv().unwrap();
553 }
554 });
555 drop(s1);
556 })
557 .unwrap();
558 }
559}
560
561mod bounded_0 {
562 use super::*;
563
564 #[bench]
565 fn create(b: &mut Bencher) {
566 b.iter(|| bounded::<i32>(0));
567 }
568
569 #[bench]
570 fn spsc(b: &mut Bencher) {
571 let steps = TOTAL_STEPS;
572 let (s, r) = bounded::<i32>(0);
573
574 let (s1, r1) = bounded(0);
575 let (s2, r2) = bounded(0);
576 scope(|scope| {
577 scope.spawn(|_| {
578 while r1.recv().is_ok() {
579 for i in 0..steps {
580 s.send(i as i32).unwrap();
581 }
582 s2.send(()).unwrap();
583 }
584 });
585
586 b.iter(|| {
587 s1.send(()).unwrap();
588 for _ in 0..steps {
589 r.recv().unwrap();
590 }
591 r2.recv().unwrap();
592 });
593 drop(s1);
594 })
595 .unwrap();
596 }
597
598 #[bench]
599 fn spmc(b: &mut Bencher) {
600 let threads = num_cpus::get() - 1;
601 let steps = TOTAL_STEPS / threads;
602 let (s, r) = bounded::<i32>(0);
603
604 let (s1, r1) = bounded(0);
605 let (s2, r2) = bounded(0);
606 scope(|scope| {
607 for _ in 0..threads {
608 scope.spawn(|_| {
609 while r1.recv().is_ok() {
610 for _ in 0..steps {
611 r.recv().unwrap();
612 }
613 s2.send(()).unwrap();
614 }
615 });
616 }
617
618 b.iter(|| {
619 for _ in 0..threads {
620 s1.send(()).unwrap();
621 }
622 for i in 0..steps * threads {
623 s.send(i as i32).unwrap();
624 }
625 for _ in 0..threads {
626 r2.recv().unwrap();
627 }
628 });
629 drop(s1);
630 })
631 .unwrap();
632 }
633
634 #[bench]
635 fn mpsc(b: &mut Bencher) {
636 let threads = num_cpus::get() - 1;
637 let steps = TOTAL_STEPS / threads;
638 let (s, r) = bounded::<i32>(0);
639
640 let (s1, r1) = bounded(0);
641 let (s2, r2) = bounded(0);
642 scope(|scope| {
643 for _ in 0..threads {
644 scope.spawn(|_| {
645 while r1.recv().is_ok() {
646 for i in 0..steps {
647 s.send(i as i32).unwrap();
648 }
649 s2.send(()).unwrap();
650 }
651 });
652 }
653
654 b.iter(|| {
655 for _ in 0..threads {
656 s1.send(()).unwrap();
657 }
658 for _ in 0..steps * threads {
659 r.recv().unwrap();
660 }
661 for _ in 0..threads {
662 r2.recv().unwrap();
663 }
664 });
665 drop(s1);
666 })
667 .unwrap();
668 }
669
670 #[bench]
671 fn mpmc(b: &mut Bencher) {
672 let threads = num_cpus::get();
673 let steps = TOTAL_STEPS / threads;
674 let (s, r) = bounded::<i32>(0);
675
676 let (s1, r1) = bounded(0);
677 let (s2, r2) = bounded(0);
678 scope(|scope| {
679 for _ in 0..threads / 2 {
680 scope.spawn(|_| {
681 while r1.recv().is_ok() {
682 for i in 0..steps {
683 s.send(i as i32).unwrap();
684 }
685 s2.send(()).unwrap();
686 }
687 });
688 }
689 for _ in 0..threads / 2 {
690 scope.spawn(|_| {
691 while r1.recv().is_ok() {
692 for _ in 0..steps {
693 r.recv().unwrap();
694 }
695 s2.send(()).unwrap();
696 }
697 });
698 }
699
700 b.iter(|| {
701 for _ in 0..threads {
702 s1.send(()).unwrap();
703 }
704 for _ in 0..threads {
705 r2.recv().unwrap();
706 }
707 });
708 drop(s1);
709 })
710 .unwrap();
711 }
712}