Skip to content

benchmark v2.1.0 vs v2.0.26 2025‐09‐21

Adam Ning edited this page Sep 21, 2025 · 1 revision

Benchmark Result

NOTE

Due to the removal of the unnecessary atomic counter in the benchmark function, all scores are higher than the previous benchmarks. So we rerun benchmarks for v2.0 (v2.0.26), to know how much performance boost in v2.1.

In the charted image, "crossfire" is v2.1.0 (v2.0.26 scores has been excluded).

This time, we have added benchmark results of tokio::mpsc and async-channel.

Platform

  • Intel(R) Core(TM) i7-8550U 4 cores with 8 hyper-threads, turbo boost on
  • Ubuntu 24.04
  • rust 1.87.0
  • tokio 1.47.1
  • crossbeam v0.8.4
  • flume 0.11.1
  • kanal 0.1.1

async context (tokio)

bounded size 100 async

unit: million/s

mpsc bounded size 100 tokio 1x1 2x1 4x1 8x1 16x1
crossfire::spsc (v2.1.0) 37.116        
crossfire::mpsc (v2.1.0) 36.488 38.821 38.591 35.093 33.811   
crossfire::mpmc (v2.1.0) 35.456 38.902 37.981 34.914 33.462
crossfire::spsc (v2.0.26) 29.332        
crossfire::mpsc (v2.0.26) 28.444 30.417 29.889 23.823 22.909
crossfire::mpmc (v2.0.26) 27.122 31.419 30.194 24.028 23.145    
kanal 10.549 10.767 10.381 10.186 10.462
flume 7.9363 5.925 4.2317 2.6682 2.0159 
async-channel 6.0784 5.5772 5.0109 4.2245 3.6917  
tokio 6.4089 5.9596 4.847 3.4356 2.6008  

mpsc bounded size 100 tokio

mpmc bounded size 100 tokio 2x2 4x4 8x8 16x16
crossfire::mpmc (v2.1.0) 36.566 33.565 29.185 29.388
crossfire::mpmc (v2.0.26) 29.573 25.409 19.694 19.868
kanal  23.578 7.6766 17.652 19.327
flume 5.5305 3.8072 3.1198 2.8173
async-channel   5.677 4.9866 3.9711 3.764

mpmc bounded size 100 tokio

Bounded size 1 async

unit: million/s

mpsc bounded size 1 tokio 1x1 2x1 4x1 8x1 16x1
crossfire::spsc (v2.1) 5.4666        
crossfire::mpsc (v2.1) 5.4725 5.3884 5.3196 5.4943 6.419
crossfire::mpmc (v2.1) 5.1895 5.4266 5.1654 5.4779 6.4887
kanal 0.32689 0.38732 0.55014 0.81729 0.97879
flume 0.17626 0.24744 0.42052 0.56692 0.53564
async-channel 0.108 0.091666 0.082779 0.08482 0.085164

(The result of v2.0.26 is roughly the same as v2.1.0)

mpsc bounded size 1 tokio

Unbounded async

unit: million/s

mpsc unbounded tokio 1x1 2x1 4x1 8x1 16x1
crossfire::spsc (v2.1.0) 35.26        
crossfire::mpsc (v2.1.0) 35.54 37.859 35.043 35.707 35.451
crossfire::mpmc (v2.1.0) 35.599 36.817 35.138 35.436 35.985
crossfire::spsc (v2.0.26) 23.803        
crossfire::mpsc (v2.0.26) 23.899 29.339 27.604 29.411 29.195
crossfire::mpmc (v2.0.26) 24.01 29.9 27.733 29.138 28.987
kanal 36.054 38.284 32.155 28.497 31.057
flume 12.279 11.153 9.1671 7.5639 7.4911
async-channel 5.8421 5.0894 4.9306 4.2715 4.2476
tokio 5.1505 5.8724 8.1421 8.1421 7.9821

mpsc unbounded async

unit: million/s

mpmc ubounded tokio   2x2 4x4 8x8 16x16
crossfire::mpmc (v2.1.0)   36.787 34.391 34.438 34.026
crossfire::mpmc (v2.0.26)   29.6 28.002 27.229 27.643
kanal   29.896 19.624 16.905 18.758
flume   7.4458 4.3728 4.3213 4.5644
async-channel   4.9271 4.5423 4.1087 4.3246

mpmc unbounded async

blocking context

bounded size 100 blocking

unit: million/s

mpsc bounded size 100 blocking 1x1 2x1 4x1 8x1 16x1
crossfire::spsc 50.297        
crossfire::mpsc 49.308 50.976 47.487 43.966 39.538
crossfire::mpmc 48.365 48.336 49.379 47.541 39.919
crossbeam 30.81 31.817 28.523 33.881 33.278
kanal 24.679 30.299 23.54 18.938 17.71
flume 13.132 8.0159 3.3441 1.0544 0.51756

mpsc bounded size 100 blocking

mpmc bounded size 100 blocking  2x2 4x4 8x8 16x16
crossfire::mpmc  49.187 46.557 28.752 15.906
crossbeam   33.082 26.475 19.569 13.245
kanal 16.104 20.459 7.9588 9.6356
flume 6.8004 3.775 2.5744 2.0051

mpmc bounded size 100 blocking

bounded size 1 blocking

unit: million/s

mpsc bounded size 1 blocking 1x1 2x1 4x1 8x1 16x1
crossfire::spsc 4.3325        
crossfire::mpsc 4.3841 4.5029 5.2273 4.2731 4.4604
crossfire::mpmc 4.383 4.426 5.1816 4.7245 3.8124
crossbeam 4.8877 4.7712 5.5047 5.5022 5.8586
kanal 2.7992 2.9495 2.4648 1.6127 1.4414
flume 0.4225 0.50063 0.55053 0.39121 0.30535

mpsc bounded size 1 blocking

unbounded blocking

unit: million/s

mpsc unbounded blocking 1x1 2x1 4x1 8x1 16x1
crossfire(spsc) 40.057        
crossfire(mpsc) 40.259 39.197 38.479 37.964 37.871
crossfire(mpmc) 40.187 37.998 39.35 37.007 38.424
crossbeam 28.095 41.119 38.08 39.705 39.771
kanal 28.146 39.225 37.825 23.933 24.65
flume 12.445 10.086 9.1263 7.3567 7.2426

mpsc unbounded blocking

mpmc unbounded blocking  2x2 4x4 8x8 16x16
crossfire(mpmc)  39.022 37.306 38.913 30.729
crossbeam 40.445 37.37 39.01 38.949
kanal 17.218 21.637 22.024 14.515
flume 8.1359 4.8267 4.1219 4.2847

mpmc unbounded blocking

Problem and Analysis

  • In async context, crossfire v2.1 achieves +26% performance, by removing the notification layer (which is of no use for us) in crossbeam-channel.

  • In blocking context, crossfire v2.1 bounded size-100 surpasses crossbeam, because crossfire only wakes one waker after one message ideally, while crossbeam wakes all senders/receivers, and optimizes the functions in crossbeam-queue to reduce moving in full condition. Meanwhile, for size-1 case, crossfire is slightly slower than crossbeam; although the backoff pattern is the same, the reason is still unknown.

  • kanal unbounded channel might grow the allocation aggressively, without shrinking, a bit faster than crossbeam. Crossfire is roughly the same as Kanal, although we use the same queue as Crossbeam, slightly faster due to the removal of the notification layer.

  • The speed of Kanal fluctuated during benchmark, non-regularly changing upon increasing the concurrency.

Clone this wiki locally