perf(libs/core): drop libuv-style partial-read break to fix node:http p99 (#33860)
## Summary
`poll_tcp_handle`'s read loop in `uv_compat` matches libuv's `uv__read`
by breaking on partial reads (`n < buf.len`) to skip the
predicted-EAGAIN syscall. That works for libuv's epoll loop, but it
interacts badly with tokio: tokio's `TcpStream` readiness is
edge-triggered and the internal "readable" bit is cleared only when
`try_read` returns `WouldBlock`. Breaking on a partial read leaves the
bit armed; the re-register block at the end of the function then sees
`poll_read_ready == Ready` and `mark_ready()` puts the handle right back
on the loop's ready queue and wakes `loop_waker`.
Under sustained HTTP keep-alive load with small responses every read is
partial, so every tick re-queues every active connection. Tokio's
current_thread runtime sees the deno task continuously awoken and never
yields to its reactor (controlled by `event_interval`, default 61). New
TCP readiness from the kernel piles up undelivered, and each connection
waits a full event_interval window before its next request is processed.
The fix is to keep looping until `try_read` actually returns
`WouldBlock`. That costs one extra `recv()` syscall when the read fully
drains the socket buffer, but the syscall returns `WouldBlock`, clears
tokio's readiness bit, and the handle drops out of the ready queue
cleanly so the reactor is free to deliver fresh wakes.
This was easy to confirm with `DENO_TOKIO_EVENT_INTERVAL=1`, which
forces tokio to check the reactor every poll and made p99 drop from 33
ms to 3 ms even without the source change.
## Reproducer
\`\`\`js
// server.mjs
import { createServer } from "node:http";
const port = Number(process.env.PORT ?? "8004");
createServer((_req, res) => {
res.writeHead(200, { "content-type": "text/plain" });
res.end("Hello, World!");
}).listen(port, "127.0.0.1");
\`\`\`
\`\`\`
oha -c 100 -z 20s --no-tui http://127.0.0.1:8004/
\`\`\`
## Results (release-lite, 100 connections, 20 s)
| | node | deno before | deno after |
| ------ | -------- | ----------- | ---------- |
| p50 | 1.26 ms | 0.96 ms | 1.58 ms |
| p99 | 2.56 ms | 33.4 ms | 3.14 ms |
| p99.9 | 4.26 ms | 60.7 ms | 6.34 ms |
| p99.99 | 7.28 ms | 68.0 ms | 8.28 ms |
\`Deno.serve\` p99 is unchanged at 1.31 ms (no regression on the hyper
path).
## Test plan
- [x] Bench `node:http` hello-world at `c=100`, confirm p99 drops from
~30 ms to ~3 ms
- [x] Bench `Deno.serve` hello-world at `c=100`, confirm no regression
- [ ] CI green
Co-authored-by: Nathan Whitaker <nathan@deno.com>