Skip to content

v1.6.0 polish: epoll engine #885

Open

Description

@FumingPower3925

Consolidated on 2026-10-02 from the per-PR 'Follow-ups from #N' bundles, by maintainer decision. From now on, review nits are fixed inside the PR before it merges, so no new bundles are filed. Each line names the bundle and item it came from; the bundle's thread keeps the full context. Everything here stays in v1.6.0.

Added 2026-10-03 (#907's round-2 reviews, lane L905):

Added 2026-10-09 (#908's lane E7, PR #958):

Added 2026-10-09 (#771/#775's lane E3, PR #960):

Items from review round 2 of #960 (lane E3, epoll fd identity / slot lock):

  • (perf-api-security, minor) The body puts commit 1's keep-alive shift down to 'binary layout and noise alone', but the shift is consistent across rounds, so it is not noise. Commit 1 changes only closeConn and shutdown, which no keep-alive request runs through. Even so, A775 ran slower than base in most rounds. Layout is a fair guess, but nobody has tested it. The body should say the shift is consistent and its cause is untested, rather than ca (open: WORDING)
  • (perf-api-security, minor) The whole-PR keep-alive cost is bounded too loosely in the body's wording. 'Inside the A/A floor' compares a median of 16 paired ratios against a floor built from single pairs (median |A/A-1|, 0.077 and 0.067). With drivers registered, the end-to-end data do not rule out a cost of up to about 12%, not about 7%. That configuration is the production one for apps whose redis or postgres drivers run on the engine's worke (open: WORDING)
  • (perf-api-security, nit) BenchmarkCloseChurn has extreme outlier samples that the body never mentions. A single A/A pair can differ by up to about 9x. The median floor of 0.032 hides this, so a reader cannot tell the instrument behaves this way. (open: WORDING)
  • (perf-api-security, minor) Contended driverMu in closeConn is still unmeasured. The body discloses this. BenchmarkKeepAliveDispatch/withdriver registers only an idle driver conn, and CloseChurn registers none. So no arm has a driver goroutine calling Write (lookupDriver RLock) while the loop closes HTTP conns under the new write lock. acceptAll already takes the same write lock once per accepted connection, so this is disclosed and in line wit (open: MEASUREMENT)
  • (correctness, minor) TestCloseDriverSparesConnOnReusedNumber771 pins where the closeDriver EPOLL_CTL_DEL sits relative to the test hook, not that it is inside the dc.mu claim section. A mutant that moves the DEL to just after dc.mu.Unlock() but before testHookCloseDriverClaimed passes every 771 and 775 test. In production that mutant still has epoll: a driver event harvested before UnregisterConn is dispatched by number after it, and closes the conn registered on the reused number (the epoll twin of #707) #771's second window: an UnregisterConn(A) can return between the unlock and the DEL, the calle (Done: epoll: the driver read's check and read, closeDriver's DEL and a refused ADD's rollback have tests, with two nil-by-default seams (v1.6.0 polish items) #1086 [diff])
  • (correctness, nit) The deadlock section in the PR body lists 'detachMu → driverMu (hijackConn, now also closeConn's slot clear)'. closeConn's new slot clear runs with no detachMu held: both detachMu sections in closeConn unlock before CloseH2, the DEL and the slot clear. No caller can hold detachMu when it enters closeConn either, since closeConn's own TryLock/Lock would self-deadlock. So that ordering edge does not exist. The claim is (open: WORDING)
  • (correctness, nit) TestDriverTakesNumberFreedByCloseConn775 calls t.Fatalf when another descriptor of the process takes the freed number between close(2) and the hook's F_GETFD check (in that case reused stays false). The window is a few microseconds and nothing else in that test opens descriptors, so this is theoretical. It could become a t.Skip, or a retry with a second connection, so a rare collision does not look like a defect. (Done: epoll: a collision for the freed number retries, a guard for the batch counters, short-write benchmarks, and the relink comment says what is so (v1.6.0 polish items) #1088 [diff])

Added 2026-10-09 (lane H964, PR #966):

Added 2026-10-09 (lane E5, PR #969):

Added 2026-10-09 (lane X1, PR #971):

Added 2026-10-10 (lane E15, review of PR #973):

Added 2026-10-10 (lane E5B, PR #975):

Added 2026-10-10 (lane E10, PR #978, RULE 61 sweep of #867):

Added 2026-10-10 (lane E9, PR #980):

Added 2026-10-10 (lane ADDR, PR #986 review r1; cross-ref #884 for the io_uring call site):

Added 2026-10-11 (lane DFAIR, PR #993):

Added 2026-10-11 (lane E14, PR #994 review r1, RULE 61 sibling of #811):

Added 2026-10-11 (lane E13, PR #992 round 3):

Added 2026-10-16 (lane PINPLAN, PR #1049, celeris#1036):

Activity

  1. added this to the v1.6.0 milestone on Oct 2, 2026
  2. FumingPower3925 commented on Oct 13, 2026

    @FumingPower3925
    ContributorAuthor

    New checklist item (lane CTXDETACH, PR #1014 review r1):

    • epoll: H1State.NowNs is written only on the inline recv path of internal/engine/epoll/loop.go (cs.h1State.NowNs = now); the ProcessH1 calls in serveAsync (loop.go), the carry/rest call after an H2 ask (loop.go, rest), and adopt.go (two calls) do not refresh it before conn.ProcessH1, which copies it to Stream.StartTimeNs (internal/conn/h1.go, s.StartTimeNs = state.NowNs). On an async-promoted conn, and on those carry/rest requests, the request's start time is the conn's last inline recv, so the duration the router records (recoverAndRelease, and the detached elapsed in Context.Detach's done func) is inflated by the idle time between that recv and the request. Found by code reading in the PR Context.Detach: a panic out of OnDetach no longer retains the Context and a goroutine; done() records a real elapsed time #1014 review (checked against origin/main 25afce5 by grep); not measured. Fix shape to weigh: refresh NowNs where the async handler is dispatched (one clock read per request on a path that already allocates a goroutine) or stamp the stream when the request is parsed. A hot-path change needs a RULE 74 measurement. RULE 92: searched celeris and probatorium by mechanism (NowNs, StartTimeNs), no tracker.
  3. 148 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/engineEngine interface or implementationengine/epollEpoll engine specificsplatform/linuxLinux-specific (io_uring, epoll)

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions