{"id":23493057,"url":"https://github.com/ytakano/async_bench","last_synced_at":"2025-10-10T10:33:34.746Z","repository":{"id":37479536,"uuid":"505886056","full_name":"ytakano/async_bench","owner":"ytakano","description":"Performance Evaluation of Channel and Mutex of Rust","archived":false,"fork":false,"pushed_at":"2022-07-20T14:57:04.000Z","size":14488,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-04T21:33:48.762Z","etag":null,"topics":["async-std","benchmark","rust","tokio"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ytakano.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["ytakano"]}},"created_at":"2022-06-21T14:49:33.000Z","updated_at":"2024-08-27T16:26:03.000Z","dependencies_parsed_at":"2022-07-21T00:24:36.945Z","dependency_job_id":null,"html_url":"https://github.com/ytakano/async_bench","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ytakano/async_bench","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ytakano%2Fasync_bench","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ytakano%2Fasync_bench/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ytakano%2Fasync_bench/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ytakano%2Fasync_bench/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ytakano","download_url":"https://codeload.github.com/ytakano/async_bench/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ytakano%2Fasync_bench/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003548,"owners_count":26083595,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async-std","benchmark","rust","tokio"],"created_at":"2024-12-25T02:16:52.460Z","updated_at":"2025-10-10T10:33:34.709Z","avatar_url":"https://github.com/ytakano.png","language":"Rust","funding_links":["https://github.com/sponsors/ytakano"],"categories":[],"sub_categories":[],"readme":"# Performance Evaluation of Channel and Mutex of Rust\n\n- Author: **Yuuki Takano**\n- Date: 25th June 2022\n\nThis article introduces a performance evaluation of channel and Mutex of Rust. I evaluated channel implementation of `std`, [Crossbeam channel](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/), [flume](https://docs.rs/flume/latest/flume/index.html), [async-std](https://async.rs/), and [Tokio](https://tokio.rs/), and Mutex implementation of `std`, [parking_lot](https://docs.rs/parking_lot/latest/parking_lot/index.html), [async-std](https://async.rs/), and [Tokio](https://tokio.rs/).\n\n---\n\n## Channel\n\n### Summary\n\n- [Crossbeam channel](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/) is the fastest. Use this for multi-threaded applications.\n- [async-std](https://async.rs/) is quite better than [Tokio](https://tokio.rs/) from a view point of performance.\n\n### Evaluation Environment\n\n- CPU\n  - AMD Ryzen 9 5900HX with Radeon Graphics\n  - 8 cores, 16 threads\n  - 3.3GHz, 4.6GHz (turbo boost)\n  - 4MB L2 cache, 16MB L3 cache\n- Memory\n  - 64GB memory\n  - 32GB DDR4 x 2\n  - 3200 MT/s\n\n### One-to-one\n\nI evaluated one-to-one communications, which means 1 sender and 1 receiver.\n\n```mermaid\ngraph LR;\n    Sender1--\u003eReceiver1;\n    Sender2--\u003eReceiver2;\n    SenderN--\u003eReceiverN;\n```\n\n![one-to-one](./figs/1to1_2022.png)\n\nThese figures describe how many messages can be sent in a second; higher is better.\nY-axis is operations per second, and X-axis is the number of pairs.\nThe left figure shows about unbounded channel, and the right figure\nshows about bounded channel.\n\nAs shown in these figures, [Crossbeam channel](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/) is the fastest.\nIn addition to that, [async-std](https://async.rs/) is quite better than [Tokio](https://tokio.rs/) and `std`.\n\n#### PDF\n\nThis section shows PDF of latency of channels.\n\nYou can see PDF from [https://ytakano.github.io/async_bench/](https://ytakano.github.io/async_bench/).\n\n##### Unbounded Channel\n\n![pdf of unbounded channel](https://ytakano.github.io/async_bench/1%20to%201%20(unbounded)/violin.svg)\n\nThis figure shows PDF of latency of 10,000 x N operations.\nN is the number of pairs.\nY-axis is channel, and X-axis is latency.\nAs shown in this figure, [async-std](https://async.rs/)'s jitter is high when contention is low.\n[Crossbeam channel](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/) achieves low jitter.\n\n##### Bounded Channel\n\n![pdf of bounded channel](https://ytakano.github.io/async_bench/1%20to%201%20(bounded)/violin.svg)\n\nThis figure shows PDF of latency of 10,000 x N operations.\nN is the number of pairs.\nY-axis is channel, and X-axis is latency.\nSimilar to the unbounded channels,\n[async-std](https://async.rs/)'s jitter is high when contention is low.\nOn the other hand, [Tokio](https://tokio.rs/)'s jitter is low.\nFrom a view point of jitter, [Tokio](https://tokio.rs/) is better than [async-std](https://async.rs/).\n\n### Many-to-one\n\nI evaluated many-to-one communications using bounded channel, which means N senders and 1 receiver.\n\n```mermaid\ngraph LR;\n    Sender1--\u003eReceiver;\n    Sender2--\u003eReceiver;\n    SenderN--\u003eReceiver;\n```\n\n![many-to-one](./figs/Nto1_2022.png)\n\nThis figure describes how many messages can be sent in a second; higher is better.\nY-axis is operations per second, and X-axis is the number of senders.\n\nAs shown in this, [Crossbeam channel](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/) and [async-std](https://async.rs/) are better than others.\n\n#### PDF\n\nThis section shows PDF of latency of many-to-one communications.\n\n![PDF of many-to-one](https://ytakano.github.io/async_bench/many%20to%201%20(bounded)/violin.svg)\n\nThis figure shows PDF of latency of 1,000 x N operations.\nN is the number of senders.\nY-axis is channel, and X-axis is latency.\n\nAs shown in this figure, jitter of [async-std](https://async.rs/) is better than [Tokio](https://tokio.rs/).\nRemind that [Tokio](https://tokio.rs/)'s jitter is lower than [async-std](https://async.rs/) when one-to-one communications.\n\n---\n\n## Mutex\n\nI evaluated Mutex to prepare N threads,\nand each thread acquires and releases a lock to access a shared variable.\n\n```mermaid\ngraph LR;\n    Thread1--lock--\u003eSharedVariable;\n    Thread2--lock--\u003eSharedVariable;\n    ThreadN--lock--\u003eSharedVariable;\n```\n\n### Summary\n\n- Mutexes of `std` and [Tokio](https://tokio.rs/) are not so fast but quite stable.\n- When contention is low, [parking_lot](https://docs.rs/parking_lot/latest/parking_lot/index.html) is better than `std`, but when contention is high [parking_lot](https://docs.rs/parking_lot/latest/parking_lot/index.html) is **worse** than `std`.\n- When contention is high, [async_std](https://docs.rs/parking_lot/latest/parking_lot/index.html) will suffer from starvation. Be careful.\n\n### Throughput\n\nTo evaluate Mutex, I prepared N threads which acquire and release a lock many times.\n\n![one-to-one](./figs/mutex_2022.png)\n\nThis figure shows how many the lock can be acquired in a second.\nY-axis is operations per second, and X-axis is the number of threads; higher is better.\n\nPay attention that [async_std](https://docs.rs/parking_lot/latest/parking_lot/index.html) of 20 and 24 threads. [async_std](https://docs.rs/parking_lot/latest/parking_lot/index.html) is significantly bad when contention is high. It may cause starvation when high contention.\n\n[Tokio](https://tokio.rs/) and `std` are very stable.\n[parking_lot](https://docs.rs/parking_lot/latest/parking_lot/index.html) is better than `std` only when low contention.\nSo, it is not bad choice using `std`,\nand [parking_lot](https://docs.rs/parking_lot/latest/parking_lot/index.html) should be used carefully.\n\n### PDF\n\nThis section shows PDF of latency of Mutexes.\n\n![pdf of mutex](https://ytakano.github.io/async_bench/mutex/violin.svg)\n\nThis figure shows PDF of latency of each Mutex.\nY-axis is Mutex, and X-axis is latency of 10,000 x N operations.\nN is the number of threads.\nIt means each thread acquire and release a lock 10,000 times,\nand the latency is the elapsed time to complete the N threads.\n\nAs shown in this figure, both [async_std](https://docs.rs/parking_lot/latest/parking_lot/index.html) and [Tokio](https://tokio.rs/)'s jitter are high.\n[parking_lot](https://docs.rs/parking_lot/latest/parking_lot/index.html) and `std` are good from a view point of jitter.\n\n## Reproducibility\n\nYou can reproduce as follows.\n\n```text\n$ cargo run --release\n```\n\nand\n\n```text\n$ cargo install criterion\n$ cargo criterion\n```\n\n## Conclusion\n\n- [Crossbeam channel](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/) is the fastest. Use this for multi-threaded programming.\n- Throughput of [async-std](https://async.rs/) is better than [Tokio](https://tokio.rs/).\n- From a view point of jitter, [Tokio](https://tokio.rs/) is better than [async-std](https://async.rs/) under some conditions, but [async-std](https://async.rs/) is better than [Tokio](https://tokio.rs/) under other conditions.\n- [parking_lot](https://docs.rs/parking_lot/latest/parking_lot/index.html) is worse than `std` when high contention. `std`'s Mutex is not so bad because it is stable.\n- Mutex of [async-std](https://async.rs/) is significantly bad when high contention. Be careful.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fytakano%2Fasync_bench","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fytakano%2Fasync_bench","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fytakano%2Fasync_bench/lists"}