From: samuel@... Date: 2021-07-12T00:54:19+00:00 Subject: [ruby-core:104582] [Ruby master Bug#17664] Behavior of sockets changed in Ruby 3.0 to non-blocking Issue #17664 has been updated by ioquatix (Samuel Williams). I rewrote the `uring` implementation to track the number of pending operations. I'm kind of surprised that the SQ doesn't do this. ``` % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 26.59 0.049621 4 10575 close 24.85 0.046369 4 10335 write 17.34 0.032363 3 10338 3 accept4 13.77 0.025693 2 10727 79 read 11.82 0.022051 2 10727 9 newfstatat 5.31 0.009911 4 2079 mprotect 0.11 0.000207 1 192 mmap 0.09 0.000165 1 87 munmap 0.05 0.000087 1 48 brk 0.04 0.000083 1 83 1 io_uring_enter ``` Now for non-blocking sockets, we only see `io_uring_enter` count proportional to the number of `read` and `write` errors which makes more sense to me. ``` Running 30s test @ http://localhost:9090 4 threads and 128 connections Thread Stats Avg Stdev Max +/- Stdev Latency 2.87ms 1.36ms 90.28ms 98.60% Req/Sec 11.16k 1.40k 26.84k 70.73% 1332172 requests in 30.04s, 58.44MB read Requests/sec: 44341.92 Transfer/sec: 1.95MB ``` As you can imagine, with only 89 calls to `io_uring_enter`, whether or not it's done early or later has little impact on overall performance. ---------------------------------------- Bug #17664: Behavior of sockets changed in Ruby 3.0 to non-blocking https://bugs.ruby-lang.org/issues/17664#change-92865 * Author: ciconia (Sharon Rosner) * Status: Assigned * Priority: Normal * Assignee: ioquatix (Samuel Williams) * ruby -v: 3.0.0 * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN ---------------------------------------- I'm not sure this is a bug, but apparently a change was introduced in Ruby 3.0 that makes sockets non-blocking by default. This change was apparently introduced as part of the work on the [FiberScheduler interface](https://github.com/ruby/ruby/blame/78f188524f551c97b1a7a44ae13514729f1a21c7/ext/socket/init.c#L411-L434). This change of behaviour is not discussed in the Ruby 3.0.0 release notes. This change complicates the implementation of an io_uring-based fiber scheduler, since io_uring SQE's on fd's with `O_NONBLOCK` can return `EAGAIN` just like normal syscalls. Using io_uring with non-blocking fd's defeats the whole purpose of using io_uring in the first place. A workaround I have put in place in the Polyphony [io_uring backend](https://github.com/digital-fabric/polyphony/blob/d3c9cf3ddc1f414387948fa40e5f6a24f68bf045/ext/polyphony/backend_io_uring.c#L28-L47) is to make sure `O_NONBLOCK` is not set before attempting I/O operations on any fd. -- https://bugs.ruby-lang.org/ Unsubscribe: