├── .gitattributes ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── analyze.py ├── inter_latencies ├── async │ └── .gitignore └── busy │ └── .gitignore ├── intra_latencies ├── async_multi_thread │ └── .gitignore └── async_single_thread │ └── .gitignore └── src ├── main.rs └── utils └── mod.rs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | *.svg 3 | perf.* 4 | .gdb_history 5 | /.mypy_cache 6 | /__pycache__ 7 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "async-broadcast" 31 | version = "0.7.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "258b52a1aa741b9f09783b2d86cf0aeeb617bbf847f6933340a39644227acbdb" 34 | dependencies = [ 35 | "event-listener", 36 | "event-listener-strategy", 37 | "futures-core", 38 | "pin-project-lite", 39 | ] 40 | 41 | [[package]] 42 | name = "async-channel" 43 | version = "2.2.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" 46 | dependencies = [ 47 | "concurrent-queue", 48 | "event-listener", 49 | "event-listener-strategy", 50 | "futures-core", 51 | "pin-project-lite", 52 | ] 53 | 54 | [[package]] 55 | name = "async-event" 56 | version = "0.1.0" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "4172595da7ffb68640606be5723e35a353555f2829e9209437627a003725bbdb" 59 | dependencies = [ 60 | "loom", 61 | ] 62 | 63 | [[package]] 64 | name = "async-trait" 65 | version = "0.1.79" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" 68 | dependencies = [ 69 | "proc-macro2", 70 | "quote", 71 | "syn 2.0.57", 72 | ] 73 | 74 | [[package]] 75 | name = "atomic" 76 | version = "0.5.3" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" 79 | 80 | [[package]] 81 | name = "autocfg" 82 | version = "1.2.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" 85 | 86 | [[package]] 87 | name = "backtrace" 88 | version = "0.3.71" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 91 | dependencies = [ 92 | "addr2line", 93 | "cc", 94 | "cfg-if", 95 | "libc", 96 | "miniz_oxide", 97 | "object", 98 | "rustc-demangle", 99 | ] 100 | 101 | [[package]] 102 | name = "bitflags" 103 | version = "1.3.2" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 106 | 107 | [[package]] 108 | name = "bumpalo" 109 | version = "3.15.4" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" 112 | 113 | [[package]] 114 | name = "bytes" 115 | version = "1.6.0" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 118 | 119 | [[package]] 120 | name = "cc" 121 | version = "1.0.90" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" 124 | 125 | [[package]] 126 | name = "cfg-if" 127 | version = "1.0.0" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 130 | 131 | [[package]] 132 | name = "concurrent-queue" 133 | version = "2.4.0" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" 136 | dependencies = [ 137 | "crossbeam-utils", 138 | ] 139 | 140 | [[package]] 141 | name = "core_affinity" 142 | version = "0.8.1" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "622892f5635ce1fc38c8f16dfc938553ed64af482edb5e150bf4caedbfcb2304" 145 | dependencies = [ 146 | "libc", 147 | "num_cpus", 148 | "winapi", 149 | ] 150 | 151 | [[package]] 152 | name = "crossbeam" 153 | version = "0.8.4" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" 156 | dependencies = [ 157 | "crossbeam-channel", 158 | "crossbeam-deque", 159 | "crossbeam-epoch", 160 | "crossbeam-queue", 161 | "crossbeam-utils", 162 | ] 163 | 164 | [[package]] 165 | name = "crossbeam-channel" 166 | version = "0.5.12" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" 169 | dependencies = [ 170 | "crossbeam-utils", 171 | ] 172 | 173 | [[package]] 174 | name = "crossbeam-deque" 175 | version = "0.8.5" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 178 | dependencies = [ 179 | "crossbeam-epoch", 180 | "crossbeam-utils", 181 | ] 182 | 183 | [[package]] 184 | name = "crossbeam-epoch" 185 | version = "0.9.18" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 188 | dependencies = [ 189 | "crossbeam-utils", 190 | ] 191 | 192 | [[package]] 193 | name = "crossbeam-queue" 194 | version = "0.3.11" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" 197 | dependencies = [ 198 | "crossbeam-utils", 199 | ] 200 | 201 | [[package]] 202 | name = "crossbeam-utils" 203 | version = "0.8.19" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" 206 | 207 | [[package]] 208 | name = "crossfire" 209 | version = "1.0.1" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "27e3e43d24a1359c5f1ba9ed36bcded70f0226fc5ad535826ee6cb1a7c07db5c" 212 | dependencies = [ 213 | "async-trait", 214 | "crossbeam", 215 | "futures", 216 | ] 217 | 218 | [[package]] 219 | name = "ctor" 220 | version = "0.1.26" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" 223 | dependencies = [ 224 | "quote", 225 | "syn 1.0.109", 226 | ] 227 | 228 | [[package]] 229 | name = "diatomic-waker" 230 | version = "0.1.0" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "28025fb55a9d815acf7b0877555f437254f373036eec6ed265116c7a5c0825e9" 233 | dependencies = [ 234 | "loom", 235 | "waker-fn", 236 | ] 237 | 238 | [[package]] 239 | name = "event-listener" 240 | version = "5.2.0" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" 243 | dependencies = [ 244 | "concurrent-queue", 245 | "parking", 246 | "pin-project-lite", 247 | ] 248 | 249 | [[package]] 250 | name = "event-listener-strategy" 251 | version = "0.5.1" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" 254 | dependencies = [ 255 | "event-listener", 256 | "pin-project-lite", 257 | ] 258 | 259 | [[package]] 260 | name = "flume" 261 | version = "0.11.0" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" 264 | dependencies = [ 265 | "futures-core", 266 | "futures-sink", 267 | "nanorand", 268 | "spin", 269 | ] 270 | 271 | [[package]] 272 | name = "futures" 273 | version = "0.3.30" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" 276 | dependencies = [ 277 | "futures-channel", 278 | "futures-core", 279 | "futures-executor", 280 | "futures-io", 281 | "futures-sink", 282 | "futures-task", 283 | "futures-util", 284 | ] 285 | 286 | [[package]] 287 | name = "futures-channel" 288 | version = "0.3.30" 289 | source = "registry+https://github.com/rust-lang/crates.io-index" 290 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 291 | dependencies = [ 292 | "futures-core", 293 | "futures-sink", 294 | ] 295 | 296 | [[package]] 297 | name = "futures-core" 298 | version = "0.3.30" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 301 | 302 | [[package]] 303 | name = "futures-executor" 304 | version = "0.3.30" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" 307 | dependencies = [ 308 | "futures-core", 309 | "futures-task", 310 | "futures-util", 311 | ] 312 | 313 | [[package]] 314 | name = "futures-io" 315 | version = "0.3.30" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 318 | 319 | [[package]] 320 | name = "futures-macro" 321 | version = "0.3.30" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 324 | dependencies = [ 325 | "proc-macro2", 326 | "quote", 327 | "syn 2.0.57", 328 | ] 329 | 330 | [[package]] 331 | name = "futures-sink" 332 | version = "0.3.30" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 335 | 336 | [[package]] 337 | name = "futures-task" 338 | version = "0.3.30" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 341 | 342 | [[package]] 343 | name = "futures-util" 344 | version = "0.3.30" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 347 | dependencies = [ 348 | "futures-channel", 349 | "futures-core", 350 | "futures-io", 351 | "futures-macro", 352 | "futures-sink", 353 | "futures-task", 354 | "memchr", 355 | "pin-project-lite", 356 | "pin-utils", 357 | "slab", 358 | ] 359 | 360 | [[package]] 361 | name = "generator" 362 | version = "0.7.5" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" 365 | dependencies = [ 366 | "cc", 367 | "libc", 368 | "log", 369 | "rustversion", 370 | "windows", 371 | ] 372 | 373 | [[package]] 374 | name = "getrandom" 375 | version = "0.2.12" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" 378 | dependencies = [ 379 | "cfg-if", 380 | "js-sys", 381 | "libc", 382 | "wasi", 383 | "wasm-bindgen", 384 | ] 385 | 386 | [[package]] 387 | name = "gimli" 388 | version = "0.28.1" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 391 | 392 | [[package]] 393 | name = "hazard" 394 | version = "0.3.1" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "0de21a47b2ccd944b16d6cc6b8e40ecf212099b5cd03ada2ae2e733f8cb802f1" 397 | 398 | [[package]] 399 | name = "hermit-abi" 400 | version = "0.3.9" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 403 | 404 | [[package]] 405 | name = "js-sys" 406 | version = "0.3.69" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" 409 | dependencies = [ 410 | "wasm-bindgen", 411 | ] 412 | 413 | [[package]] 414 | name = "kanal" 415 | version = "0.1.0-pre8" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "b05d55519627edaf7fd0f29981f6dc03fb52df3f5b257130eb8d0bf2801ea1d7" 418 | dependencies = [ 419 | "futures-core", 420 | "lock_api", 421 | ] 422 | 423 | [[package]] 424 | name = "lazy_static" 425 | version = "1.4.0" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 428 | 429 | [[package]] 430 | name = "libc" 431 | version = "0.2.153" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 434 | 435 | [[package]] 436 | name = "lock_api" 437 | version = "0.4.11" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" 440 | dependencies = [ 441 | "autocfg", 442 | "scopeguard", 443 | ] 444 | 445 | [[package]] 446 | name = "log" 447 | version = "0.4.21" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 450 | 451 | [[package]] 452 | name = "loom" 453 | version = "0.5.6" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" 456 | dependencies = [ 457 | "cfg-if", 458 | "generator", 459 | "scoped-tls", 460 | "tracing", 461 | "tracing-subscriber", 462 | ] 463 | 464 | [[package]] 465 | name = "magnetic" 466 | version = "2.4.1" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "fdf478b1bdf6a482a166b519c12af5c007459a39df0290015ac7e51aee84ea07" 469 | dependencies = [ 470 | "crossbeam-utils", 471 | ] 472 | 473 | [[package]] 474 | name = "matchers" 475 | version = "0.1.0" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 478 | dependencies = [ 479 | "regex-automata 0.1.10", 480 | ] 481 | 482 | [[package]] 483 | name = "memchr" 484 | version = "2.7.2" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" 487 | 488 | [[package]] 489 | name = "miniz_oxide" 490 | version = "0.7.2" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" 493 | dependencies = [ 494 | "adler", 495 | ] 496 | 497 | [[package]] 498 | name = "minstant" 499 | version = "0.1.7" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | checksum = "1fb9b5c752f145ac5046bccc3c4f62892e3c950c1d1eab80c5949cd68a2078db" 502 | dependencies = [ 503 | "ctor", 504 | "web-time", 505 | ] 506 | 507 | [[package]] 508 | name = "mio" 509 | version = "0.8.11" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 512 | dependencies = [ 513 | "libc", 514 | "wasi", 515 | "windows-sys 0.48.0", 516 | ] 517 | 518 | [[package]] 519 | name = "nanorand" 520 | version = "0.7.0" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" 523 | dependencies = [ 524 | "getrandom", 525 | ] 526 | 527 | [[package]] 528 | name = "npnc" 529 | version = "0.2.1" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "6825af9328c9f24a0e2502e5aaf12612006790683314c1a86989dc93f0cf94d5" 532 | dependencies = [ 533 | "hazard", 534 | ] 535 | 536 | [[package]] 537 | name = "nu-ansi-term" 538 | version = "0.46.0" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 541 | dependencies = [ 542 | "overload", 543 | "winapi", 544 | ] 545 | 546 | [[package]] 547 | name = "num_cpus" 548 | version = "1.16.0" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 551 | dependencies = [ 552 | "hermit-abi", 553 | "libc", 554 | ] 555 | 556 | [[package]] 557 | name = "object" 558 | version = "0.32.2" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 561 | dependencies = [ 562 | "memchr", 563 | ] 564 | 565 | [[package]] 566 | name = "omango" 567 | version = "0.2.2" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "7d9e476d89068bba14cb87ec38fa5b8ee5cd6769362812c4041a8c910d4ef63b" 570 | dependencies = [ 571 | "omango-futex", 572 | "omango-util", 573 | "parking_lot", 574 | ] 575 | 576 | [[package]] 577 | name = "omango-futex" 578 | version = "0.1.1" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "fab7f930f5f15a7edd922793b8809086084c0bc2b6255d68b7c171e1f1cabdca" 581 | dependencies = [ 582 | "libc", 583 | "omango-util", 584 | "windows-sys 0.48.0", 585 | ] 586 | 587 | [[package]] 588 | name = "omango-util" 589 | version = "0.1.0" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "81c6ab8daab53f3435d15b89e30c96642aa00861aa3a047489985932e12230bd" 592 | 593 | [[package]] 594 | name = "once_cell" 595 | version = "1.19.0" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 598 | 599 | [[package]] 600 | name = "overload" 601 | version = "0.1.1" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 604 | 605 | [[package]] 606 | name = "parking" 607 | version = "2.2.0" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" 610 | 611 | [[package]] 612 | name = "parking_lot" 613 | version = "0.12.1" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 616 | dependencies = [ 617 | "lock_api", 618 | "parking_lot_core", 619 | ] 620 | 621 | [[package]] 622 | name = "parking_lot_core" 623 | version = "0.9.9" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" 626 | dependencies = [ 627 | "cfg-if", 628 | "libc", 629 | "redox_syscall", 630 | "smallvec", 631 | "windows-targets 0.48.5", 632 | ] 633 | 634 | [[package]] 635 | name = "pin-project" 636 | version = "1.1.5" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" 639 | dependencies = [ 640 | "pin-project-internal", 641 | ] 642 | 643 | [[package]] 644 | name = "pin-project-internal" 645 | version = "1.1.5" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" 648 | dependencies = [ 649 | "proc-macro2", 650 | "quote", 651 | "syn 2.0.57", 652 | ] 653 | 654 | [[package]] 655 | name = "pin-project-lite" 656 | version = "0.2.14" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 659 | 660 | [[package]] 661 | name = "pin-utils" 662 | version = "0.1.0" 663 | source = "registry+https://github.com/rust-lang/crates.io-index" 664 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 665 | 666 | [[package]] 667 | name = "pollster" 668 | version = "0.2.5" 669 | source = "registry+https://github.com/rust-lang/crates.io-index" 670 | checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" 671 | 672 | [[package]] 673 | name = "postage" 674 | version = "0.5.0" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "af3fb618632874fb76937c2361a7f22afd393c982a2165595407edc75b06d3c1" 677 | dependencies = [ 678 | "atomic", 679 | "crossbeam-queue", 680 | "log", 681 | "parking_lot", 682 | "pin-project", 683 | "pollster", 684 | "static_assertions", 685 | "thiserror", 686 | ] 687 | 688 | [[package]] 689 | name = "ppv-lite86" 690 | version = "0.2.17" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 693 | 694 | [[package]] 695 | name = "proc-macro2" 696 | version = "1.0.79" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" 699 | dependencies = [ 700 | "unicode-ident", 701 | ] 702 | 703 | [[package]] 704 | name = "quote" 705 | version = "1.0.35" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 708 | dependencies = [ 709 | "proc-macro2", 710 | ] 711 | 712 | [[package]] 713 | name = "rand" 714 | version = "0.8.5" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 717 | dependencies = [ 718 | "libc", 719 | "rand_chacha", 720 | "rand_core", 721 | ] 722 | 723 | [[package]] 724 | name = "rand_chacha" 725 | version = "0.3.1" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 728 | dependencies = [ 729 | "ppv-lite86", 730 | "rand_core", 731 | ] 732 | 733 | [[package]] 734 | name = "rand_core" 735 | version = "0.6.4" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 738 | dependencies = [ 739 | "getrandom", 740 | ] 741 | 742 | [[package]] 743 | name = "redox_syscall" 744 | version = "0.4.1" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 747 | dependencies = [ 748 | "bitflags", 749 | ] 750 | 751 | [[package]] 752 | name = "regex" 753 | version = "1.10.4" 754 | source = "registry+https://github.com/rust-lang/crates.io-index" 755 | checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" 756 | dependencies = [ 757 | "aho-corasick", 758 | "memchr", 759 | "regex-automata 0.4.6", 760 | "regex-syntax 0.8.3", 761 | ] 762 | 763 | [[package]] 764 | name = "regex-automata" 765 | version = "0.1.10" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 768 | dependencies = [ 769 | "regex-syntax 0.6.29", 770 | ] 771 | 772 | [[package]] 773 | name = "regex-automata" 774 | version = "0.4.6" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" 777 | dependencies = [ 778 | "aho-corasick", 779 | "memchr", 780 | "regex-syntax 0.8.3", 781 | ] 782 | 783 | [[package]] 784 | name = "regex-syntax" 785 | version = "0.6.29" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 788 | 789 | [[package]] 790 | name = "regex-syntax" 791 | version = "0.8.3" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" 794 | 795 | [[package]] 796 | name = "ringbuf" 797 | version = "0.3.3" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "79abed428d1fd2a128201cec72c5f6938e2da607c6f3745f769fabea399d950a" 800 | dependencies = [ 801 | "crossbeam-utils", 802 | ] 803 | 804 | [[package]] 805 | name = "rtrb" 806 | version = "0.3.0" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "636b228b5adb32add7f0e41e5084d38aa66fb0f942e8a91751c1e90023288fbe" 809 | dependencies = [ 810 | "crossbeam-utils", 811 | ] 812 | 813 | [[package]] 814 | name = "rust-channel-benchmark" 815 | version = "0.1.0" 816 | dependencies = [ 817 | "async-broadcast", 818 | "async-channel", 819 | "core_affinity", 820 | "crossbeam-channel", 821 | "crossbeam-queue", 822 | "crossfire", 823 | "flume", 824 | "futures-channel", 825 | "kanal", 826 | "magnetic", 827 | "minstant", 828 | "npnc", 829 | "omango", 830 | "postage", 831 | "rand", 832 | "ringbuf", 833 | "rtrb", 834 | "tachyonix", 835 | "thingbuf", 836 | "tokio", 837 | ] 838 | 839 | [[package]] 840 | name = "rustc-demangle" 841 | version = "0.1.23" 842 | source = "registry+https://github.com/rust-lang/crates.io-index" 843 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 844 | 845 | [[package]] 846 | name = "rustversion" 847 | version = "1.0.14" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" 850 | 851 | [[package]] 852 | name = "scoped-tls" 853 | version = "1.0.1" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" 856 | 857 | [[package]] 858 | name = "scopeguard" 859 | version = "1.2.0" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 862 | 863 | [[package]] 864 | name = "sharded-slab" 865 | version = "0.1.7" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 868 | dependencies = [ 869 | "lazy_static", 870 | ] 871 | 872 | [[package]] 873 | name = "signal-hook-registry" 874 | version = "1.4.1" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 877 | dependencies = [ 878 | "libc", 879 | ] 880 | 881 | [[package]] 882 | name = "slab" 883 | version = "0.4.9" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 886 | dependencies = [ 887 | "autocfg", 888 | ] 889 | 890 | [[package]] 891 | name = "smallvec" 892 | version = "1.13.2" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 895 | 896 | [[package]] 897 | name = "socket2" 898 | version = "0.5.6" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" 901 | dependencies = [ 902 | "libc", 903 | "windows-sys 0.52.0", 904 | ] 905 | 906 | [[package]] 907 | name = "spin" 908 | version = "0.9.8" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 911 | dependencies = [ 912 | "lock_api", 913 | ] 914 | 915 | [[package]] 916 | name = "static_assertions" 917 | version = "1.1.0" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 920 | 921 | [[package]] 922 | name = "syn" 923 | version = "1.0.109" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 926 | dependencies = [ 927 | "proc-macro2", 928 | "quote", 929 | "unicode-ident", 930 | ] 931 | 932 | [[package]] 933 | name = "syn" 934 | version = "2.0.57" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" 937 | dependencies = [ 938 | "proc-macro2", 939 | "quote", 940 | "unicode-ident", 941 | ] 942 | 943 | [[package]] 944 | name = "tachyonix" 945 | version = "0.2.1" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "64e0bf82be3359dbefbfea621d6365db00e1d7846561daad2ea74cc4cb4c9604" 948 | dependencies = [ 949 | "async-event", 950 | "crossbeam-utils", 951 | "diatomic-waker", 952 | "futures-core", 953 | "loom", 954 | ] 955 | 956 | [[package]] 957 | name = "thingbuf" 958 | version = "0.1.4" 959 | source = "registry+https://github.com/rust-lang/crates.io-index" 960 | checksum = "4706f1bfb859af03f099ada2de3cea3e515843c2d3e93b7893f16d94a37f9415" 961 | dependencies = [ 962 | "parking_lot", 963 | "pin-project", 964 | ] 965 | 966 | [[package]] 967 | name = "thiserror" 968 | version = "1.0.58" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" 971 | dependencies = [ 972 | "thiserror-impl", 973 | ] 974 | 975 | [[package]] 976 | name = "thiserror-impl" 977 | version = "1.0.58" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" 980 | dependencies = [ 981 | "proc-macro2", 982 | "quote", 983 | "syn 2.0.57", 984 | ] 985 | 986 | [[package]] 987 | name = "thread_local" 988 | version = "1.1.8" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 991 | dependencies = [ 992 | "cfg-if", 993 | "once_cell", 994 | ] 995 | 996 | [[package]] 997 | name = "tokio" 998 | version = "1.37.0" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" 1001 | dependencies = [ 1002 | "backtrace", 1003 | "bytes", 1004 | "libc", 1005 | "mio", 1006 | "num_cpus", 1007 | "parking_lot", 1008 | "pin-project-lite", 1009 | "signal-hook-registry", 1010 | "socket2", 1011 | "tokio-macros", 1012 | "windows-sys 0.48.0", 1013 | ] 1014 | 1015 | [[package]] 1016 | name = "tokio-macros" 1017 | version = "2.2.0" 1018 | source = "registry+https://github.com/rust-lang/crates.io-index" 1019 | checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" 1020 | dependencies = [ 1021 | "proc-macro2", 1022 | "quote", 1023 | "syn 2.0.57", 1024 | ] 1025 | 1026 | [[package]] 1027 | name = "tracing" 1028 | version = "0.1.40" 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" 1030 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1031 | dependencies = [ 1032 | "pin-project-lite", 1033 | "tracing-attributes", 1034 | "tracing-core", 1035 | ] 1036 | 1037 | [[package]] 1038 | name = "tracing-attributes" 1039 | version = "0.1.27" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 1042 | dependencies = [ 1043 | "proc-macro2", 1044 | "quote", 1045 | "syn 2.0.57", 1046 | ] 1047 | 1048 | [[package]] 1049 | name = "tracing-core" 1050 | version = "0.1.32" 1051 | source = "registry+https://github.com/rust-lang/crates.io-index" 1052 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1053 | dependencies = [ 1054 | "once_cell", 1055 | "valuable", 1056 | ] 1057 | 1058 | [[package]] 1059 | name = "tracing-log" 1060 | version = "0.2.0" 1061 | source = "registry+https://github.com/rust-lang/crates.io-index" 1062 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 1063 | dependencies = [ 1064 | "log", 1065 | "once_cell", 1066 | "tracing-core", 1067 | ] 1068 | 1069 | [[package]] 1070 | name = "tracing-subscriber" 1071 | version = "0.3.18" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" 1074 | dependencies = [ 1075 | "matchers", 1076 | "nu-ansi-term", 1077 | "once_cell", 1078 | "regex", 1079 | "sharded-slab", 1080 | "smallvec", 1081 | "thread_local", 1082 | "tracing", 1083 | "tracing-core", 1084 | "tracing-log", 1085 | ] 1086 | 1087 | [[package]] 1088 | name = "unicode-ident" 1089 | version = "1.0.12" 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" 1091 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1092 | 1093 | [[package]] 1094 | name = "valuable" 1095 | version = "0.1.0" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 1098 | 1099 | [[package]] 1100 | name = "waker-fn" 1101 | version = "1.1.1" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" 1104 | 1105 | [[package]] 1106 | name = "wasi" 1107 | version = "0.11.0+wasi-snapshot-preview1" 1108 | source = "registry+https://github.com/rust-lang/crates.io-index" 1109 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1110 | 1111 | [[package]] 1112 | name = "wasm-bindgen" 1113 | version = "0.2.92" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" 1116 | dependencies = [ 1117 | "cfg-if", 1118 | "wasm-bindgen-macro", 1119 | ] 1120 | 1121 | [[package]] 1122 | name = "wasm-bindgen-backend" 1123 | version = "0.2.92" 1124 | source = "registry+https://github.com/rust-lang/crates.io-index" 1125 | checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" 1126 | dependencies = [ 1127 | "bumpalo", 1128 | "log", 1129 | "once_cell", 1130 | "proc-macro2", 1131 | "quote", 1132 | "syn 2.0.57", 1133 | "wasm-bindgen-shared", 1134 | ] 1135 | 1136 | [[package]] 1137 | name = "wasm-bindgen-macro" 1138 | version = "0.2.92" 1139 | source = "registry+https://github.com/rust-lang/crates.io-index" 1140 | checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" 1141 | dependencies = [ 1142 | "quote", 1143 | "wasm-bindgen-macro-support", 1144 | ] 1145 | 1146 | [[package]] 1147 | name = "wasm-bindgen-macro-support" 1148 | version = "0.2.92" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" 1151 | dependencies = [ 1152 | "proc-macro2", 1153 | "quote", 1154 | "syn 2.0.57", 1155 | "wasm-bindgen-backend", 1156 | "wasm-bindgen-shared", 1157 | ] 1158 | 1159 | [[package]] 1160 | name = "wasm-bindgen-shared" 1161 | version = "0.2.92" 1162 | source = "registry+https://github.com/rust-lang/crates.io-index" 1163 | checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" 1164 | 1165 | [[package]] 1166 | name = "web-time" 1167 | version = "1.1.0" 1168 | source = "registry+https://github.com/rust-lang/crates.io-index" 1169 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 1170 | dependencies = [ 1171 | "js-sys", 1172 | "wasm-bindgen", 1173 | ] 1174 | 1175 | [[package]] 1176 | name = "winapi" 1177 | version = "0.3.9" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1180 | dependencies = [ 1181 | "winapi-i686-pc-windows-gnu", 1182 | "winapi-x86_64-pc-windows-gnu", 1183 | ] 1184 | 1185 | [[package]] 1186 | name = "winapi-i686-pc-windows-gnu" 1187 | version = "0.4.0" 1188 | source = "registry+https://github.com/rust-lang/crates.io-index" 1189 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1190 | 1191 | [[package]] 1192 | name = "winapi-x86_64-pc-windows-gnu" 1193 | version = "0.4.0" 1194 | source = "registry+https://github.com/rust-lang/crates.io-index" 1195 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1196 | 1197 | [[package]] 1198 | name = "windows" 1199 | version = "0.48.0" 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" 1201 | checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" 1202 | dependencies = [ 1203 | "windows-targets 0.48.5", 1204 | ] 1205 | 1206 | [[package]] 1207 | name = "windows-sys" 1208 | version = "0.48.0" 1209 | source = "registry+https://github.com/rust-lang/crates.io-index" 1210 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1211 | dependencies = [ 1212 | "windows-targets 0.48.5", 1213 | ] 1214 | 1215 | [[package]] 1216 | name = "windows-sys" 1217 | version = "0.52.0" 1218 | source = "registry+https://github.com/rust-lang/crates.io-index" 1219 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1220 | dependencies = [ 1221 | "windows-targets 0.52.4", 1222 | ] 1223 | 1224 | [[package]] 1225 | name = "windows-targets" 1226 | version = "0.48.5" 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" 1228 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1229 | dependencies = [ 1230 | "windows_aarch64_gnullvm 0.48.5", 1231 | "windows_aarch64_msvc 0.48.5", 1232 | "windows_i686_gnu 0.48.5", 1233 | "windows_i686_msvc 0.48.5", 1234 | "windows_x86_64_gnu 0.48.5", 1235 | "windows_x86_64_gnullvm 0.48.5", 1236 | "windows_x86_64_msvc 0.48.5", 1237 | ] 1238 | 1239 | [[package]] 1240 | name = "windows-targets" 1241 | version = "0.52.4" 1242 | source = "registry+https://github.com/rust-lang/crates.io-index" 1243 | checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" 1244 | dependencies = [ 1245 | "windows_aarch64_gnullvm 0.52.4", 1246 | "windows_aarch64_msvc 0.52.4", 1247 | "windows_i686_gnu 0.52.4", 1248 | "windows_i686_msvc 0.52.4", 1249 | "windows_x86_64_gnu 0.52.4", 1250 | "windows_x86_64_gnullvm 0.52.4", 1251 | "windows_x86_64_msvc 0.52.4", 1252 | ] 1253 | 1254 | [[package]] 1255 | name = "windows_aarch64_gnullvm" 1256 | version = "0.48.5" 1257 | source = "registry+https://github.com/rust-lang/crates.io-index" 1258 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1259 | 1260 | [[package]] 1261 | name = "windows_aarch64_gnullvm" 1262 | version = "0.52.4" 1263 | source = "registry+https://github.com/rust-lang/crates.io-index" 1264 | checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" 1265 | 1266 | [[package]] 1267 | name = "windows_aarch64_msvc" 1268 | version = "0.48.5" 1269 | source = "registry+https://github.com/rust-lang/crates.io-index" 1270 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1271 | 1272 | [[package]] 1273 | name = "windows_aarch64_msvc" 1274 | version = "0.52.4" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" 1277 | 1278 | [[package]] 1279 | name = "windows_i686_gnu" 1280 | version = "0.48.5" 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" 1282 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1283 | 1284 | [[package]] 1285 | name = "windows_i686_gnu" 1286 | version = "0.52.4" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" 1289 | 1290 | [[package]] 1291 | name = "windows_i686_msvc" 1292 | version = "0.48.5" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1295 | 1296 | [[package]] 1297 | name = "windows_i686_msvc" 1298 | version = "0.52.4" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" 1301 | 1302 | [[package]] 1303 | name = "windows_x86_64_gnu" 1304 | version = "0.48.5" 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" 1306 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1307 | 1308 | [[package]] 1309 | name = "windows_x86_64_gnu" 1310 | version = "0.52.4" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" 1313 | 1314 | [[package]] 1315 | name = "windows_x86_64_gnullvm" 1316 | version = "0.48.5" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1319 | 1320 | [[package]] 1321 | name = "windows_x86_64_gnullvm" 1322 | version = "0.52.4" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" 1325 | 1326 | [[package]] 1327 | name = "windows_x86_64_msvc" 1328 | version = "0.48.5" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1331 | 1332 | [[package]] 1333 | name = "windows_x86_64_msvc" 1334 | version = "0.52.4" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" 1337 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-channel-benchmark" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | core_affinity = "0.8.1" 10 | tokio = { version = "1.37.0", features = ["full"] } 11 | minstant = "0.1.7" 12 | rand = "0.8.5" 13 | 14 | 15 | kanal = "0.1.0-pre8" 16 | flume = "0.11.0" 17 | async-channel = "2.2.0" 18 | futures-channel = "0.3.30" 19 | crossfire = "1.0.1" 20 | thingbuf = "0.1.4" 21 | tachyonix = "0.2.1" 22 | postage = "0.5.0" 23 | async-broadcast = "0.7.0" 24 | 25 | 26 | rtrb = "0.3.0" 27 | ringbuf = "0.3.3" 28 | crossbeam-channel = "0.5.12" 29 | crossbeam-queue = "0.3.11" 30 | omango = "0.2.2" 31 | npnc = "0.2.1" 32 | magnetic = "2.4.1" 33 | 34 | 35 | [profile.release] 36 | debug = true 37 | 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # On-Site Rust Channel Benchmarking Helper 2 | 3 | Deploy on server to determine which public crates are the fastest for communicating in different architectures 4 | 5 | ### Requirements: 6 | - 2 CPUs are needed for most of the experiments. Please refer to `main()` to change which cores you'd like to be utilized before running. 7 | 8 | ## Analysis Pipeline 9 | 1. `cargo run --release` 10 | 2. Once the experiments are completed, run `python3 analyze.py` to view the results and the corresponding latency distributions 11 | 12 | ## Crates tested by Architecture: 13 | ### Async 14 | - Kanal (https://crates.io/crates/kanal) 15 | - Flume (https://crates.io/crates/flume) 16 | - Tokio (https://crates.io/crates/tokio) 17 | - Async_Channel (https://crates.io/crates/async-channel) 18 | - Crossfire (https://crates.io/crates/crossfire) 19 | - Thingbuf (https://crates.io/crates/thingbuf) 20 | - Tachyonix (https://crates.io/crates/tachyonix) 21 | - Postage (https://crates.io/crates/postage) 22 | - Async_Broadcast (https://crates.io/crates/async-broadcast) 23 | ### Busy-Spinning 24 | - Rtrb (https://crates.io/crates/rtrb) 25 | - Ringbuf (https://crates.io/crates/ringbuf) 26 | - Crossbeam-channel (https://crates.io/crates/crossbeam-channel) 27 | - Crossbeam-queue (https://crates.io/crates/crossbeam-queue) 28 | - Kanal (https://crates.io/crates/kanal) 29 | - Flume (https://crates.io/crates/flume) 30 | - Omango (https://crates.io/crates/omango) 31 | - Npnc (https://crates.io/crates/npnc) 32 | - Magnetic (https://crates.io/crates/magnetic) 33 | - Tokio (https://crates.io/crates/tokio) 34 | 35 | 36 | ## Future Plans 37 | I'd like to split up the experiments to test `mpmc` / `mpsc` / `spsc` against each other in these different architectures. This will be included at some point but for now `mpmc` & `mpsc` have been favored as there are more use cases for them 38 | 39 | ## Notes 40 | - Some of these crates (such as `async_broadcast`) are tailored to specific features which incur some speed disadvantages. Thus, I recommend doing adequate research to determine the best crate for your architecture and only use this as a reference. 41 | - Thread-pinning has been included in most of these experiments so please check the `main()` function and change the parameters as needed. If you'd like more realistic non-jittery results, consider using `isolcpus` or the like 42 | - `payload_size` parameter was included in `main()` as well, feel free to change this at your discretion. The default is 0 bytes 43 | 44 | 45 | ### P.s. 46 | If you'd like another crate added, have questions / ideas, please DM me on twitter `@Dub0x3A` or on discord `0xdub`. Cheers and thanks -------------------------------------------------------------------------------- /analyze.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import pandas as pd 3 | 4 | plt.style.use("dark_background") 5 | 6 | 7 | class bcolors: 8 | HEADER = "\033[95m" 9 | OKBLUE = "\033[94m" 10 | OKCYAN = "\033[96m" 11 | OKGREEN = "\033[92m" 12 | WARNING = "\033[93m" 13 | FAIL = "\033[91m" 14 | ENDC = "\033[0m" 15 | BOLD = "\033[1m" 16 | DIM = "\033[2m" 17 | UNDERLINE = "\033[4m" 18 | 19 | 20 | # =------------------------------------------------------------= # 21 | def get_available_colors(): 22 | return [ 23 | "#21fced", 24 | "#21fc80", 25 | "#fc2130", 26 | "#219efc", 27 | "#ed21fc", 28 | "#8021fc", 29 | "#30fc21", 30 | "#fc8021", 31 | "#FFFF00", 32 | "#FDECA0", 33 | "#FF00FF", 34 | "#00FFFF", 35 | "#FF0000", 36 | "#00FF00", 37 | "#0000FF", 38 | "#FF8000", 39 | "#FF0080", 40 | "#80FF00", 41 | "#80FF00", 42 | "#0080FF", 43 | "#8000FF", 44 | "#FF8080", 45 | "#80FF80", 46 | "#8080FF", 47 | "#FF80FF", 48 | "#80FFFF", 49 | "#FF80FF", 50 | "#FFFF80", 51 | "#FF8000", 52 | "#FF0080", 53 | "#80FF00", 54 | "#80FF00", 55 | "#0080FF", 56 | "#8000FF", 57 | "#FF8080", 58 | "#80FF80", 59 | "#8080FF", 60 | "#FF80FF", 61 | "#80FFFF", 62 | "#FF80FF", 63 | "#FFFF80", 64 | "#FF8000", 65 | "#FF0080", 66 | "#80FF00", 67 | "#80FF00", 68 | "#0080FF", 69 | "#8000FF", 70 | "#FF8080", 71 | "#80FF80", 72 | "#8080FF", 73 | "#FF80FF", 74 | "#80FFFF", 75 | "#FF80FF", 76 | "#FFFF80", 77 | "#FF8000", 78 | "#FF0080", 79 | "#80FF00", 80 | "#80FF00", 81 | "#0080FF", 82 | "#8000FF", 83 | "#FF8080", 84 | "#80FF80", 85 | "#8080FF", 86 | "#FF80FF", 87 | "#80FFFF", 88 | "#FF80FF", 89 | "#FFFF80", 90 | "#FF8000", 91 | "#FF0080", 92 | "#80FF00", 93 | "#80FF00", 94 | "#0080FF", 95 | "#8000FF", 96 | "#FF8080", 97 | "#80FF80", 98 | "#8080FF", 99 | "#FF80FF", 100 | "#80FFFF", 101 | "#FF80FF", 102 | "#FFFF80", 103 | "#FF8000", 104 | "#FF0080", 105 | "#80FF00", 106 | "#80FF00", 107 | "#0080FF", 108 | "#8000FF", 109 | "#FF8080", 110 | "#80FF80", 111 | "#8080FF", 112 | "#FF80FF", 113 | "#80FFFF", 114 | "#FF80FF", 115 | "#FFFF80", 116 | "#FF8000", 117 | "#FF0080", 118 | "#80FF00", 119 | "#80FF00", 120 | "#0080FF", 121 | "#8000FF", 122 | "#FF8080", 123 | "#80FF80", 124 | "#8080FF", 125 | "#FF80FF", 126 | "#80FFFF", 127 | "#FF80FF", 128 | "#FFFF80", 129 | "#FF8000", 130 | "#FF0080", 131 | "#80FF00", 132 | "#80FF00", 133 | "#0080FF", 134 | "#8000FF", 135 | "#FF8080", 136 | "#80FF80", 137 | "#8080FF", 138 | ] 139 | 140 | 141 | def analyze_inter_async(bins, sender_threshold, receiver_threshold, show_graph=False): 142 | available_colors = get_available_colors() 143 | methods = [ 144 | "flume", 145 | "kanal", 146 | "tokio", 147 | "async_channel", 148 | "crossfire", 149 | "thingbuf", 150 | "tachyonix", 151 | "postage", 152 | "async_broadcast", 153 | ] # 154 | 155 | aggregate_data = pd.DataFrame(columns=["latency", "method"]) 156 | 157 | print() 158 | print( 159 | bcolors.OKCYAN 160 | + "=-= Inter-Process (Async) | Latency Stats (ns) =-=" 161 | + bcolors.ENDC 162 | ) 163 | 164 | fig, sender_ax = plt.subplots(1) 165 | sender_ax.set_title("Inter-Process (Async) | Sender | Latency Distribution") 166 | sender_ax.set_xlabel("Latency (ns)") 167 | sender_ax.set_ylabel("Density") 168 | 169 | fig, receiver_ax = plt.subplots(1) 170 | receiver_ax.set_title("Inter-Process (Async) | Receiver | Latency Distribution") 171 | receiver_ax.set_xlabel("Latency (ns)") 172 | receiver_ax.set_ylabel("Density") 173 | 174 | for method in methods: 175 | # =------------------------------------------------------------= # 176 | with open(f"inter_latencies/async/{method}_sender.txt", "r") as f: 177 | lines = f.readlines() 178 | lines = [x.rstrip() for x in lines] 179 | lines = [int(x) for x in lines if x != ""] 180 | sender_data = pd.DataFrame(lines, columns=["latency"]) 181 | sender_data = sender_data.astype(int) 182 | sender_data = sender_data[sender_data["latency"] < sender_threshold] 183 | sender_data["method"] = method 184 | sender_data["direction"] = "sender" 185 | if len(aggregate_data) == 0: 186 | aggregate_data = sender_data 187 | else: 188 | aggregate_data = pd.concat([aggregate_data, sender_data]) 189 | # =------------------------------------------------------------= # 190 | with open(f"inter_latencies/async/{method}_receiver.txt", "r") as f: 191 | lines = f.readlines() 192 | lines = [x.rstrip() for x in lines] 193 | lines = [int(x) for x in lines if x != ""] 194 | recv_data = pd.DataFrame(lines, columns=["latency"]) 195 | recv_data = recv_data.astype(int) 196 | recv_data = recv_data[recv_data["latency"] < receiver_threshold] 197 | recv_data["method"] = method 198 | recv_data["direction"] = "receiver" 199 | if len(aggregate_data) == 0: 200 | aggregate_data = recv_data 201 | else: 202 | aggregate_data = pd.concat([aggregate_data, recv_data]) 203 | # =------------------------------------------------------------= # 204 | 205 | alpha = 0.25 206 | 207 | # get color from available colors 208 | color = available_colors.pop(0) 209 | sender_ax.hist( 210 | sender_data["latency"], 211 | bins=bins, 212 | alpha=alpha, 213 | density=True, 214 | color=color, 215 | label=method, 216 | ) 217 | sender_ax.axvline( 218 | sender_data["latency"].mean(), color=color, linestyle="solid", linewidth=1 219 | ) 220 | receiver_ax.hist( 221 | recv_data["latency"], 222 | bins=bins, 223 | alpha=alpha, 224 | density=True, 225 | color=color, 226 | label=method, 227 | ) 228 | receiver_ax.axvline( 229 | recv_data["latency"].mean(), color=color, linestyle="solid", linewidth=1 230 | ) 231 | 232 | for direction in ["sender", "receiver"]: 233 | print() 234 | print( 235 | bcolors.OKGREEN 236 | + f"=-------------= {direction.capitalize()} | Latencies =-------------=" 237 | + bcolors.ENDC 238 | ) 239 | pre_sorted_data = aggregate_data[(aggregate_data["direction"] == direction)] 240 | # group by method, calculate mean of latency, then sort by mean latency 241 | pre_sorted_data = ( 242 | pre_sorted_data.groupby("method") 243 | .agg({"latency": ["mean", "median", "std"]}) 244 | .reset_index() 245 | ) 246 | sorted_by_mean = pre_sorted_data.sort_values(by=[("latency", "mean")]) 247 | for _, row in sorted_by_mean.iterrows(): 248 | method = row["method"].iloc[0] 249 | mean_latency = format(row[("latency", "mean")] / 1000, ".2f") 250 | median_latency = format(row[("latency", "median")] / 1000, ".2f") 251 | std_latency = format(row[("latency", "std")] / 1000, ".2f") 252 | # format the lines to be more readable 253 | padding = " " * (20 - len(method)) 254 | print( 255 | f"{method}{padding}| mu: {mean_latency}us | median: {median_latency}us | std: {std_latency}us" 256 | ) 257 | 258 | sender_ax.legend() 259 | receiver_ax.legend() 260 | 261 | if show_graph: 262 | plt.show() 263 | 264 | 265 | def analyze_inter_busy(bins, sender_threshold, receiver_threshold, show_graph=False): 266 | 267 | available_colors = get_available_colors() 268 | methods = [ 269 | "rtrb", 270 | "ringbuf", 271 | "crossbeam_channel", 272 | "crossbeam_queue", 273 | "kanal", 274 | "flume", 275 | "omango", 276 | "npnc", 277 | "magnetic", 278 | "tokio", 279 | ] # 280 | 281 | aggregate_data = pd.DataFrame(columns=["latency", "method"]) 282 | 283 | print() 284 | print( 285 | bcolors.OKCYAN 286 | + "=-= Inter-Process (Busy) | Latency Stats (ns) =-=" 287 | + bcolors.ENDC 288 | ) 289 | 290 | fig, sender_ax = plt.subplots(1) 291 | sender_ax.set_title("Inter-Process (Busy) | Sender | Latency Distribution") 292 | sender_ax.set_xlabel("Latency (ns)") 293 | sender_ax.set_ylabel("Density") 294 | 295 | fig, receiver_ax = plt.subplots(1) 296 | receiver_ax.set_title("Inter-Process (Busy) | Receiver | Latency Distribution") 297 | receiver_ax.set_xlabel("Latency (ns)") 298 | receiver_ax.set_ylabel("Density") 299 | 300 | for method in methods: 301 | # =------------------------------------------------------------= # 302 | with open(f"inter_latencies/busy/{method}_sender.txt", "r") as f: 303 | lines = f.readlines() 304 | lines = [x.rstrip() for x in lines] 305 | lines = [int(x) for x in lines if x != ""] 306 | sender_data = pd.DataFrame(lines, columns=["latency"]) 307 | sender_data = sender_data.astype(int) 308 | sender_data = sender_data[sender_data["latency"] < sender_threshold] 309 | sender_data["method"] = method 310 | sender_data["direction"] = "sender" 311 | if len(aggregate_data) == 0: 312 | aggregate_data = sender_data 313 | else: 314 | aggregate_data = pd.concat([aggregate_data, sender_data]) 315 | # =------------------------------------------------------------= # 316 | with open(f"inter_latencies/busy/{method}_receiver.txt", "r") as f: 317 | lines = f.readlines() 318 | lines = [x.rstrip() for x in lines] 319 | lines = [int(x) for x in lines if x != ""] 320 | recv_data = pd.DataFrame(lines, columns=["latency"]) 321 | recv_data = recv_data.astype(int) 322 | recv_data = recv_data[recv_data["latency"] < receiver_threshold] 323 | recv_data["method"] = method 324 | recv_data["direction"] = "receiver" 325 | if len(aggregate_data) == 0: 326 | aggregate_data = recv_data 327 | else: 328 | aggregate_data = pd.concat([aggregate_data, recv_data]) 329 | # =------------------------------------------------------------= # 330 | 331 | alpha = 0.25 332 | 333 | # get color from available colors 334 | color = available_colors.pop(0) 335 | sender_ax.hist( 336 | sender_data["latency"], 337 | bins=bins, 338 | alpha=alpha, 339 | density=True, 340 | color=color, 341 | label=method, 342 | ) 343 | sender_ax.axvline( 344 | sender_data["latency"].mean(), color=color, linestyle="solid", linewidth=1 345 | ) 346 | receiver_ax.hist( 347 | recv_data["latency"], 348 | bins=bins, 349 | alpha=alpha, 350 | density=True, 351 | color=color, 352 | label=method, 353 | ) 354 | receiver_ax.axvline( 355 | recv_data["latency"].mean(), color=color, linestyle="solid", linewidth=1 356 | ) 357 | 358 | for direction in ["sender", "receiver"]: 359 | print() 360 | print( 361 | bcolors.OKGREEN 362 | + f"=-------------= {direction.capitalize()} | Latencies =-------------=" 363 | + bcolors.ENDC 364 | ) 365 | pre_sorted_data = aggregate_data[(aggregate_data["direction"] == direction)] 366 | # group by method, calculate mean of latency, then sort by mean latency 367 | pre_sorted_data = ( 368 | pre_sorted_data.groupby("method") 369 | .agg({"latency": ["mean", "median", "std"]}) 370 | .reset_index() 371 | ) 372 | sorted_by_mean = pre_sorted_data.sort_values(by=[("latency", "mean")]) 373 | for _, row in sorted_by_mean.iterrows(): 374 | method = row["method"].iloc[0] 375 | mean_latency = format(row[("latency", "mean")] / 1000, ".2f") 376 | median_latency = format(row[("latency", "median")] / 1000, ".2f") 377 | std_latency = format(row[("latency", "std")] / 1000, ".2f") 378 | # format the lines to be more readable 379 | padding = " " * (20 - len(method)) 380 | print( 381 | f"{method}{padding}| mu: {mean_latency}us | median: {median_latency}us | std: {std_latency}us" 382 | ) 383 | 384 | sender_ax.legend() 385 | receiver_ax.legend() 386 | if show_graph: 387 | plt.show() 388 | 389 | 390 | def analyze_intra_async_single_thread( 391 | bins, sender_threshold, receiver_threshold, show_graph=False 392 | ): 393 | available_colors = get_available_colors() 394 | methods = [ 395 | "flume", 396 | "kanal", 397 | "tokio", 398 | "async_channel", 399 | "crossfire", 400 | "thingbuf", 401 | "tachyonix", 402 | "postage", 403 | "async_broadcast", 404 | ] # 405 | 406 | aggregate_data = pd.DataFrame(columns=["latency", "method"]) 407 | 408 | print() 409 | print( 410 | bcolors.OKCYAN 411 | + "=-= Intra-Process (Async Single Thread) | Latency Stats (ns) =-=" 412 | + bcolors.ENDC 413 | ) 414 | 415 | fig, sender_ax = plt.subplots(1) 416 | sender_ax.set_title( 417 | "Intra-Process (Async Single Thread) | Sender | Latency Distribution" 418 | ) 419 | sender_ax.set_xlabel("Latency (ns)") 420 | sender_ax.set_ylabel("Density") 421 | 422 | fig, receiver_ax = plt.subplots(1) 423 | receiver_ax.set_title( 424 | "Intra-Process (Async Single Thread) | Receiver | Latency Distribution" 425 | ) 426 | receiver_ax.set_xlabel("Latency (ns)") 427 | receiver_ax.set_ylabel("Density") 428 | 429 | for method in methods: 430 | # =------------------------------------------------------------= # 431 | with open(f"intra_latencies/async_single_thread/{method}_sender.txt", "r") as f: 432 | lines = f.readlines() 433 | lines = [x.rstrip() for x in lines] 434 | lines = [int(x) for x in lines if x != ""] 435 | sender_data = pd.DataFrame(lines, columns=["latency"]) 436 | sender_data = sender_data.astype(int) 437 | sender_data = sender_data[sender_data["latency"] < sender_threshold] 438 | sender_data["method"] = method 439 | sender_data["direction"] = "sender" 440 | if len(aggregate_data) == 0: 441 | aggregate_data = sender_data 442 | else: 443 | aggregate_data = pd.concat([aggregate_data, sender_data]) 444 | # =------------------------------------------------------------= # 445 | with open( 446 | f"intra_latencies/async_single_thread/{method}_receiver.txt", "r" 447 | ) as f: 448 | lines = f.readlines() 449 | lines = [x.rstrip() for x in lines] 450 | lines = [int(x) for x in lines if x != ""] 451 | recv_data = pd.DataFrame(lines, columns=["latency"]) 452 | recv_data = recv_data.astype(int) 453 | recv_data = recv_data[recv_data["latency"] < receiver_threshold] 454 | recv_data["method"] = method 455 | recv_data["direction"] = "receiver" 456 | if len(aggregate_data) == 0: 457 | aggregate_data = recv_data 458 | else: 459 | aggregate_data = pd.concat([aggregate_data, recv_data]) 460 | # =------------------------------------------------------------= # 461 | 462 | alpha = 0.25 463 | 464 | # get color from available colors 465 | color = available_colors.pop(0) 466 | sender_ax.hist( 467 | sender_data["latency"], 468 | bins=bins, 469 | alpha=alpha, 470 | density=True, 471 | color=color, 472 | label=method, 473 | ) 474 | sender_ax.axvline( 475 | sender_data["latency"].mean(), color=color, linestyle="solid", linewidth=1 476 | ) 477 | receiver_ax.hist( 478 | recv_data["latency"], 479 | bins=bins, 480 | alpha=alpha, 481 | density=True, 482 | color=color, 483 | label=method, 484 | ) 485 | receiver_ax.axvline( 486 | recv_data["latency"].mean(), color=color, linestyle="solid", linewidth=1 487 | ) 488 | 489 | for direction in ["sender", "receiver"]: 490 | print() 491 | print( 492 | bcolors.OKGREEN 493 | + f"=-------------= {direction.capitalize()} | Latencies =-------------=" 494 | + bcolors.ENDC 495 | ) 496 | pre_sorted_data = aggregate_data[(aggregate_data["direction"] == direction)] 497 | # group by method, calculate mean of latency, then sort by mean latency 498 | pre_sorted_data = ( 499 | pre_sorted_data.groupby("method") 500 | .agg({"latency": ["mean", "median", "std"]}) 501 | .reset_index() 502 | ) 503 | sorted_by_mean = pre_sorted_data.sort_values(by=[("latency", "mean")]) 504 | for _, row in sorted_by_mean.iterrows(): 505 | method = row["method"].iloc[0] 506 | mean_latency = format(row[("latency", "mean")] / 1000, ".2f") 507 | median_latency = format(row[("latency", "median")] / 1000, ".2f") 508 | std_latency = format(row[("latency", "std")] / 1000, ".2f") 509 | # format the lines to be more readable 510 | padding = " " * (20 - len(method)) 511 | print( 512 | f"{method}{padding}| mu: {mean_latency}us | median: {median_latency}us | std: {std_latency}us" 513 | ) 514 | 515 | sender_ax.legend() 516 | receiver_ax.legend() 517 | if show_graph: 518 | plt.show() 519 | 520 | 521 | def analyze_intra_async_multi_thread( 522 | bins, sender_threshold, receiver_threshold, show_graph=False 523 | ): 524 | 525 | available_colors = get_available_colors() 526 | methods = [ 527 | "flume", 528 | "kanal", 529 | "tokio", 530 | "async_channel", 531 | "crossfire", 532 | "thingbuf", 533 | "tachyonix", 534 | "postage", 535 | "async_broadcast", 536 | ] # 537 | 538 | aggregate_data = pd.DataFrame(columns=["latency", "method"]) 539 | 540 | print() 541 | print( 542 | bcolors.OKCYAN 543 | + "=-= Intra-Process (Async Multi Thread) | Latency Stats (ns) =-=" 544 | + bcolors.ENDC 545 | ) 546 | 547 | fig, sender_ax = plt.subplots(1) 548 | sender_ax.set_title( 549 | "Intra-Process (Async Multi Thread) | Sender | Latency Distribution" 550 | ) 551 | sender_ax.set_xlabel("Latency (ns)") 552 | sender_ax.set_ylabel("Density") 553 | 554 | fig, receiver_ax = plt.subplots(1) 555 | receiver_ax.set_title( 556 | "Intra-Process (Async Multi Thread) | Receiver | Latency Distribution" 557 | ) 558 | receiver_ax.set_xlabel("Latency (ns)") 559 | receiver_ax.set_ylabel("Density") 560 | 561 | for method in methods: 562 | # =------------------------------------------------------------= # 563 | with open(f"intra_latencies/async_multi_thread/{method}_sender.txt", "r") as f: 564 | lines = f.readlines() 565 | lines = [x.rstrip() for x in lines] 566 | lines = [int(x) for x in lines if x != ""] 567 | sender_data = pd.DataFrame(lines, columns=["latency"]) 568 | sender_data = sender_data.astype(int) 569 | sender_data = sender_data[sender_data["latency"] < sender_threshold] 570 | sender_data["method"] = method 571 | sender_data["direction"] = "sender" 572 | if len(aggregate_data) == 0: 573 | aggregate_data = sender_data 574 | else: 575 | aggregate_data = pd.concat([aggregate_data, sender_data]) 576 | # =------------------------------------------------------------= # 577 | with open( 578 | f"intra_latencies/async_multi_thread/{method}_receiver.txt", "r" 579 | ) as f: 580 | lines = f.readlines() 581 | lines = [x.rstrip() for x in lines] 582 | lines = [int(x) for x in lines if x != ""] 583 | recv_data = pd.DataFrame(lines, columns=["latency"]) 584 | recv_data = recv_data.astype(int) 585 | recv_data = recv_data[recv_data["latency"] < receiver_threshold] 586 | recv_data["method"] = method 587 | recv_data["direction"] = "receiver" 588 | if len(aggregate_data) == 0: 589 | aggregate_data = recv_data 590 | else: 591 | aggregate_data = pd.concat([aggregate_data, recv_data]) 592 | # =------------------------------------------------------------= # 593 | 594 | alpha = 0.25 595 | 596 | # get color from available colors 597 | color = available_colors.pop(0) 598 | sender_ax.hist( 599 | sender_data["latency"], 600 | bins=bins, 601 | alpha=alpha, 602 | density=True, 603 | color=color, 604 | label=method, 605 | ) 606 | sender_ax.axvline( 607 | sender_data["latency"].mean(), color=color, linestyle="solid", linewidth=1 608 | ) 609 | receiver_ax.hist( 610 | recv_data["latency"], 611 | bins=bins, 612 | alpha=alpha, 613 | density=True, 614 | color=color, 615 | label=method, 616 | ) 617 | receiver_ax.axvline( 618 | recv_data["latency"].mean(), color=color, linestyle="solid", linewidth=1 619 | ) 620 | 621 | for direction in ["sender", "receiver"]: 622 | print() 623 | print( 624 | bcolors.OKGREEN 625 | + f"=-------------= {direction.capitalize()} | Latencies =-------------=" 626 | + bcolors.ENDC 627 | ) 628 | pre_sorted_data = aggregate_data[(aggregate_data["direction"] == direction)] 629 | # group by method, calculate mean of latency, then sort by mean latency 630 | pre_sorted_data = ( 631 | pre_sorted_data.groupby("method") 632 | .agg({"latency": ["mean", "median", "std"]}) 633 | .reset_index() 634 | ) 635 | sorted_by_mean = pre_sorted_data.sort_values(by=[("latency", "mean")]) 636 | for _, row in sorted_by_mean.iterrows(): 637 | method = row["method"].iloc[0] 638 | mean_latency = format(row[("latency", "mean")] / 1000, ".2f") 639 | median_latency = format(row[("latency", "median")] / 1000, ".2f") 640 | std_latency = format(row[("latency", "std")] / 1000, ".2f") 641 | # format the lines to be more readable 642 | padding = " " * (20 - len(method)) 643 | print( 644 | f"{method}{padding}| mu: {mean_latency}us | median: {median_latency}us | std: {std_latency}us" 645 | ) 646 | 647 | sender_ax.legend() 648 | receiver_ax.legend() 649 | if show_graph: 650 | plt.show() 651 | 652 | 653 | # =------------------------------------------------------------= # 654 | # Definitely a cleaner way to do this, but I'm in a rush for now 655 | 656 | # Thresholds are used to cut off outliers in latency (if desired), there are denoted in nanoseconds (ns) 657 | # 1000ns = 1us 658 | # 1000us = 1ms 659 | 660 | bins = 150 661 | show_graph = False 662 | 663 | inter_async_sender_threshold = 15000 664 | inter_async_receiver_threshold = 40000 665 | 666 | inter_busy_sender_threshold = 7500 667 | inter_busy_receiver_threshold = 15000 668 | 669 | intra_async_single_thread_sender_threshold = 7500 670 | intra_async_single_thread_receiver_threshold = 75000 671 | 672 | intra_async_multi_thread_sender_threshold = 7500 673 | intra_async_multi_thread_receiver_threshold = 60000 674 | 675 | analyze_inter_async(bins, inter_async_sender_threshold, inter_async_receiver_threshold, show_graph) 676 | analyze_inter_busy(bins, inter_busy_sender_threshold, inter_busy_receiver_threshold, show_graph) 677 | analyze_intra_async_single_thread( 678 | bins, 679 | intra_async_single_thread_sender_threshold, 680 | intra_async_single_thread_receiver_threshold, 681 | show_graph, 682 | ) 683 | analyze_intra_async_multi_thread( 684 | bins, 685 | intra_async_multi_thread_sender_threshold, 686 | intra_async_multi_thread_receiver_threshold, 687 | show_graph, 688 | ) 689 | -------------------------------------------------------------------------------- /inter_latencies/async/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt -------------------------------------------------------------------------------- /inter_latencies/busy/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt -------------------------------------------------------------------------------- /intra_latencies/async_multi_thread/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt -------------------------------------------------------------------------------- /intra_latencies/async_single_thread/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use rand::{RngCore, thread_rng}; 2 | use postage::prelude::Stream; 3 | use postage::prelude::Sink; 4 | use std::sync::Arc; 5 | use magnetic::{Producer, Consumer}; 6 | 7 | mod utils; 8 | use utils::{CL, FileHandler}; 9 | 10 | 11 | // =-= Experiments =-=-= // 12 | 13 | #[derive(Debug)] 14 | pub enum AsyncExperiments { 15 | Kanal, 16 | Flume, 17 | Tokio, 18 | AsyncChannel, 19 | Crossfire, 20 | Thingbuf, 21 | Tachyonix, 22 | Postage, 23 | AsyncBroadcast, 24 | } 25 | 26 | #[derive(Debug, Clone)] 27 | pub enum InterProcessSync { 28 | Rtrb, 29 | Ringbuf, 30 | CrossbeamChannel, 31 | CrossbeamQueue, 32 | Kanal, 33 | Flume, 34 | Omango, 35 | Npnc, 36 | Magnetic, 37 | Tokio 38 | } 39 | 40 | // =-= Data being passed =-=-= // 41 | 42 | #[derive(Debug, Clone)] 43 | pub struct Data { 44 | pub time: minstant::Instant, 45 | pub data: Vec, 46 | pub kill: bool, 47 | } 48 | 49 | impl Default for Data { 50 | fn default() -> Self { 51 | Data { 52 | time: minstant::Instant::now(), 53 | data: vec![], 54 | kill: false, 55 | } 56 | } 57 | } 58 | 59 | impl Data { 60 | pub fn new(data: Vec, kill: bool) -> Self { 61 | Data { 62 | time: minstant::Instant::now(), 63 | data, 64 | kill, 65 | } 66 | } 67 | } 68 | 69 | // =-= Inter-Process =-=-= // 70 | // - Cross CPUs / Threads communication 71 | // - Asynchronous vs Synchronous (blocking + spinning) 72 | 73 | fn inter_process_async(sample_size: i64, payload_size_in_bytes: i64, cpu_0: usize, cpu_1: usize) { 74 | CL::Teal.print("[+][Inter-Process][Async] Starting"); 75 | 76 | let mut kanal_sender_handler = FileHandler::new("inter_latencies/async/kanal_sender.txt").unwrap(); 77 | let mut flume_sender_handler = FileHandler::new("inter_latencies/async/flume_sender.txt").unwrap(); 78 | let mut tokio_sender_handler = FileHandler::new("inter_latencies/async/tokio_sender.txt").unwrap(); 79 | let mut async_channel_sender_handler = FileHandler::new("inter_latencies/async/async_channel_sender.txt").unwrap(); 80 | let mut crossfire_sender_handler = FileHandler::new("inter_latencies/async/crossfire_sender.txt").unwrap(); 81 | let mut thingbuf_sender_handler = FileHandler::new("inter_latencies/async/thingbuf_sender.txt").unwrap(); 82 | let mut tachyonix_sender_handler = FileHandler::new("inter_latencies/async/tachyonix_sender.txt").unwrap(); 83 | let mut postage_sender_handler = FileHandler::new("inter_latencies/async/postage_sender.txt").unwrap(); 84 | let mut async_broadcast_sender_handler = FileHandler::new("inter_latencies/async/async_broadcast_sender.txt").unwrap(); 85 | 86 | let (kanal_tx, kanal_rx) = kanal::bounded_async::(128); 87 | let (flume_tx, flume_rx) = flume::bounded::(128); 88 | let (tokio_tx, mut tokio_rx) = tokio::sync::mpsc::channel::(128); 89 | let (async_channel_tx, async_channel_rx) = async_channel::bounded::(128); 90 | let (crossfire_tx, crossfire_rx) = crossfire::mpsc::bounded_future_both::(128); 91 | let (thingbuf_tx, thingbuf_rx) = thingbuf::mpsc::channel::(128); 92 | let (tachyonix_tx, mut tachyonix_rx) = tachyonix::channel::(128); 93 | let (mut postage_tx, mut postage_rx) = postage::mpsc::channel::(128); 94 | let (async_broadcast_tx, mut async_broadcast_rx) = async_broadcast::broadcast::(128); 95 | 96 | 97 | let mut rng = thread_rng(); 98 | let mut random_data = vec![0; payload_size_in_bytes as usize]; 99 | rng.fill_bytes(&mut random_data); 100 | 101 | 102 | let sender_handle = std::thread::spawn(move || { // create a system thread 103 | let res = core_affinity::set_for_current(core_affinity::CoreId { id: cpu_0 }); // pin thread to specific core 104 | if res { 105 | 106 | // create tokio runtime 107 | let runtime = tokio::runtime::Builder::new_current_thread() 108 | .enable_all() 109 | .worker_threads(1) 110 | .build() 111 | .expect(&CL::Red.str("[!][Inter-Process][Async] Failed to create runtime")); 112 | let local = tokio::task::LocalSet::new(); 113 | local.block_on(&runtime, async { 114 | 115 | let experiments = vec![ 116 | AsyncExperiments::Kanal, 117 | AsyncExperiments::Flume, 118 | AsyncExperiments::Tokio, 119 | AsyncExperiments::AsyncChannel, 120 | AsyncExperiments::Crossfire, 121 | AsyncExperiments::Thingbuf, 122 | AsyncExperiments::Tachyonix, 123 | AsyncExperiments::Postage, 124 | AsyncExperiments::AsyncBroadcast, 125 | ]; 126 | 127 | for experiment in experiments { 128 | CL::Dull.print_literal(format!("[-] {:?} | Running experiment...", experiment)); 129 | match experiment { 130 | AsyncExperiments::Kanal => { 131 | for _ in 0..sample_size { 132 | 133 | let send_time = minstant::Instant::now(); 134 | kanal_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Kanal | Failed to send message")); 135 | let latency = send_time.elapsed().as_nanos(); 136 | kanal_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Kanal | Failed to write to file")); 137 | 138 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 139 | } 140 | kanal_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Kanal | Failed to send message")); 141 | }, 142 | AsyncExperiments::Flume => { 143 | for _ in 0..sample_size { 144 | 145 | let send_time = minstant::Instant::now(); 146 | flume_tx.send_async(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Flume | Failed to send message")); 147 | let latency = send_time.elapsed().as_nanos(); 148 | flume_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Flume | Failed to write to file")); 149 | 150 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 151 | } 152 | flume_tx.send_async(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Flume | Failed to send message")); 153 | }, 154 | AsyncExperiments::Tokio => { 155 | for _ in 0..sample_size { 156 | let send_time = minstant::Instant::now(); 157 | tokio_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Tokio | Failed to send message")); 158 | let latency = send_time.elapsed().as_nanos(); 159 | tokio_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Tokio | Failed to write to file")); 160 | 161 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 162 | } 163 | tokio_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Tokio | Failed to send message")); 164 | }, 165 | AsyncExperiments::AsyncChannel => { 166 | for _ in 0..sample_size { 167 | 168 | let send_time = minstant::Instant::now(); 169 | async_channel_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Async Channel | Failed to send message")); 170 | let latency = send_time.elapsed().as_nanos(); 171 | async_channel_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Async Channel | Failed to write to file")); 172 | 173 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 174 | } 175 | async_channel_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Async Channel | Failed to send message")); 176 | }, 177 | AsyncExperiments::Crossfire => { 178 | for _ in 0..sample_size { 179 | 180 | let send_time = minstant::Instant::now(); 181 | crossfire_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Crossfire | Failed to send message")); 182 | let latency = send_time.elapsed().as_nanos(); 183 | crossfire_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Crossfire | Failed to write to file")); 184 | 185 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 186 | } 187 | crossfire_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Crossfire | Failed to send message")); 188 | }, 189 | AsyncExperiments::Thingbuf => { 190 | for _ in 0..sample_size { 191 | 192 | let send_time = minstant::Instant::now(); 193 | thingbuf_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Thingbuf | Failed to send message")); 194 | let latency = send_time.elapsed().as_nanos(); 195 | thingbuf_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Thingbuf | Failed to write to file")); 196 | 197 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 198 | } 199 | thingbuf_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Thingbuf | Failed to send message")); 200 | }, 201 | AsyncExperiments::Tachyonix => { 202 | for _ in 0..sample_size { 203 | 204 | let send_time = minstant::Instant::now(); 205 | tachyonix_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Tachyonix | Failed to send message")); 206 | let latency = send_time.elapsed().as_nanos(); 207 | tachyonix_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Tachyonix | Failed to write to file")); 208 | 209 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 210 | } 211 | tachyonix_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Tachyonix | Failed to send message")); 212 | }, 213 | AsyncExperiments::Postage => { 214 | for _ in 0..sample_size { 215 | 216 | let send_time = minstant::Instant::now(); 217 | postage_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Postage | Failed to send message")); 218 | let latency = send_time.elapsed().as_nanos(); 219 | postage_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Postage | Failed to write to file")); 220 | 221 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 222 | } 223 | postage_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Postage | Failed to send message")); 224 | }, 225 | AsyncExperiments::AsyncBroadcast => { 226 | for _ in 0..sample_size { 227 | 228 | let send_time = minstant::Instant::now(); 229 | async_broadcast_tx.broadcast(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Async Broadcast | Failed to send message")); 230 | let latency = send_time.elapsed().as_nanos(); 231 | async_broadcast_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Async Broadcast | Failed to write to file")); 232 | 233 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 234 | } 235 | async_broadcast_tx.broadcast(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Async] Async Broadcast | Failed to send message")); 236 | }, 237 | } 238 | } 239 | 240 | }); 241 | } 242 | }); 243 | 244 | let mut kanal_receiver_handler = FileHandler::new("inter_latencies/async/kanal_receiver.txt").unwrap(); 245 | let mut flume_receiver_handler = FileHandler::new("inter_latencies/async/flume_receiver.txt").unwrap(); 246 | let mut tokio_receiver_handler = FileHandler::new("inter_latencies/async/tokio_receiver.txt").unwrap(); 247 | let mut async_channel_receiver_handler = FileHandler::new("inter_latencies/async/async_channel_receiver.txt").unwrap(); 248 | let mut crossfire_receiver_handler = FileHandler::new("inter_latencies/async/crossfire_receiver.txt").unwrap(); 249 | let mut thingbuf_receiver_handler = FileHandler::new("inter_latencies/async/thingbuf_receiver.txt").unwrap(); 250 | let mut tachyonix_receiver_handler = FileHandler::new("inter_latencies/async/tachyonix_receiver.txt").unwrap(); 251 | let mut postage_receiver_handler = FileHandler::new("inter_latencies/async/postage_receiver.txt").unwrap(); 252 | let mut async_broadcast_receiver_handler = FileHandler::new("inter_latencies/async/async_broadcast_receiver.txt").unwrap(); 253 | 254 | let receiver_handle = std::thread::spawn(move || { // create a system thread 255 | let res = core_affinity::set_for_current(core_affinity::CoreId { id: cpu_1 }); // pin thread to specific core 256 | if res { 257 | 258 | // create tokio runtime 259 | let runtime = tokio::runtime::Builder::new_current_thread() 260 | .enable_all() 261 | .worker_threads(1) 262 | .build() 263 | .expect(&CL::Red.str("[!][Inter-Process][Async] Failed to create runtime")); 264 | let local = tokio::task::LocalSet::new(); 265 | local.block_on(&runtime, async { 266 | 267 | let mut handles = Vec::new(); 268 | 269 | let kanal_handler = tokio::task::spawn_local(async move { 270 | loop { 271 | match kanal_rx.recv().await { 272 | Ok(data) => { 273 | if data.kill { break } 274 | 275 | let latency = data.time.elapsed().as_nanos(); 276 | kanal_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Kanal | Failed to write to file")); 277 | 278 | }, 279 | Err(e) => { 280 | CL::Red.print(&format!("[!][Inter-Process][Async] Kanal | Failed to receive message: {}", e)); 281 | break; 282 | } 283 | } 284 | } 285 | }); 286 | handles.push(kanal_handler); 287 | 288 | let flume_handler = tokio::task::spawn_local(async move { 289 | loop { 290 | match flume_rx.recv_async().await { 291 | Ok(data) => { 292 | if data.kill { break } 293 | 294 | let latency = data.time.elapsed().as_nanos(); 295 | flume_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Flume | Failed to write to file")); 296 | 297 | }, 298 | Err(e) => { 299 | CL::Red.print(&format!("[!][Inter-Process][Async] Flume | Failed to receive message: {}", e)); 300 | break; 301 | } 302 | } 303 | } 304 | }); 305 | handles.push(flume_handler); 306 | 307 | let tokio_handler = tokio::task::spawn_local(async move { 308 | while let Some(data) = tokio_rx.recv().await { 309 | if data.kill { break } 310 | 311 | let latency = data.time.elapsed().as_nanos(); 312 | tokio_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Tokio | Failed to write to file")); 313 | } 314 | }); 315 | handles.push(tokio_handler); 316 | 317 | let async_channel_handler = tokio::task::spawn_local(async move { 318 | loop { 319 | match async_channel_rx.recv().await { 320 | Ok(data) => { 321 | if data.kill { break } 322 | 323 | let latency = data.time.elapsed().as_nanos(); 324 | async_channel_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Async Channel | Failed to write to file")); 325 | 326 | }, 327 | Err(e) => { 328 | CL::Red.print(&format!("[!][Inter-Process][Async] Async Channel | Failed to receive message: {}", e)); 329 | break; 330 | } 331 | } 332 | } 333 | }); 334 | handles.push(async_channel_handler); 335 | 336 | let crossfire_handler = tokio::task::spawn_local(async move { 337 | loop { 338 | match crossfire_rx.recv().await { 339 | Ok(data) => { 340 | if data.kill { break } 341 | 342 | let latency = data.time.elapsed().as_nanos(); 343 | crossfire_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Crossfire | Failed to write to file")); 344 | 345 | }, 346 | Err(e) => { 347 | CL::Red.print(&format!("[!][Inter-Process][Async] Crossfire | Failed to receive message: {}", e)); 348 | break; 349 | } 350 | } 351 | } 352 | }); 353 | handles.push(crossfire_handler); 354 | 355 | let thingbuf_handler = tokio::task::spawn_local(async move { 356 | loop { 357 | match thingbuf_rx.recv().await { 358 | Some(data) => { 359 | if data.kill { break } 360 | 361 | let latency = data.time.elapsed().as_nanos(); 362 | thingbuf_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Thingbuf | Failed to write to file")); 363 | 364 | }, 365 | None => { 366 | CL::Red.print(&format!("[!][Inter-Process][Async] Thingbuf | Failed to receive message")); 367 | break; 368 | } 369 | } 370 | } 371 | }); 372 | handles.push(thingbuf_handler); 373 | 374 | let tachyonix_handler = tokio::task::spawn_local(async move { 375 | loop { 376 | match tachyonix_rx.recv().await { 377 | Ok(data) => { 378 | if data.kill { break } 379 | 380 | let latency = data.time.elapsed().as_nanos(); 381 | tachyonix_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Tachyonix | Failed to write to file")); 382 | 383 | }, 384 | Err(e) => { 385 | CL::Red.print(&format!("[!][Inter-Process][Async] Tachyonix | Failed to receive message: {}", e)); 386 | break; 387 | } 388 | } 389 | } 390 | }); 391 | handles.push(tachyonix_handler); 392 | 393 | let postage_handler = tokio::task::spawn_local(async move { 394 | loop { 395 | match postage_rx.recv().await { 396 | Some(data) => { 397 | if data.kill { break } 398 | 399 | let latency = data.time.elapsed().as_nanos(); 400 | postage_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Postage | Failed to write to file")); 401 | 402 | }, 403 | None => { 404 | CL::Red.print(&format!("[!][Inter-Process][Async] Postage | Failed to receive message")); 405 | break; 406 | } 407 | } 408 | } 409 | }); 410 | handles.push(postage_handler); 411 | 412 | let async_broadcast_handler = tokio::task::spawn_local(async move { 413 | loop { 414 | match async_broadcast_rx.recv().await { 415 | Ok(data) => { 416 | if data.kill { break } 417 | 418 | let latency = data.time.elapsed().as_nanos(); 419 | async_broadcast_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Async] Async Broadcast | Failed to write to file")); 420 | 421 | }, 422 | Err(e) => { 423 | CL::Red.print(&format!("[!][Inter-Process][Async] Async Broadcast | Failed to receive message: {}", e)); 424 | break; 425 | } 426 | } 427 | } 428 | }); 429 | handles.push(async_broadcast_handler); 430 | 431 | for handle in handles { 432 | handle.await.expect(&CL::Red.str("[!][Inter-Process][Async] Receiver_handle | Failed to await a handle")); 433 | } 434 | 435 | }); 436 | } 437 | }); 438 | 439 | receiver_handle.join().unwrap(); 440 | sender_handle.join().unwrap(); 441 | 442 | CL::DullGreen.print("[+][Inter-Process][Async] Complete\n"); 443 | 444 | } 445 | 446 | fn inter_process_busy_spin(sample_size: i64, payload_size_in_bytes: i64, cpu_0: usize, cpu_1: usize) { 447 | CL::Teal.print("[+][Inter-Process][Busy] Starting"); 448 | 449 | // this setup will have to be a bit different as one of the cores will be busy spinning and consuming all the resources. 450 | // so, we'll iter through the impls and create a new thread / core for each one of them. 451 | // afterwards, business as usual! 452 | 453 | let experiments = vec![ 454 | InterProcessSync::Rtrb, 455 | InterProcessSync::Ringbuf, 456 | InterProcessSync::CrossbeamChannel, 457 | InterProcessSync::CrossbeamQueue, 458 | InterProcessSync::Kanal, 459 | InterProcessSync::Flume, 460 | InterProcessSync::Omango, 461 | InterProcessSync::Npnc, 462 | InterProcessSync::Magnetic, 463 | InterProcessSync::Tokio, 464 | ]; 465 | 466 | 467 | for experiment in experiments { 468 | CL::Dull.print_literal(format!("[-] {:?} | Running experiment...", experiment)); 469 | 470 | let mut rtrb_sender_handler = FileHandler::new("inter_latencies/busy/rtrb_sender.txt").unwrap(); 471 | let mut ringbuf_sender_handler = FileHandler::new("inter_latencies/busy/ringbuf_sender.txt").unwrap(); 472 | let mut crossbeam_channel_sender_handler = FileHandler::new("inter_latencies/busy/crossbeam_channel_sender.txt").unwrap(); 473 | let mut crossbeam_queue_sender_handler = FileHandler::new("inter_latencies/busy/crossbeam_queue_sender.txt").unwrap(); 474 | let mut kanal_sender_handler = FileHandler::new("inter_latencies/busy/kanal_sender.txt").unwrap(); 475 | let mut flume_sender_handler = FileHandler::new("inter_latencies/busy/flume_sender.txt").unwrap(); 476 | let mut omango_sender_handler = FileHandler::new("inter_latencies/busy/omango_sender.txt").unwrap(); 477 | let mut npnc_sender_handler = FileHandler::new("inter_latencies/busy/npnc_sender.txt").unwrap(); 478 | let mut magnetic_sender_handler = FileHandler::new("inter_latencies/busy/magnetic_sender.txt").unwrap(); 479 | let mut tokio_sender_handler = FileHandler::new("inter_latencies/busy/tokio_sender.txt").unwrap(); 480 | 481 | 482 | let (mut rtrb_tx, mut rtrb_rx) = rtrb::RingBuffer::::new(128); 483 | let (mut ringbuf_tx, mut ringbuf_rx) = ringbuf::HeapRb::::new(128).split(); 484 | let (crossbeam_channel_tx, crossbeam_channel_rx) = crossbeam_channel::bounded::(128); 485 | let crossbeam_queue_tx = Arc::new(crossbeam_queue::ArrayQueue::::new(128)); 486 | let crossbeam_queue_rx = Arc::clone(&crossbeam_queue_tx); 487 | let (kanal_tx, kanal_rx) = kanal::bounded::(128); 488 | let (flume_tx, flume_rx) = flume::bounded::(128); 489 | let (omango_tx, omango_rx) = omango::queue::mpmc::bounded::(128); 490 | let (npnc_tx, npnc_rx) = npnc::bounded::mpmc::channel::(128); 491 | let (magnetic_tx, magnetic_rx) = magnetic::mpsc::mpsc_queue(magnetic::buffer::dynamic::DynamicBuffer::::new(128).expect("Failed to create dynamic buffer")); 492 | let (tokio_tx, mut tokio_rx) = tokio::sync::mpsc::channel::(128); 493 | 494 | let mut rng = thread_rng(); 495 | let mut random_data = vec![0; payload_size_in_bytes as usize]; 496 | rng.fill_bytes(&mut random_data); 497 | 498 | 499 | let sender_experiment = experiment.clone(); 500 | let sender_handle = std::thread::spawn(move || { // create a system thread 501 | let res = core_affinity::set_for_current(core_affinity::CoreId { id: cpu_0 }); // pin thread to specific core 502 | if res { 503 | 504 | // create tokio runtime 505 | let runtime = tokio::runtime::Builder::new_current_thread() 506 | .enable_all() 507 | .worker_threads(1) 508 | .build() 509 | .expect(&CL::Red.str("[!][Inter-Process][Busy] Failed to create runtime")); 510 | let local = tokio::task::LocalSet::new(); 511 | local.block_on(&runtime, async { 512 | 513 | // these experiments will be sending data to the receiver core every 1ms (this is the minimum of a tokio sleep command) 514 | 515 | match sender_experiment { 516 | InterProcessSync::Rtrb => { 517 | for _ in 0..sample_size { 518 | 519 | let send_time = minstant::Instant::now(); 520 | rtrb_tx.push(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] Rtrb | Failed to send message")); 521 | let latency = send_time.elapsed().as_nanos(); 522 | rtrb_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Rtrb | Failed to write to file")); 523 | 524 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 525 | } 526 | rtrb_tx.push(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] Rtrb | Failed to send message")); 527 | }, 528 | InterProcessSync::Ringbuf => { 529 | for _ in 0..sample_size { 530 | 531 | let send_time = minstant::Instant::now(); 532 | ringbuf_tx.push(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] Ringbuf | Failed to send message")); 533 | let latency = send_time.elapsed().as_nanos(); 534 | ringbuf_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Ringbuf | Failed to write to file")); 535 | 536 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 537 | } 538 | ringbuf_tx.push(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] Ringbuf | Failed to send message")); 539 | }, 540 | InterProcessSync::CrossbeamChannel => { 541 | for _ in 0..sample_size { 542 | 543 | let send_time = minstant::Instant::now(); 544 | crossbeam_channel_tx.send(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] CrossbeamChannel | Failed to send message")); 545 | let latency = send_time.elapsed().as_nanos(); 546 | crossbeam_channel_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] CrossbeamChannel | Failed to write to file")); 547 | 548 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 549 | } 550 | crossbeam_channel_tx.send(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] CrossbeamChannel | Failed to send message")); 551 | }, 552 | InterProcessSync::CrossbeamQueue => { 553 | for _ in 0..sample_size { 554 | 555 | let send_time = minstant::Instant::now(); 556 | crossbeam_queue_tx.push(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] CrossbeamQueue | Failed to send message")); 557 | let latency = send_time.elapsed().as_nanos(); 558 | crossbeam_queue_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] CrossbeamQueue | Failed to write to file")); 559 | 560 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 561 | } 562 | crossbeam_queue_tx.push(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] CrossbeamQueue | Failed to send message")); 563 | }, 564 | InterProcessSync::Kanal => { 565 | for _ in 0..sample_size { 566 | 567 | let send_time = minstant::Instant::now(); 568 | kanal_tx.send(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] Kanal | Failed to send message")); 569 | let latency = send_time.elapsed().as_nanos(); 570 | kanal_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Kanal | Failed to write to file")); 571 | 572 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 573 | } 574 | kanal_tx.send(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] Kanal | Failed to send message")); 575 | }, 576 | InterProcessSync::Flume => { 577 | for _ in 0..sample_size { 578 | 579 | let send_time = minstant::Instant::now(); 580 | flume_tx.send(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] Flume | Failed to send message")); 581 | let latency = send_time.elapsed().as_nanos(); 582 | flume_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Flume | Failed to write to file")); 583 | 584 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 585 | } 586 | flume_tx.send(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] Flume | Failed to send message")); 587 | }, 588 | InterProcessSync::Omango => { 589 | for _ in 0..sample_size { 590 | 591 | let send_time = minstant::Instant::now(); 592 | omango_tx.send(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] Omango | Failed to send message")); 593 | let latency = send_time.elapsed().as_nanos(); 594 | omango_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Omango | Failed to write to file")); 595 | 596 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 597 | } 598 | omango_tx.send(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] Omango | Failed to send message")); 599 | }, 600 | InterProcessSync::Npnc => { 601 | for _ in 0..sample_size { 602 | 603 | let send_time = minstant::Instant::now(); 604 | npnc_tx.produce(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] Npnc | Failed to send message")); 605 | let latency = send_time.elapsed().as_nanos(); 606 | npnc_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Npnc | Failed to write to file")); 607 | 608 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 609 | } 610 | npnc_tx.produce(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] Npnc | Failed to send message")); 611 | }, 612 | InterProcessSync::Magnetic => { 613 | for _ in 0..sample_size { 614 | 615 | let send_time = minstant::Instant::now(); 616 | magnetic_tx.push(Data::new(random_data.clone(), false)).expect(&CL::Red.str("[!][Inter-Process][Busy] Magnetic | Failed to send message")); 617 | let latency = send_time.elapsed().as_nanos(); 618 | magnetic_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Magnetic | Failed to write to file")); 619 | 620 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 621 | } 622 | magnetic_tx.push(Data::new(random_data.clone(), true)).expect(&CL::Red.str("[!][Inter-Process][Busy] Magnetic | Failed to send message")); 623 | }, 624 | InterProcessSync::Tokio => { 625 | for _ in 0..sample_size { 626 | 627 | let send_time = minstant::Instant::now(); 628 | tokio_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Inter-Process][Busy] Tokio | Failed to send message")); 629 | let latency = send_time.elapsed().as_nanos(); 630 | tokio_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Tokio | Failed to write to file")); 631 | 632 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 633 | } 634 | tokio_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Inter-Process][Busy] Tokio | Failed to send message")); 635 | }, 636 | } 637 | }); 638 | } 639 | }); 640 | 641 | let mut rtrb_receiver_handler = FileHandler::new("inter_latencies/busy/rtrb_receiver.txt").unwrap(); 642 | let mut ringbuf_receiver_handler = FileHandler::new("inter_latencies/busy/ringbuf_receiver.txt").unwrap(); 643 | let mut crossbeam_channel_receiver_handler = FileHandler::new("inter_latencies/busy/crossbeam_channel_receiver.txt").unwrap(); 644 | let mut crossbeam_queue_receiver_handler = FileHandler::new("inter_latencies/busy/crossbeam_queue_receiver.txt").unwrap(); 645 | let mut kanal_receiver_handler = FileHandler::new("inter_latencies/busy/kanal_receiver.txt").unwrap(); 646 | let mut flume_receiver_handler = FileHandler::new("inter_latencies/busy/flume_receiver.txt").unwrap(); 647 | let mut omango_receiver_handler = FileHandler::new("inter_latencies/busy/omango_receiver.txt").unwrap(); 648 | let mut npnc_receiver_handler = FileHandler::new("inter_latencies/busy/npnc_receiver.txt").unwrap(); 649 | let mut magnetic_receiver_handler = FileHandler::new("inter_latencies/busy/magnetic_receiver.txt").unwrap(); 650 | let mut tokio_receiver_handler = FileHandler::new("inter_latencies/busy/tokio_receiver.txt").unwrap(); 651 | 652 | let receiver_handle = std::thread::spawn(move || { // create a system thread 653 | let res = core_affinity::set_for_current(core_affinity::CoreId { id: cpu_1 }); // pin thread to specific core 654 | if res { 655 | 656 | // create tokio runtime 657 | let runtime = tokio::runtime::Builder::new_current_thread() 658 | .enable_all() 659 | .worker_threads(1) 660 | .build() 661 | .expect(&CL::Red.str("[!][Inter-Process][Busy] Failed to create runtime")); 662 | let local = tokio::task::LocalSet::new(); 663 | local.block_on(&runtime, async { 664 | 665 | // these experiments will be busy spinning and consuming all the resources on the designated core 666 | 667 | match experiment { 668 | InterProcessSync::Rtrb => { 669 | loop { 670 | match rtrb_rx.pop() { 671 | Ok(data) => { 672 | if data.kill { break } 673 | 674 | let latency = data.time.elapsed().as_nanos(); 675 | rtrb_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Rtrb | Failed to write to file")); 676 | 677 | }, 678 | Err(_) => {}, // error will populate if buffer is empty, which is expected as the buffer is being read faster than it's being written to 679 | } 680 | } 681 | }, 682 | InterProcessSync::Ringbuf => { 683 | loop { 684 | match ringbuf_rx.pop() { 685 | Some(data) => { 686 | if data.kill { break } 687 | 688 | let latency = data.time.elapsed().as_nanos(); 689 | ringbuf_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Ringbuf | Failed to write to file")); 690 | 691 | }, 692 | None => {}, 693 | } 694 | } 695 | }, 696 | InterProcessSync::CrossbeamChannel => { 697 | loop { 698 | match crossbeam_channel_rx.try_recv() { 699 | Ok(data) => { 700 | if data.kill { break } 701 | 702 | let latency = data.time.elapsed().as_nanos(); 703 | crossbeam_channel_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] CrossbeamChannel | Failed to write to file")); 704 | 705 | }, 706 | Err(_) => {}, 707 | } 708 | } 709 | }, 710 | InterProcessSync::CrossbeamQueue => { 711 | loop { 712 | match crossbeam_queue_rx.pop() { 713 | Some(data) => { 714 | if data.kill { break } 715 | 716 | let latency = data.time.elapsed().as_nanos(); 717 | crossbeam_queue_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] CrossbeamQueue | Failed to write to file")); 718 | 719 | }, 720 | None => {}, 721 | } 722 | } 723 | }, 724 | InterProcessSync::Kanal => { 725 | loop { 726 | match kanal_rx.try_recv() { 727 | Ok(optional_data) => { 728 | match optional_data { 729 | Some(data) => { 730 | if data.kill { break } 731 | 732 | let latency = data.time.elapsed().as_nanos(); 733 | kanal_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Kanal | Failed to write to file")); 734 | }, 735 | None => {} 736 | } 737 | }, 738 | Err(e) => { 739 | CL::Red.print(&format!("[!][Inter-Process][Busy] Kanal | Failed to receive message: {}", e)); 740 | break; 741 | }, 742 | } 743 | } 744 | }, 745 | InterProcessSync::Flume => { 746 | loop { 747 | match flume_rx.recv() { 748 | Ok(data) => { 749 | if data.kill { break } 750 | 751 | let latency = data.time.elapsed().as_nanos(); 752 | flume_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Flume | Failed to write to file")); 753 | 754 | }, 755 | Err(_) => {}, 756 | } 757 | } 758 | }, 759 | InterProcessSync::Omango => { 760 | loop { 761 | match omango_rx.recv() { 762 | Ok(data) => { 763 | if data.kill { break } 764 | 765 | let latency = data.time.elapsed().as_nanos(); 766 | omango_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Omango | Failed to write to file")); 767 | 768 | }, 769 | Err(_) => {}, 770 | } 771 | } 772 | }, 773 | InterProcessSync::Npnc => { 774 | loop { 775 | match npnc_rx.consume() { 776 | Ok(data) => { 777 | if data.kill { break } 778 | 779 | let latency = data.time.elapsed().as_nanos(); 780 | npnc_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Npnc | Failed to write to file")); 781 | 782 | }, 783 | Err(_) => {}, 784 | } 785 | } 786 | }, 787 | InterProcessSync::Magnetic => { 788 | loop { 789 | match magnetic_rx.pop() { 790 | Ok(data) => { 791 | if data.kill { break } 792 | 793 | let latency = data.time.elapsed().as_nanos(); 794 | magnetic_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Magnetic | Failed to write to file")); 795 | 796 | }, 797 | Err(_) => {}, 798 | } 799 | } 800 | }, 801 | InterProcessSync::Tokio => { 802 | loop { 803 | match tokio_rx.try_recv() { 804 | Ok(data) => { 805 | if data.kill { break } 806 | 807 | let latency = data.time.elapsed().as_nanos(); 808 | tokio_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Inter-Process][Busy] Tokio | Failed to write to file")); 809 | 810 | }, 811 | Err(_) => {}, 812 | } 813 | } 814 | }, 815 | } 816 | }); 817 | } 818 | }); 819 | 820 | receiver_handle.join().unwrap(); 821 | sender_handle.join().unwrap(); 822 | } 823 | 824 | 825 | 826 | CL::DullGreen.print("[+][Inter-Process][Busy] Complete\n"); 827 | } 828 | 829 | 830 | // =-= Intra-Process =-=-= // 831 | // - Communication within the same tokio runtime 832 | // - Testing different tokio structures (single-threaded (pinned to one core / thread) vs multi-threaded across all cores) 833 | 834 | fn intra_process_async_multi_thread(sample_size: i64, payload_size_in_bytes: i64) { 835 | CL::Teal.print("[+][Intra-Process][Async-Multi-Thread] Starting"); 836 | 837 | // this experiment differs a bit. instead of creating and pinning a thread to a core, we assume that people going the intra-process 838 | // route will be using a runtime over multiple cores. so, we'll create a multi-threaded runtime which will create worker threads equal 839 | // to the number of cores on the machine. this way, we can simulate the intra-process async scenario. 840 | 841 | // create tokio runtime 842 | let runtime = tokio::runtime::Builder::new_multi_thread() 843 | .enable_all() 844 | .build() 845 | .expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Failed to create runtime")); 846 | //let local = tokio::task::LocalSet::new(); 847 | runtime.block_on(async { 848 | 849 | let mut kanal_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/kanal_sender.txt").unwrap(); 850 | let mut flume_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/flume_sender.txt").unwrap(); 851 | let mut tokio_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/tokio_sender.txt").unwrap(); 852 | let mut async_channel_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/async_channel_sender.txt").unwrap(); 853 | let mut crossfire_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/crossfire_sender.txt").unwrap(); 854 | let mut thingbuf_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/thingbuf_sender.txt").unwrap(); 855 | let mut tachyonix_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/tachyonix_sender.txt").unwrap(); 856 | let mut postage_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/postage_sender.txt").unwrap(); 857 | let mut async_broadcast_sender_handler = FileHandler::new("intra_latencies/async_multi_thread/async_broadcast_sender.txt").unwrap(); 858 | 859 | let mut kanal_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/kanal_receiver.txt").unwrap(); 860 | let mut flume_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/flume_receiver.txt").unwrap(); 861 | let mut tokio_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/tokio_receiver.txt").unwrap(); 862 | let mut async_channel_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/async_channel_receiver.txt").unwrap(); 863 | let mut crossfire_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/crossfire_receiver.txt").unwrap(); 864 | let mut thingbuf_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/thingbuf_receiver.txt").unwrap(); 865 | let mut tachyonix_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/tachyonix_receiver.txt").unwrap(); 866 | let mut postage_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/postage_receiver.txt").unwrap(); 867 | let mut async_broadcast_receiver_handler = FileHandler::new("intra_latencies/async_multi_thread/async_broadcast_receiver.txt").unwrap(); 868 | 869 | let (kanal_tx, kanal_rx) = kanal::bounded_async::(128); 870 | let (flume_tx, flume_rx) = flume::bounded::(128); 871 | let (tokio_tx, mut tokio_rx) = tokio::sync::mpsc::channel::(128); 872 | let (async_channel_tx, async_channel_rx) = async_channel::bounded::(128); 873 | let (crossfire_tx, crossfire_rx) = crossfire::mpsc::bounded_future_both::(128); 874 | let (thingbuf_tx, thingbuf_rx) = thingbuf::mpsc::channel::(128); 875 | let (tachyonix_tx, mut tachyonix_rx) = tachyonix::channel::(128); 876 | let (mut postage_tx, mut postage_rx) = postage::mpsc::channel::(128); 877 | let (async_broadcast_tx, mut async_broadcast_rx) = async_broadcast::broadcast::(128); 878 | 879 | 880 | let mut rng = thread_rng(); 881 | let mut random_data = vec![0; payload_size_in_bytes as usize]; 882 | rng.fill_bytes(&mut random_data); 883 | 884 | 885 | let mut handles = Vec::new(); 886 | 887 | let experiments = vec![ 888 | AsyncExperiments::Kanal, 889 | AsyncExperiments::Flume, 890 | AsyncExperiments::Tokio, 891 | AsyncExperiments::AsyncChannel, 892 | AsyncExperiments::Crossfire, 893 | AsyncExperiments::Thingbuf, 894 | AsyncExperiments::Tachyonix, 895 | AsyncExperiments::Postage, 896 | AsyncExperiments::AsyncBroadcast, 897 | ]; 898 | 899 | 900 | let sender_handler = tokio::task::spawn(async move { 901 | for experiment in experiments { 902 | CL::Dull.print_literal(format!("[-] {:?} | Running experiment...", experiment)); 903 | match experiment { 904 | AsyncExperiments::Kanal => { 905 | for _ in 0..sample_size { 906 | 907 | let send_time = minstant::Instant::now(); 908 | kanal_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Kanal | Failed to send message")); 909 | let latency = send_time.elapsed().as_nanos(); 910 | kanal_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Kanal | Failed to write to file")); 911 | 912 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 913 | } 914 | kanal_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Kanal | Failed to send message")); 915 | }, 916 | AsyncExperiments::Flume => { 917 | for _ in 0..sample_size { 918 | 919 | let send_time = minstant::Instant::now(); 920 | flume_tx.send_async(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Flume | Failed to send message")); 921 | let latency = send_time.elapsed().as_nanos(); 922 | flume_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Flume | Failed to write to file")); 923 | 924 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 925 | } 926 | flume_tx.send_async(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Flume | Failed to send message")); 927 | }, 928 | AsyncExperiments::Tokio => { 929 | for _ in 0..sample_size { 930 | let send_time = minstant::Instant::now(); 931 | tokio_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Tokio | Failed to send message")); 932 | let latency = send_time.elapsed().as_nanos(); 933 | tokio_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Tokio | Failed to write to file")); 934 | 935 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 936 | } 937 | tokio_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Tokio | Failed to send message")); 938 | }, 939 | AsyncExperiments::AsyncChannel => { 940 | for _ in 0..sample_size { 941 | 942 | let send_time = minstant::Instant::now(); 943 | async_channel_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Async Channel | Failed to send message")); 944 | let latency = send_time.elapsed().as_nanos(); 945 | async_channel_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Async Channel | Failed to write to file")); 946 | 947 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 948 | } 949 | async_channel_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Async Channel | Failed to send message")); 950 | }, 951 | AsyncExperiments::Crossfire => { 952 | for _ in 0..sample_size { 953 | 954 | let send_time = minstant::Instant::now(); 955 | crossfire_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Crossfire | Failed to send message")); 956 | let latency = send_time.elapsed().as_nanos(); 957 | crossfire_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Crossfire | Failed to write to file")); 958 | 959 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 960 | } 961 | crossfire_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Crossfire | Failed to send message")); 962 | }, 963 | AsyncExperiments::Thingbuf => { 964 | for _ in 0..sample_size { 965 | 966 | let send_time = minstant::Instant::now(); 967 | thingbuf_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Thingbuf | Failed to send message")); 968 | let latency = send_time.elapsed().as_nanos(); 969 | thingbuf_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Thingbuf | Failed to write to file")); 970 | 971 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 972 | } 973 | thingbuf_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Thingbuf | Failed to send message")); 974 | }, 975 | AsyncExperiments::Tachyonix => { 976 | for _ in 0..sample_size { 977 | 978 | let send_time = minstant::Instant::now(); 979 | tachyonix_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Tachyonix | Failed to send message")); 980 | let latency = send_time.elapsed().as_nanos(); 981 | tachyonix_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Tachyonix | Failed to write to file")); 982 | 983 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 984 | } 985 | tachyonix_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Tachyonix | Failed to send message")); 986 | }, 987 | AsyncExperiments::Postage => { 988 | for _ in 0..sample_size { 989 | 990 | let send_time = minstant::Instant::now(); 991 | postage_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Postage | Failed to send message")); 992 | let latency = send_time.elapsed().as_nanos(); 993 | postage_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Postage | Failed to write to file")); 994 | 995 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 996 | } 997 | postage_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Postage | Failed to send message")); 998 | }, 999 | AsyncExperiments::AsyncBroadcast => { 1000 | for _ in 0..sample_size { 1001 | 1002 | let send_time = minstant::Instant::now(); 1003 | async_broadcast_tx.broadcast(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Async Broadcast | Failed to send message")); 1004 | let latency = send_time.elapsed().as_nanos(); 1005 | async_broadcast_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Async Broadcast | Failed to write to file")); 1006 | 1007 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1008 | } 1009 | async_broadcast_tx.broadcast(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Async Broadcast | Failed to send message")); 1010 | }, 1011 | } 1012 | } 1013 | }); 1014 | handles.push(sender_handler); 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | let kanal_handler = tokio::task::spawn(async move { 1021 | loop { 1022 | match kanal_rx.recv().await { 1023 | Ok(data) => { 1024 | if data.kill { break } 1025 | 1026 | let latency = data.time.elapsed().as_nanos(); 1027 | kanal_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Kanal | Failed to write to file")); 1028 | 1029 | }, 1030 | Err(e) => { 1031 | CL::Red.print(&format!("[!][Intra-Process][Async-Multi-Thread] Kanal | Failed to receive message: {}", e)); 1032 | break; 1033 | } 1034 | } 1035 | } 1036 | }); 1037 | handles.push(kanal_handler); 1038 | 1039 | let flume_handler = tokio::task::spawn(async move { 1040 | loop { 1041 | match flume_rx.recv_async().await { 1042 | Ok(data) => { 1043 | if data.kill { break } 1044 | 1045 | let latency = data.time.elapsed().as_nanos(); 1046 | flume_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Flume | Failed to write to file")); 1047 | 1048 | }, 1049 | Err(e) => { 1050 | CL::Red.print(&format!("[!][Intra-Process][Async-Multi-Thread] Flume | Failed to receive message: {}", e)); 1051 | break; 1052 | } 1053 | } 1054 | } 1055 | }); 1056 | handles.push(flume_handler); 1057 | 1058 | let tokio_handler = tokio::task::spawn(async move { 1059 | while let Some(data) = tokio_rx.recv().await { 1060 | if data.kill { break } 1061 | 1062 | let latency = data.time.elapsed().as_nanos(); 1063 | tokio_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Tokio | Failed to write to file")); 1064 | } 1065 | }); 1066 | handles.push(tokio_handler); 1067 | 1068 | let async_channel_handler = tokio::task::spawn(async move { 1069 | loop { 1070 | match async_channel_rx.recv().await { 1071 | Ok(data) => { 1072 | if data.kill { break } 1073 | 1074 | let latency = data.time.elapsed().as_nanos(); 1075 | async_channel_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Async Channel | Failed to write to file")); 1076 | 1077 | }, 1078 | Err(e) => { 1079 | CL::Red.print(&format!("[!][Intra-Process][Async-Multi-Thread] Async Channel | Failed to receive message: {}", e)); 1080 | break; 1081 | } 1082 | } 1083 | } 1084 | }); 1085 | handles.push(async_channel_handler); 1086 | 1087 | let crossfire_handler = tokio::task::spawn(async move { 1088 | loop { 1089 | match crossfire_rx.recv().await { 1090 | Ok(data) => { 1091 | if data.kill { break } 1092 | 1093 | let latency = data.time.elapsed().as_nanos(); 1094 | crossfire_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Crossfire | Failed to write to file")); 1095 | 1096 | }, 1097 | Err(e) => { 1098 | CL::Red.print(&format!("[!][Intra-Process][Async-Multi-Thread] Crossfire | Failed to receive message: {}", e)); 1099 | break; 1100 | } 1101 | } 1102 | } 1103 | }); 1104 | handles.push(crossfire_handler); 1105 | 1106 | let thingbuf_handler = tokio::task::spawn(async move { 1107 | loop { 1108 | match thingbuf_rx.recv().await { 1109 | Some(data) => { 1110 | if data.kill { break } 1111 | 1112 | let latency = data.time.elapsed().as_nanos(); 1113 | thingbuf_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Thingbuf | Failed to write to file")); 1114 | 1115 | }, 1116 | None => { 1117 | CL::Red.print(&format!("[!][Intra-Process][Async-Multi-Thread] Thingbuf | Failed to receive message")); 1118 | break; 1119 | } 1120 | } 1121 | } 1122 | }); 1123 | handles.push(thingbuf_handler); 1124 | 1125 | let tachyonix_handler = tokio::task::spawn(async move { 1126 | loop { 1127 | match tachyonix_rx.recv().await { 1128 | Ok(data) => { 1129 | if data.kill { break } 1130 | 1131 | let latency = data.time.elapsed().as_nanos(); 1132 | tachyonix_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Tachyonix | Failed to write to file")); 1133 | 1134 | }, 1135 | Err(e) => { 1136 | CL::Red.print(&format!("[!][Intra-Process][Async-Multi-Thread] Tachyonix | Failed to receive message: {}", e)); 1137 | break; 1138 | } 1139 | } 1140 | } 1141 | }); 1142 | handles.push(tachyonix_handler); 1143 | 1144 | let postage_handler = tokio::task::spawn(async move { 1145 | loop { 1146 | match postage_rx.recv().await { 1147 | Some(data) => { 1148 | if data.kill { break } 1149 | 1150 | let latency = data.time.elapsed().as_nanos(); 1151 | postage_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Postage | Failed to write to file")); 1152 | 1153 | }, 1154 | None => { 1155 | CL::Red.print(&format!("[!][Intra-Process][Async-Multi-Thread] Postage | Failed to receive message")); 1156 | break; 1157 | } 1158 | } 1159 | } 1160 | }); 1161 | handles.push(postage_handler); 1162 | 1163 | let async_broadcast_handler = tokio::task::spawn(async move { 1164 | loop { 1165 | match async_broadcast_rx.recv().await { 1166 | Ok(data) => { 1167 | if data.kill { break } 1168 | 1169 | let latency = data.time.elapsed().as_nanos(); 1170 | async_broadcast_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Async Broadcast | Failed to write to file")); 1171 | 1172 | }, 1173 | Err(e) => { 1174 | CL::Red.print(&format!("[!][Intra-Process][Async-Multi-Thread] Async Broadcast | Failed to receive message: {}", e)); 1175 | break; 1176 | } 1177 | } 1178 | } 1179 | }); 1180 | handles.push(async_broadcast_handler); 1181 | 1182 | for handle in handles { 1183 | handle.await.expect(&CL::Red.str("[!][Intra-Process][Async-Multi-Thread] Receiver_handle | Failed to await a handle")); 1184 | } 1185 | 1186 | }); 1187 | 1188 | 1189 | 1190 | CL::DullGreen.print("[+][Intra-Process][Async-Multi-Thread] Complete\n"); 1191 | 1192 | } 1193 | 1194 | fn intra_process_async_single_thread(sample_size: i64, payload_size_in_bytes: i64, cpu_0: usize) { 1195 | CL::Teal.print("[+][Intra-Process][Async-Single-Thread] Starting"); 1196 | 1197 | let sender_handle = std::thread::spawn(move || { // create a system thread 1198 | let res = core_affinity::set_for_current(core_affinity::CoreId { id: cpu_0 }); // pin thread to specific core 1199 | if res { 1200 | // create tokio runtime 1201 | let runtime = tokio::runtime::Builder::new_multi_thread() 1202 | .enable_all() 1203 | .build() 1204 | .expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Failed to create runtime")); 1205 | let local = tokio::task::LocalSet::new(); 1206 | local.block_on(&runtime, async { 1207 | 1208 | let mut kanal_sender_handler = FileHandler::new("intra_latencies/async_single_thread/kanal_sender.txt").unwrap(); 1209 | let mut flume_sender_handler = FileHandler::new("intra_latencies/async_single_thread/flume_sender.txt").unwrap(); 1210 | let mut tokio_sender_handler = FileHandler::new("intra_latencies/async_single_thread/tokio_sender.txt").unwrap(); 1211 | let mut async_channel_sender_handler = FileHandler::new("intra_latencies/async_single_thread/async_channel_sender.txt").unwrap(); 1212 | let mut crossfire_sender_handler = FileHandler::new("intra_latencies/async_single_thread/crossfire_sender.txt").unwrap(); 1213 | let mut thingbuf_sender_handler = FileHandler::new("intra_latencies/async_single_thread/thingbuf_sender.txt").unwrap(); 1214 | let mut tachyonix_sender_handler = FileHandler::new("intra_latencies/async_single_thread/tachyonix_sender.txt").unwrap(); 1215 | let mut postage_sender_handler = FileHandler::new("intra_latencies/async_single_thread/postage_sender.txt").unwrap(); 1216 | let mut async_broadcast_sender_handler = FileHandler::new("intra_latencies/async_single_thread/async_broadcast_sender.txt").unwrap(); 1217 | 1218 | let mut kanal_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/kanal_receiver.txt").unwrap(); 1219 | let mut flume_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/flume_receiver.txt").unwrap(); 1220 | let mut tokio_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/tokio_receiver.txt").unwrap(); 1221 | let mut async_channel_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/async_channel_receiver.txt").unwrap(); 1222 | let mut crossfire_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/crossfire_receiver.txt").unwrap(); 1223 | let mut thingbuf_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/thingbuf_receiver.txt").unwrap(); 1224 | let mut tachyonix_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/tachyonix_receiver.txt").unwrap(); 1225 | let mut postage_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/postage_receiver.txt").unwrap(); 1226 | let mut async_broadcast_receiver_handler = FileHandler::new("intra_latencies/async_single_thread/async_broadcast_receiver.txt").unwrap(); 1227 | 1228 | let (kanal_tx, kanal_rx) = kanal::bounded_async::(128); 1229 | let (flume_tx, flume_rx) = flume::bounded::(128); 1230 | let (tokio_tx, mut tokio_rx) = tokio::sync::mpsc::channel::(128); 1231 | let (async_channel_tx, async_channel_rx) = async_channel::bounded::(128); 1232 | let (crossfire_tx, crossfire_rx) = crossfire::mpsc::bounded_future_both::(128); 1233 | let (thingbuf_tx, thingbuf_rx) = thingbuf::mpsc::channel::(128); 1234 | let (tachyonix_tx, mut tachyonix_rx) = tachyonix::channel::(128); 1235 | let (mut postage_tx, mut postage_rx) = postage::mpsc::channel::(128); 1236 | let (async_broadcast_tx, mut async_broadcast_rx) = async_broadcast::broadcast::(128); 1237 | 1238 | 1239 | let mut rng = thread_rng(); 1240 | let mut random_data = vec![0; payload_size_in_bytes as usize]; 1241 | rng.fill_bytes(&mut random_data); 1242 | 1243 | 1244 | let mut handles = Vec::new(); 1245 | 1246 | let experiments = vec![ 1247 | AsyncExperiments::Kanal, 1248 | AsyncExperiments::Flume, 1249 | AsyncExperiments::Tokio, 1250 | AsyncExperiments::AsyncChannel, 1251 | AsyncExperiments::Crossfire, 1252 | AsyncExperiments::Thingbuf, 1253 | AsyncExperiments::Tachyonix, 1254 | AsyncExperiments::Postage, 1255 | AsyncExperiments::AsyncBroadcast, 1256 | ]; 1257 | 1258 | 1259 | let sender_handler = tokio::task::spawn_local(async move { 1260 | for experiment in experiments { 1261 | CL::Dull.print_literal(format!("[-] {:?} | Running experiment...", experiment)); 1262 | match experiment { 1263 | AsyncExperiments::Kanal => { 1264 | for _ in 0..sample_size { 1265 | 1266 | let send_time = minstant::Instant::now(); 1267 | kanal_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Kanal | Failed to send message")); 1268 | let latency = send_time.elapsed().as_nanos(); 1269 | kanal_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Kanal | Failed to write to file")); 1270 | 1271 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1272 | } 1273 | kanal_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Kanal | Failed to send message")); 1274 | }, 1275 | AsyncExperiments::Flume => { 1276 | for _ in 0..sample_size { 1277 | 1278 | let send_time = minstant::Instant::now(); 1279 | flume_tx.send_async(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Flume | Failed to send message")); 1280 | let latency = send_time.elapsed().as_nanos(); 1281 | flume_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Flume | Failed to write to file")); 1282 | 1283 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1284 | } 1285 | flume_tx.send_async(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Flume | Failed to send message")); 1286 | }, 1287 | AsyncExperiments::Tokio => { 1288 | for _ in 0..sample_size { 1289 | let send_time = minstant::Instant::now(); 1290 | tokio_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Tokio | Failed to send message")); 1291 | let latency = send_time.elapsed().as_nanos(); 1292 | tokio_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Tokio | Failed to write to file")); 1293 | 1294 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1295 | } 1296 | tokio_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Tokio | Failed to send message")); 1297 | }, 1298 | AsyncExperiments::AsyncChannel => { 1299 | for _ in 0..sample_size { 1300 | 1301 | let send_time = minstant::Instant::now(); 1302 | async_channel_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Async Channel | Failed to send message")); 1303 | let latency = send_time.elapsed().as_nanos(); 1304 | async_channel_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Async Channel | Failed to write to file")); 1305 | 1306 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1307 | } 1308 | async_channel_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Async Channel | Failed to send message")); 1309 | }, 1310 | AsyncExperiments::Crossfire => { 1311 | for _ in 0..sample_size { 1312 | 1313 | let send_time = minstant::Instant::now(); 1314 | crossfire_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Crossfire | Failed to send message")); 1315 | let latency = send_time.elapsed().as_nanos(); 1316 | crossfire_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Crossfire | Failed to write to file")); 1317 | 1318 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1319 | } 1320 | crossfire_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Crossfire | Failed to send message")); 1321 | }, 1322 | AsyncExperiments::Thingbuf => { 1323 | for _ in 0..sample_size { 1324 | 1325 | let send_time = minstant::Instant::now(); 1326 | thingbuf_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Thingbuf | Failed to send message")); 1327 | let latency = send_time.elapsed().as_nanos(); 1328 | thingbuf_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Thingbuf | Failed to write to file")); 1329 | 1330 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1331 | } 1332 | thingbuf_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Thingbuf | Failed to send message")); 1333 | }, 1334 | AsyncExperiments::Tachyonix => { 1335 | for _ in 0..sample_size { 1336 | 1337 | let send_time = minstant::Instant::now(); 1338 | tachyonix_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Tachyonix | Failed to send message")); 1339 | let latency = send_time.elapsed().as_nanos(); 1340 | tachyonix_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Tachyonix | Failed to write to file")); 1341 | 1342 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1343 | } 1344 | tachyonix_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Tachyonix | Failed to send message")); 1345 | }, 1346 | AsyncExperiments::Postage => { 1347 | for _ in 0..sample_size { 1348 | 1349 | let send_time = minstant::Instant::now(); 1350 | postage_tx.send(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Postage | Failed to send message")); 1351 | let latency = send_time.elapsed().as_nanos(); 1352 | postage_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Postage | Failed to write to file")); 1353 | 1354 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1355 | } 1356 | postage_tx.send(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Postage | Failed to send message")); 1357 | }, 1358 | AsyncExperiments::AsyncBroadcast => { 1359 | for _ in 0..sample_size { 1360 | 1361 | let send_time = minstant::Instant::now(); 1362 | async_broadcast_tx.broadcast(Data::new(random_data.clone(), false)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Async Broadcast | Failed to send message")); 1363 | let latency = send_time.elapsed().as_nanos(); 1364 | async_broadcast_sender_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Async Broadcast | Failed to write to file")); 1365 | 1366 | tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; 1367 | } 1368 | async_broadcast_tx.broadcast(Data::new(random_data.clone(), true)).await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Async Broadcast | Failed to send message")); 1369 | }, 1370 | } 1371 | } 1372 | }); 1373 | handles.push(sender_handler); 1374 | 1375 | 1376 | 1377 | 1378 | 1379 | let kanal_handler = tokio::task::spawn_local(async move { 1380 | loop { 1381 | match kanal_rx.recv().await { 1382 | Ok(data) => { 1383 | if data.kill { break } 1384 | 1385 | let latency = data.time.elapsed().as_nanos(); 1386 | kanal_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Kanal | Failed to write to file")); 1387 | 1388 | }, 1389 | Err(e) => { 1390 | CL::Red.print(&format!("[!][Intra-Process][Async-Single-Thread] Kanal | Failed to receive message: {}", e)); 1391 | break; 1392 | } 1393 | } 1394 | } 1395 | }); 1396 | handles.push(kanal_handler); 1397 | 1398 | let flume_handler = tokio::task::spawn_local(async move { 1399 | loop { 1400 | match flume_rx.recv_async().await { 1401 | Ok(data) => { 1402 | if data.kill { break } 1403 | 1404 | let latency = data.time.elapsed().as_nanos(); 1405 | flume_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Flume | Failed to write to file")); 1406 | 1407 | }, 1408 | Err(e) => { 1409 | CL::Red.print(&format!("[!][Intra-Process][Async-Single-Thread] Flume | Failed to receive message: {}", e)); 1410 | break; 1411 | } 1412 | } 1413 | } 1414 | }); 1415 | handles.push(flume_handler); 1416 | 1417 | let tokio_handler = tokio::task::spawn_local(async move { 1418 | while let Some(data) = tokio_rx.recv().await { 1419 | if data.kill { break } 1420 | 1421 | let latency = data.time.elapsed().as_nanos(); 1422 | tokio_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Tokio | Failed to write to file")); 1423 | } 1424 | }); 1425 | handles.push(tokio_handler); 1426 | 1427 | let async_channel_handler = tokio::task::spawn_local(async move { 1428 | loop { 1429 | match async_channel_rx.recv().await { 1430 | Ok(data) => { 1431 | if data.kill { break } 1432 | 1433 | let latency = data.time.elapsed().as_nanos(); 1434 | async_channel_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Async Channel | Failed to write to file")); 1435 | 1436 | }, 1437 | Err(e) => { 1438 | CL::Red.print(&format!("[!][Intra-Process][Async-Single-Thread] Async Channel | Failed to receive message: {}", e)); 1439 | break; 1440 | } 1441 | } 1442 | } 1443 | }); 1444 | handles.push(async_channel_handler); 1445 | 1446 | let crossfire_handler = tokio::task::spawn_local(async move { 1447 | loop { 1448 | match crossfire_rx.recv().await { 1449 | Ok(data) => { 1450 | if data.kill { break } 1451 | 1452 | let latency = data.time.elapsed().as_nanos(); 1453 | crossfire_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Crossfire | Failed to write to file")); 1454 | 1455 | }, 1456 | Err(e) => { 1457 | CL::Red.print(&format!("[!][Intra-Process][Async-Single-Thread] Crossfire | Failed to receive message: {}", e)); 1458 | break; 1459 | } 1460 | } 1461 | } 1462 | }); 1463 | handles.push(crossfire_handler); 1464 | 1465 | let thingbuf_handler = tokio::task::spawn_local(async move { 1466 | loop { 1467 | match thingbuf_rx.recv().await { 1468 | Some(data) => { 1469 | if data.kill { break } 1470 | 1471 | let latency = data.time.elapsed().as_nanos(); 1472 | thingbuf_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Thingbuf | Failed to write to file")); 1473 | 1474 | }, 1475 | None => { 1476 | CL::Red.print(&format!("[!][Intra-Process][Async-Single-Thread] Thingbuf | Failed to receive message")); 1477 | break; 1478 | } 1479 | } 1480 | } 1481 | }); 1482 | handles.push(thingbuf_handler); 1483 | 1484 | let tachyonix_handler = tokio::task::spawn_local(async move { 1485 | loop { 1486 | match tachyonix_rx.recv().await { 1487 | Ok(data) => { 1488 | if data.kill { break } 1489 | 1490 | let latency = data.time.elapsed().as_nanos(); 1491 | tachyonix_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Tachyonix | Failed to write to file")); 1492 | 1493 | }, 1494 | Err(e) => { 1495 | CL::Red.print(&format!("[!][Intra-Process][Async-Single-Thread] Tachyonix | Failed to receive message: {}", e)); 1496 | break; 1497 | } 1498 | } 1499 | } 1500 | }); 1501 | handles.push(tachyonix_handler); 1502 | 1503 | let postage_handler = tokio::task::spawn_local(async move { 1504 | loop { 1505 | match postage_rx.recv().await { 1506 | Some(data) => { 1507 | if data.kill { break } 1508 | 1509 | let latency = data.time.elapsed().as_nanos(); 1510 | postage_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Postage | Failed to write to file")); 1511 | 1512 | }, 1513 | None => { 1514 | CL::Red.print(&format!("[!][Intra-Process][Async-Single-Thread] Postage | Failed to receive message")); 1515 | break; 1516 | } 1517 | } 1518 | } 1519 | }); 1520 | handles.push(postage_handler); 1521 | 1522 | let async_broadcast_handler = tokio::task::spawn_local(async move { 1523 | loop { 1524 | match async_broadcast_rx.recv().await { 1525 | Ok(data) => { 1526 | if data.kill { break } 1527 | 1528 | let latency = data.time.elapsed().as_nanos(); 1529 | async_broadcast_receiver_handler.write_line(latency.to_string()).expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Async Broadcast | Failed to write to file")); 1530 | 1531 | }, 1532 | Err(e) => { 1533 | CL::Red.print(&format!("[!][Intra-Process][Async-Single-Thread] Async Broadcast | Failed to receive message: {}", e)); 1534 | break; 1535 | } 1536 | } 1537 | } 1538 | }); 1539 | handles.push(async_broadcast_handler); 1540 | 1541 | for handle in handles { 1542 | handle.await.expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Receiver_handle | Failed to await a handle")); 1543 | } 1544 | 1545 | }); 1546 | } 1547 | }); 1548 | 1549 | sender_handle.join().expect(&CL::Red.str("[!][Intra-Process][Async-Single-Thread] Sender_handle | Failed to join a handle")); 1550 | 1551 | CL::DullGreen.print("[+][Intra-Process][Async-Single-Thread] Complete\n"); 1552 | 1553 | } 1554 | 1555 | 1556 | 1557 | fn main() { 1558 | CL::DullTeal.print("\n 1559 | ////////////////////////////////////// 1560 | // // 1561 | // Research Project Overview // 1562 | // // 1563 | // ================================ // 1564 | // Objectives: // 1565 | // -------------------------------- // 1566 | // Inter-process communication // 1567 | // - async // 1568 | // - busy spinning (synchronous) // 1569 | // -------------------------------- // 1570 | // Intra-process communication // 1571 | // - async (single-thread) // 1572 | // - async (multi-thread) // 1573 | // ================================ // 1574 | //////////////////////////////////////\n\n 1575 | "); 1576 | 1577 | // =------------------------------------------------------------------------------= // 1578 | 1579 | let sample_size: i64 = 10000; // Number of samples to take for each test 1580 | let payload_size_in_bytes: i64 = 0; // 0 bytes is default 1581 | 1582 | let cpu_0: usize = 0; // this one is always the sender in the experiments 1583 | let cpu_1: usize = 1; // this one is always the receiver in the experiments 1584 | 1585 | // =------------------------------------------------------------------------------= // 1586 | 1587 | CL::Green.print("[+][Main] Running all tests\n"); 1588 | 1589 | inter_process_async(sample_size, payload_size_in_bytes, cpu_0, cpu_1); 1590 | inter_process_busy_spin(sample_size, payload_size_in_bytes, cpu_0, cpu_1); 1591 | intra_process_async_multi_thread(sample_size, payload_size_in_bytes); 1592 | intra_process_async_single_thread(sample_size, payload_size_in_bytes, cpu_0); // cpu_0 is the whole CPU being tested on 1593 | 1594 | CL::Green.print("[+][Main] All tests complete\n"); 1595 | 1596 | 1597 | } -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | use std::fs::OpenOptions; 2 | use std::io::{self, Write}; 3 | 4 | #[derive(Debug, Clone)] 5 | pub enum CL { 6 | Pink, 7 | Purple, 8 | Green, 9 | DullGreen, 10 | Blue, 11 | DullRed, 12 | Red, 13 | Orange, 14 | Teal, 15 | DullTeal, 16 | Dull, 17 | End, 18 | } 19 | 20 | impl ToString for CL { 21 | fn to_string(&self) -> String { 22 | match self { 23 | CL::Pink => "\x1b[38;5;201m".to_string(), 24 | CL::Purple => "\x1b[38;5;135m".to_string(), 25 | CL::Green => "\x1b[38;5;46m".to_string(), 26 | CL::DullGreen => "\x1b[38;5;29m".to_string(), 27 | CL::Blue => "\x1b[38;5;27m".to_string(), 28 | CL::DullRed => "\x1b[38;5;124m".to_string(), 29 | CL::Red => "\x1b[38;5;196m".to_string(), 30 | CL::Orange => "\x1b[38;5;208m".to_string(), 31 | CL::Teal => "\x1b[38;5;14m".to_string(), 32 | CL::DullTeal => "\x1b[38;5;153m".to_string(), 33 | CL::Dull => "\x1b[38;5;8m".to_string(), 34 | CL::End => "\x1b[37m".to_string(), 35 | } 36 | } 37 | } 38 | 39 | impl CL { 40 | pub fn print(&self, content: &str) { 41 | println!("{}{}{}", self.to_string(), content, CL::End.to_string()) 42 | } 43 | 44 | pub fn print_literal(&self, content: String) { 45 | println!("{}{}{}", self.to_string(), content, CL::End.to_string()) 46 | } 47 | 48 | pub fn str(&self, content: &str) -> String { 49 | format!("{}{}{}", self.to_string(), content, CL::End.to_string()) 50 | } 51 | } 52 | 53 | // =-= FileHandler =-= // 54 | pub struct FileHandler { 55 | file: std::fs::File, 56 | } 57 | 58 | impl FileHandler { 59 | pub fn new(file_path: &str) -> io::Result { 60 | let file = OpenOptions::new() 61 | .create(true) 62 | .write(true) 63 | .append(true) 64 | .open(file_path)?; 65 | Ok(Self { file }) 66 | } 67 | 68 | pub fn write_line(&mut self, content: String) -> io::Result<()> { 69 | writeln!(self.file, "{}", content) 70 | } 71 | } 72 | 73 | --------------------------------------------------------------------------------