{"id":22874127,"url":"https://github.com/joakimthun/io-uring-echo-server","last_synced_at":"2025-05-07T18:22:34.130Z","repository":{"id":77196475,"uuid":"585190944","full_name":"joakimthun/io-uring-echo-server","owner":"joakimthun","description":"Very simple TCP echo servers based on io_uring and epoll.","archived":false,"fork":false,"pushed_at":"2023-01-08T22:35:14.000Z","size":43,"stargazers_count":5,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T12:57:31.412Z","etag":null,"topics":["async-io","epoll","io-uring","tcp-echo-server"],"latest_commit_sha":null,"homepage":"","language":"C++","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/joakimthun.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-04T14:49:05.000Z","updated_at":"2024-12-31T20:13:39.000Z","dependencies_parsed_at":"2023-09-04T14:03:34.526Z","dependency_job_id":null,"html_url":"https://github.com/joakimthun/io-uring-echo-server","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joakimthun%2Fio-uring-echo-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joakimthun%2Fio-uring-echo-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joakimthun%2Fio-uring-echo-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joakimthun%2Fio-uring-echo-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joakimthun","download_url":"https://codeload.github.com/joakimthun/io-uring-echo-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252931963,"owners_count":21827194,"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","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-io","epoll","io-uring","tcp-echo-server"],"created_at":"2024-12-13T14:33:22.411Z","updated_at":"2025-05-07T18:22:34.047Z","avatar_url":"https://github.com/joakimthun.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# io-uring-echo-server\n\nVery simple TCP echo servers based on io_uring and epoll. Both servers are single-threaded i.e. they both run a single\nevent loop. Some very simple benchmark results for both servers can be found below.\n\n# Requirements\n\nOnly tested on Ubuntu with kernel version 6.0.9-060009-generic.\nBuilt and tested with clang 14 and g++ 11.3.0.\n\n# io_uring echo server\n\n* ```src/net/UringEchoServer.h```\n* Uses multishot variants of accept (```io_uring_prep_multishot_accept```) and recv (```io_uring_prep_recv_multishot```)\n* IO buffers are pre-allocated and registered using ```io_uring_register_buf_ring```/```io_uring_buf_ring_init``` and\n  recycled once the buffer content has been written. I.e. no more buffer allocations happens after the init.\n* All context is kept by serializing what is needed into the 8 bytes provided\n  by ```io_uring_sqe::user_data```/```io_uring_cqe::user_data```\n* **TODO:** Test ```IORING_SETUP_IOPOLL``` - https://man7.org/linux/man-pages/man2/io_uring_setup.2.html\n\n# epoll echo server\n\n* ```src/net/EpollEchoServer.h```\n* The benchmarks below are compiled with ```INLINE_EPOLL_WRITE``` defined i.e. no dynamic buffer management (without ```INLINE_EPOLL_WRITE``` the server is using a per connection tx buffer queue and a global list of pre-allocated IO buffers) and less calls to ```epoll_ctl```.\n  For an echo server this kinda works, but we risk dropping repsonses on ```EAGAIN```/```EWOULDBLOCK```, partial scoket writes or other errors\n  i.e. not really something that can be done in a real application. **TLDR:** With ```INLINE_EPOLL_WRITE``` we try to\n  write/echo what we just read, and ignore any errors.\n* Allocates 1 \"context\" per connection to keep track of FDs and RX buffers (the allocation can technically be removed when\n  defining ```INLINE_EPOLL_WRITE``` but since in that mode we only have 1 allocation on every accept/new connection the\n  benchmark results does not really change...)\n\n# io_uring vs epoll benchmark results\n\n**NOTE:** These benchmarks are not very scientific. E.g. they are run with the clients and server on the same machine (\nIntel i7-12700) i.e. loopback. They do **not** reflect real world performance.\n\n## Set-up\n\n### Client(s)\n\nhttps://github.com/haraldh/rust_echo_bench\n\nExample command: ```cargo run --release -- --address \"localhost:6379\" --number 1 --duration 60 --length 1024```\n\nThis is the same tool that is used by: https://github.com/frevib/io_uring-echo-server\n\n### Server\n\nBuilt with the build command below. Servers are started like this:\n\n``` taskset -c 0 ./uring_echo_server```\n\n``` taskset -c 0 ./epoll_echo_server```\n\nServer commit used for the benchmarks: ```b1acab8d13cd2ba58a8caf28618f87e44322a857``` (for config values)\n\n## Results\n\nThe numbers in the table are requests/sec calculated by rust_echo_bench. All benchmarks are run with a 1024 byte\npayload. And as mentioned above, the benchmarks uses a single event-loop/cpu-core on the server side.\n\n|  Server  | Num connections:  |    1    |   256   |   512   |  1024   |\n|:--------:|:-----------------:|:-------:|:-------:|:-------:|:-------:|\n| io_uring | 1024 byte payload | 176 402 | 421 246 | 354 244 | 353 988 |\n|  epoll   | 1024 byte payload | 169 021 | 421 010 | 405 133 |   :(    |\n\n**NOTE:** With 1024 connections the epoll server gets stuck @ 100% cpu usage, have not looked into why yet...\n\n**TODO:** Run benchmarks in a more realistic set-up.\n\n# Build\n\nInstall https://github.com/axboe/liburing.\n\n```\nmkdir build \u0026\u0026 cd build\ncmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/clang++\nmake\n```\n\n# Run (the io_uring or epoll server)\n\n```\n./uring_echo_server\n./epoll_echo_server\n```\n\n# Example usage\n\n```\njthun@jthun:~$ echo \"Hello, World!\" | nc localhost 6379\nHello, World!\n```\n\n# io-uring resources\n\n* https://kernel.dk/io_uring.pdf\n* https://unixism.net/loti/what_is_io_uring.html\n* https://github.com/axboe/liburing\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoakimthun%2Fio-uring-echo-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoakimthun%2Fio-uring-echo-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoakimthun%2Fio-uring-echo-server/lists"}