Reuse the same channel for all precompleted contexts
authorJoe Wreschnig <joe.wreschnig@gmail.com>
Sat, 13 Jun 2020 15:41:23 +0000 (17:41 +0200)
committerJoe Wreschnig <joe.wreschnig@gmail.com>
Sun, 14 Jun 2020 13:50:00 +0000 (15:50 +0200)
This avoids making a new channel and immediately closing it. `benchcmp`
says:

    benchmark                      old ns/op     new ns/op     delta
    BenchmarkPrecompleted-4        213           138           -35.21%

    benchmark                      old allocs    new allocs    delta
    BenchmarkPrecompleted-4        3             2             -33.33%

    benchmark                      old bytes     new bytes     delta
    BenchmarkPrecompleted-4        176           80            -54.55%

context.go

index 1bd24d3..3681417 100644 (file)
@@ -28,14 +28,14 @@ type Context struct {
 func UntilSignal(parent context.Context, sig ...os.Signal) *Context {
        ctx := new(Context)
        ctx.parent = parent
-       ctx.done = make(chan struct{})
 
        if err := parent.Err(); err != nil {
-               close(ctx.done)
+               ctx.done = alreadyclosed
                ctx.err = err
                return ctx
        }
 
+       ctx.done = make(chan struct{})
        ctx.c = make(chan os.Signal, 1)
        signal.Notify(ctx.c, sig...)
        go ctx.wait(sig...)
@@ -103,3 +103,11 @@ func (s *Context) Err() error {
        s.m.Unlock()
        return err
 }
+
+// Reuse the same channel for all contexts which begin life already
+// completed.
+var alreadyclosed = make(chan struct{})
+
+func init() {
+       close(alreadyclosed)
+}