Skip to content

runtime: add fast paths for common select patterns #64900

@CAFxX

Description

@CAFxX

This select:

select {
case <-closedCh: // or otherwise any channel for which the receive won't block
case <-nilCh: // e.g. context.Background().Done()
}

should, ideally, be as fast as this one:

select {
case <-closedCh: // or otherwise any channel for which the receive won't block
default:
}

This is currently not the case though, with the latter being over 2 orders of magnitude faster under contention, and almost 1 with no contention.

goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
                              │    sec/op     │
Select/closed+nil-16             126.6n ±  2%
Select/closed+default-16        0.8886n ± 10%
Select/closed+nil                53.27n ±  0%
Select/closed+default            6.306n ±  0%

In selectgo there is a (pretty old) comment that claims that the code in the first example is "rare enough" that it is not worth optimizing for. I would argue that at least in code I write and maintain, a two-cases select with one of the cases being <-ctx.Done() is pretty common. This would be especially beneficial in libraries, where the library normally has no control over which Context it is passed by the host application, and where the compiler would likely be unable to statically determine that the channel is nil.

AFAICT, to address this, selectgo could - after counting how many non-nil cases exist - dispatch directly to chansend/chanrecv if there is only one non-nil case. This would be somewhat similar to what the compiler does for simple cases, but done dynamically instead of statically.


update: I actually tried it out, and to achieve the speedup it is also going to require extending the fast paths in chanrecv/chansend, but the results are promising:

Select/closed+nil-16        2.360n ±  1%
Select/closed+default-16   0.8645n ± 10%
Select/closed+nil           17.84n ±  1%
Select/closed+default       6.302n ±  0%

go version go1.21.1 darwin/amd64

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performancecompiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    In Progress

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions