非阻塞 IO 不是「更快」,而是「不用等」。这篇验证它的返回形式、忙等的真实代价、用 poll 在一个线程里同时盯多个连接,以及一个容易踩的克隆共享陷阱。
编译:成功
运行(退出码 0):
没有客户端时 accept:WouldBlock,耗时 3 µs(立即返回)
没有数据时 read:WouldBlock,耗时 6 µs
对端发 2 字节后 read: Ok(2)
对端关闭后 read: Ok(0)(Ok(0) = EOF)阻塞式 TCP 见TCP Listener 与 TcpStream。
编译:成功 busy 等到数据用了 300 ms,循环 1222679 次,消耗 CPU 时间 305.1 ms blocking 等到数据用了 310 ms,循环 1 次,消耗 CPU 时间 0.2 ms poll 等到数据用了 300 ms,循环 1 次,消耗 CPU 时间 0.0 ms
CPU 时间通过 clock_gettime(CLOCK_PROCESS_CPUTIME_ID) 读取;poll 通过 extern 声明直接调用 libc,没有使用 mio。
编译:成功
运行(退出码 0):
一个线程(ThreadId(1))按就绪顺序处理了 3 个连接:[("client1", 40), ("client2", 80), ("client0", 120)](客户端 0/1/2 分别在 120/40/80 ms 发数据)异步运行时在这个基础上封装,见Async Runtime 做了什么。
编译:成功
运行(退出码 0):
只对 a 调用 set_nonblocking(true);用克隆 b 去 read:Err(WouldBlock)(立即返回 WouldBlock,没有阻塞 —— 非阻塞标志属于同一个打开的 socket)