xiaoyang-sde / co-uring-http

High performance HTTP server built on C++20 coroutines and io_uring
MIT License
141 stars 5 forks source link

Discussion: Implement an HTTP server using C++ 20 coroutines and io_uring #2

Open xiaoyang-sde opened 1 year ago

xiaoyang-sde commented 1 year ago

Feel free to share thoughts, ideas, and suggestions.

CarterLi commented 1 year ago

之前研究过一点io-uring

  1. 别用 splice。io-uring 目前版本的 splice 极其慢,比 read-send 慢很多
  2. 可以使用 IOLINK 减少 syscall 次数,比如 read(IOLINK)-send。这两个请求一次性 submit,send 会等待 read 执行成功后再执行。
  3. 建议使用同步版本的 cancel。异步的 cancel 不能保证IO请求被及时取消,导致 use-after-free 的情况
  4. 少用 std::function。std::function 会动态申请内存并有类型擦除机制,比直接调用函数慢很多。建议 io_uring::for_each_cqe 改成返回迭代器,这样既可以避免回调函数省去 std::function,而且普通循环更容易使用可以随时 break
  5. cqe_seen 可以考虑放在事件回调之前,并提前把 cqe 结构体拷贝出来。这样可以提前给内核释放空间
  6. 可以考虑 使用 io_uring_queue_init_params 指定 wq_fd,让不同线程的 io_uring 实例复用同一个内核线程池,节省内核资源。
xiaoyang-sde commented 1 year ago

之前研究过一点io-uring

  • 有个小问题:multishot_accept 是怎么使用的没看懂。就我所知一个 multishot_sqe 会有多个 cqe,所有 cqe 的 data 都是一样的,这就和 coroutine 使用冲突,因为每次 resume 之后 coroutine address 都已经变了。
  • 还有一些小建议:
  1. 别用 splice。io-uring 目前版本的 splice 极其慢,比 read-send 慢很多
  2. 可以使用 IOLINK 减少 syscall 次数,比如 read(IOLINK)-send。这两个请求一次性 submit,send 会等待 read 执行成功后再执行。
  3. 建议使用同步版本的 cancel。异步的 cancel 不能保证IO请求被及时取消,导致 use-after-free 的情况
  4. 少用 std::function。std::function 会动态申请内存并有类型擦除机制,比直接调用函数慢很多。建议 io_uring::for_each_cqe 改成返回迭代器,这样既可以避免回调函数省去 std::function,而且普通循环更容易使用可以随时 break
  5. cqe_seen 可以考虑放在事件回调之前,并提前把 cqe 结构体拷贝出来。这样可以提前给内核释放空间
  6. 可以考虑 使用 io_uring_queue_init_params 指定 wq_fd,让不同线程的 io_uring 实例复用同一个内核线程池,节省内核资源。

感谢这些建议! multishot_accept 其实是写了个 bug... 按说每次 suspend 时要更新一下 sqe_data 的 coroutine_handle 地址, 这样下次 cqe 可以拿到正确的 coroutine handle

xiaoyang-sde commented 1 year ago

Here are potential improvements: