Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions doc/coro-performance-baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -1963,3 +1963,61 @@ not on the file/syscall path. Small standard-file, direct-syscall, sole-M
blocking-pipe/timer, and loopback-TCP execution gates pass with
`GOMAXPROCS=1`, as do separately linked same-M callback, locked-thread
compensation, deferred replacement, and worker-capability E2Es.

### Demand-lazy replacement and compiler-task route checkpoint

The 2026-08-15 follow-up starts at merge
`95acde8e415516d07f2caea74578d91125a0997f`; the measured implementation is
`13bdf13c4`. Profiling the scalar-ABI binary showed that a quick native syscall
still reserved and initialized a replacement directory slot before entering
the kernel, even though almost every call returned before another task or event
needed a physical owner. The same compiler-owned call window also recovered the
current driver repeatedly through its complete registry, source-catalog,
poll-transaction, and owner-local lifecycle validator.

The deferred handoff gate now has two demand-lazy phases. `Armed` and
`Starting` contain no replacement slot. A durable executor request must first
win the stable parent's `Armed -> Starting` CAS; only that unique publisher
reads the released execution-domain generation, allocates a directory slot,
and publishes `Queued` or `Started` with the slot. A quick returning syscall
wins `Withdraw` without scanning, initializing, or recycling replacement
storage. The request side retains no pointer to the caller's stack, G, P,
driver, LLVM handle, or coroutine frame. The post-Arm durable-demand recheck
and request-tail activation still close the request-before-Arm race.

Generated physical coroutine code already carries the exact hidden task. The
native boundary now consumes `CurrentExecutorDriverForCompilerTask`, freezes
its route for the no-suspend detach interval, and uses route-authenticated
native-owner and managed-quota operations. The detach transition still checks
the mutable task, frame, park, action, lock, preemption, and P fields it changes.
TLS/reentry, retained, and otherwise non-compiler callers retain the original
complete validator; no annotation or function-address reverse lookup was
introduced.

The parent and candidate were built from the same `io_workload` source with
independent caches, full LTO, stripped output, Go 1.26.5, LLVM 22.1.8, and
process-start `GOMAXPROCS=1` on Darwin arm64. Fifteen three-way rotated process
runs gave:

| Workload | scalar parent median [range] | candidate median [range] | Go median [range] | candidate delta / Go |
| --- | ---: | ---: | ---: | ---: |
| cache-hot 4 KiB standard file round trip, 5,000 operations | 42.343 ms [41.093, 44.261] | 38.376 ms [37.189, 39.208] | 7.765 ms [7.644, 7.946] | -9.37%; 4.94x |
| direct `syscall` file round trip, 5,000 operations | 18.485 ms [18.149, 19.471] | 15.826 ms [15.384, 16.718] | 7.658 ms [7.467, 7.891] | -14.39%; 2.07x |
| loopback TCP echo, 500 operations | 19.980 ms [17.879, 21.272] | 19.343 ms [18.015, 21.213] | 9.486 ms [8.745, 10.183] | -3.19%; 2.04x |

The TCP ranges overlap, so the table establishes no network speedup beyond a
no-regression observation. In a three-second direct-syscall sample, the kernel
`write` leaf accounted for about 77% of samples below `syscall.Write`, versus
about 62% before the route-capability change; complete source-set validation no
longer appears in the ordinary begin/release/reenter path. The stripped binary
is 7,016,288 bytes versus 7,014,768 (+1,520, 0.022%), and Mach-O `__text` is
3,140,944 bytes versus 3,137,244 (+3,700, 0.118%).

The full runtime module, architecture debt gate, native target-plan gate,
same-M scheduler-progress E2E, locked compensation E2E, request-driven direct
channel replacement E2E, and real standard-file/direct-syscall/sole-M blocking
pipe with timer/loopback-TCP executions pass. Sampling now identifies the
remaining standard-file gap primarily in synchronous child coroutine
allocation, frame publication, inline-await completion, and destroy/consume
transactions through `syscall`, `internal/poll`, `os.File`, and `io`, rather
than in replacement-slot or full driver-route recovery.
2 changes: 1 addition & 1 deletion internal/build/coro_native_fleet_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1930,7 +1930,7 @@ func TestCoroNativeFleetLockedForeignReleasesQuotaBeforeReplacementStarts(t *tes
source := string(raw)
release := strings.Index(
source,
"if releaseManaged && !coroTargetReleaseManagedExecutionV1(boundary.driver)",
"if releaseManaged && !coroTargetReleaseManagedExecutionAtRouteV1(",
)
request := strings.Index(
source,
Expand Down
100 changes: 53 additions & 47 deletions runtime/internal/coro/deferred_executor_handoff.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,28 @@ func (*deferredExecutorHandoffNoCopy) Lock() {}
func (*deferredExecutorHandoffNoCopy) Unlock() {}

// DeferredExecutorHandoff is a pointer-free, stable-address dispatch gate for
// a replacement which has already obtained an exact ExecutionDomainHandoff
// and directory slot but has not yet consumed a physical thread. Arm happens
// only after the blocked owner releases its managed-execution permit. A
// durable target request and the returning owner then race one CAS:
// a replacement whose exact ExecutionDomainHandoff has been published but
// whose directory slot and physical thread are both still demand-lazy. Arm
// happens only after the blocked owner releases its managed-execution permit.
// A durable target request and the returning owner then race one CAS:
//
// - BeginStart wins and must publish Queued or Started;
// - Withdraw wins and proves that no physical owner was dispatched.
//
// Starting is a short publication interval, not a scheduler wait state. The
// returning owner may yield until the request publisher records the outcome.
// Queued distinguishes an asynchronously dispatched cached thread, which can
// still be canceled before C-to-Go dispatch, from a synchronously acknowledged
// start. Complete is called only after the ordinary generation-bound return and
// Armed and Starting carry no directory slot. The unique Starting publisher
// allocates one and includes it only when publishing Queued or Started. Starting
// is a short publication interval, not a scheduler wait state; the returning
// owner may yield until the request publisher records the outcome. Queued
// distinguishes an asynchronously dispatched cached thread, which can still be
// canceled before C-to-Go dispatch, from a synchronously acknowledged start.
// Complete is called only after the ordinary generation-bound return and
// strong-recycle protocol has finished.
//
// Slot is deliberately a routing hint rather than a generation capability. A
// delayed accepted request may start a later armed use of the same slot; that
// is a safe coalesced compensation request. ExecutionDomainHandoff remains the
// authority which prevents a stale physical owner from claiming a later call.
// delayed accepted request may start a later armed use of the same stable
// parent; that is a safe coalesced compensation request. ExecutionDomainHandoff
// remains the authority which prevents a stale physical owner from claiming a
// later call.
type DeferredExecutorHandoff struct {
noCopy deferredExecutorHandoffNoCopy
state uint32
Expand All @@ -76,80 +79,83 @@ func deferredExecutorHandoffUnpack(state uint32) (uint32, DeferredExecutorHandof
}

func deferredExecutorHandoffValid(slot uint32, phase DeferredExecutorHandoffPhase) bool {
if phase == DeferredExecutorHandoffIdle {
switch phase {
case DeferredExecutorHandoffIdle,
DeferredExecutorHandoffArmed,
DeferredExecutorHandoffStarting:
return slot == 0
case DeferredExecutorHandoffQueued,
DeferredExecutorHandoffStarted:
return slot != 0 && slot <= deferredExecutorHandoffSlotMask
default:
return false
}
return slot != 0 && slot <= deferredExecutorHandoffSlotMask &&
phase <= DeferredExecutorHandoffStarted
}

// Arm publishes one prepared replacement after its managed-execution permit
// has been released. The zero value is reusable Idle.
func (handoff *DeferredExecutorHandoff) Arm(slot uint32) bool {
return handoff != nil && deferredExecutorHandoffValid(slot, DeferredExecutorHandoffArmed) &&
preemptCompareAndSwap(
&handoff.state,
0,
deferredExecutorHandoffPack(slot, DeferredExecutorHandoffArmed),
)
// Arm publishes one demand-lazy replacement after its managed-execution
// permit has been released. The zero value is reusable Idle.
func (handoff *DeferredExecutorHandoff) Arm() bool {
return handoff != nil && preemptCompareAndSwap(
&handoff.state,
0,
deferredExecutorHandoffPack(0, DeferredExecutorHandoffArmed),
)
}

// BeginStart lets one accepted durable executor request become the unique
// physical-start publisher. A false result means there is no armed replacement
// to start; Idle and an already-starting/started request are both benign.
func (handoff *DeferredExecutorHandoff) BeginStart() (slot uint32, started bool) {
func (handoff *DeferredExecutorHandoff) BeginStart() bool {
if handoff == nil {
return 0, false
return false
}
state := preemptLoad(&handoff.state)
slot, phase := deferredExecutorHandoffUnpack(state)
if !deferredExecutorHandoffValid(slot, phase) || phase != DeferredExecutorHandoffArmed {
return 0, false
return false
}
return slot, preemptCompareAndSwap(
return preemptCompareAndSwap(
&handoff.state,
state,
deferredExecutorHandoffPack(slot, DeferredExecutorHandoffStarting),
deferredExecutorHandoffPack(0, DeferredExecutorHandoffStarting),
)
}

// PublishStart completes the unique Starting interval. queued records whether
// the cached-thread dispatch can still be withdrawn through its C token.
func (handoff *DeferredExecutorHandoff) PublishStart(slot uint32, queued bool) bool {
if handoff == nil || !deferredExecutorHandoffValid(slot, DeferredExecutorHandoffStarting) {
return false
}
phase := DeferredExecutorHandoffStarted
if queued {
phase = DeferredExecutorHandoffQueued
}
if handoff == nil || !deferredExecutorHandoffValid(slot, phase) {
return false
}
return preemptCompareAndSwap(
&handoff.state,
deferredExecutorHandoffPack(slot, DeferredExecutorHandoffStarting),
deferredExecutorHandoffPack(0, DeferredExecutorHandoffStarting),
deferredExecutorHandoffPack(slot, phase),
)
}

// RetryStart returns a failed physical-start publication to Armed. The durable
// request caller must report failure; a later request may retry, while a
// concurrently returning owner may withdraw the restored arm.
func (handoff *DeferredExecutorHandoff) RetryStart(slot uint32) bool {
return handoff != nil && deferredExecutorHandoffValid(slot, DeferredExecutorHandoffStarting) &&
preemptCompareAndSwap(
&handoff.state,
deferredExecutorHandoffPack(slot, DeferredExecutorHandoffStarting),
deferredExecutorHandoffPack(slot, DeferredExecutorHandoffArmed),
)
func (handoff *DeferredExecutorHandoff) RetryStart() bool {
return handoff != nil && preemptCompareAndSwap(
&handoff.state,
deferredExecutorHandoffPack(0, DeferredExecutorHandoffStarting),
deferredExecutorHandoffPack(0, DeferredExecutorHandoffArmed),
)
}

// Withdraw wins only before a durable request has begun physical dispatch.
func (handoff *DeferredExecutorHandoff) Withdraw(slot uint32) bool {
return handoff != nil && deferredExecutorHandoffValid(slot, DeferredExecutorHandoffArmed) &&
preemptCompareAndSwap(
&handoff.state,
deferredExecutorHandoffPack(slot, DeferredExecutorHandoffArmed),
0,
)
func (handoff *DeferredExecutorHandoff) Withdraw() bool {
return handoff != nil && preemptCompareAndSwap(
&handoff.state,
deferredExecutorHandoffPack(0, DeferredExecutorHandoffArmed),
0,
)
}

// Observe returns one atomic state snapshot. ok rejects an impossible packed
Expand Down
39 changes: 21 additions & 18 deletions runtime/internal/coro/deferred_executor_handoff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@ import (

func TestDeferredExecutorHandoffWithdraw(t *testing.T) {
var handoff DeferredExecutorHandoff
if !handoff.Idle() || !handoff.Arm(17) || handoff.Arm(18) {
if !handoff.Idle() || !handoff.Arm() || handoff.Arm() {
t.Fatal("arm deferred executor handoff")
}
if slot, phase, ok := handoff.Observe(); !ok || slot != 17 || phase != DeferredExecutorHandoffArmed {
if slot, phase, ok := handoff.Observe(); !ok || slot != 0 || phase != DeferredExecutorHandoffArmed {
t.Fatalf("armed snapshot = (%d, %d, %t)", slot, phase, ok)
}
if handoff.Withdraw(18) || !handoff.Withdraw(17) || !handoff.Idle() {
if !handoff.Withdraw() || handoff.Withdraw() || !handoff.Idle() {
t.Fatal("withdraw deferred executor handoff")
}
}

func TestDeferredExecutorHandoffStartOutcomes(t *testing.T) {
for _, queued := range []bool{false, true} {
var handoff DeferredExecutorHandoff
if !handoff.Arm(23) {
if !handoff.Arm() {
t.Fatal("arm deferred executor handoff")
}
slot, begun := handoff.BeginStart()
if !begun || slot != 23 || handoff.Withdraw(23) ||
const slot = uint32(23)
if !handoff.BeginStart() || handoff.Withdraw() ||
!handoff.PublishStart(slot, queued) {
t.Fatalf("publish deferred start queued=%t", queued)
}
Expand All @@ -60,14 +60,13 @@ func TestDeferredExecutorHandoffStartOutcomes(t *testing.T) {

func TestDeferredExecutorHandoffRetry(t *testing.T) {
var handoff DeferredExecutorHandoff
if !handoff.Arm(29) {
if !handoff.Arm() {
t.Fatal("arm deferred executor handoff")
}
slot, begun := handoff.BeginStart()
if !begun || slot != 29 || !handoff.RetryStart(slot) {
if !handoff.BeginStart() || !handoff.RetryStart() {
t.Fatal("retry deferred executor start")
}
if !handoff.Withdraw(slot) || !handoff.Idle() {
if !handoff.Withdraw() || !handoff.Idle() {
t.Fatal("withdraw retried deferred executor handoff")
}
}
Expand All @@ -76,7 +75,7 @@ func TestDeferredExecutorHandoffStartWithdrawRace(t *testing.T) {
const iterations = 2_000
for iteration := 0; iteration < iterations; iteration++ {
var handoff DeferredExecutorHandoff
if !handoff.Arm(31) {
if !handoff.Arm() {
t.Fatal("arm deferred executor handoff")
}
var wait sync.WaitGroup
Expand All @@ -85,15 +84,15 @@ func TestDeferredExecutorHandoffStartWithdrawRace(t *testing.T) {
withdrawn := make(chan bool, 1)
go func() {
defer wait.Done()
slot, ok := handoff.BeginStart()
if ok && !handoff.PublishStart(slot, true) {
ok := handoff.BeginStart()
if ok && !handoff.PublishStart(31, true) {
t.Errorf("publish winning start at iteration %d", iteration)
}
started <- ok
}()
go func() {
defer wait.Done()
withdrawn <- handoff.Withdraw(31)
withdrawn <- handoff.Withdraw()
}()
wait.Wait()
startWon, withdrawWon := <-started, <-withdrawn
Expand All @@ -113,10 +112,14 @@ func TestDeferredExecutorHandoffStartWithdrawRace(t *testing.T) {

func TestDeferredExecutorHandoffRejectsInvalidSlots(t *testing.T) {
var handoff DeferredExecutorHandoff
if handoff.Arm(0) || handoff.Arm(deferredExecutorHandoffSlotMask+1) {
t.Fatal("accepted invalid deferred executor slot")
}
if _, begun := handoff.BeginStart(); begun {
if handoff.BeginStart() {
t.Fatal("started idle deferred executor handoff")
}
if !handoff.Arm() || !handoff.BeginStart() {
t.Fatal("cannot begin deferred executor handoff")
}
if handoff.PublishStart(0, false) ||
handoff.PublishStart(deferredExecutorHandoffSlotMask+1, false) {
t.Fatal("accepted invalid deferred executor slot")
}
}
Loading