From 93722181071cd124ad5bb67122d33b31d4ada632 Mon Sep 17 00:00:00 2001 From: bakape Date: Wed, 1 Jan 2020 19:34:56 +0200 Subject: [PATCH] Don't synchronize with context.Background() --- benchmark_test.go | 12 +++++++---- doc.go | 4 +--- pgconn.go | 52 +++++++++++++++++++++++++++++++++-------------- 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/benchmark_test.go b/benchmark_test.go index 1914e07a..4cce5a97 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -18,8 +18,10 @@ func BenchmarkConnect(b *testing.B) { }{ // The first benchmark in the list sometimes executes faster, no matter how // you reorder it. Nil context is still faster on average. - {"Unix socket", "PGX_TEST_UNIX_SOCKET_CONN_STRING", context.Background()}, - {"TCP", "PGX_TEST_TCP_CONN_STRING", context.Background()}, + // + // Using and empty context other than context.Background() to compare. + {"Unix socket", "PGX_TEST_UNIX_SOCKET_CONN_STRING", context.TODO()}, + {"TCP", "PGX_TEST_TCP_CONN_STRING", context.TODO()}, {"Unix socket nil context", "PGX_TEST_UNIX_SOCKET_CONN_STRING", nil}, {"TCP nil context", "PGX_TEST_TCP_CONN_STRING", nil}, } @@ -49,7 +51,8 @@ func BenchmarkExec(b *testing.B) { name string ctx context.Context }{ - {"background context", context.Background()}, + // Using and empty context other than context.Background() to compare. + {"empty context", context.TODO()}, {"nil context", nil}, } @@ -153,7 +156,8 @@ func BenchmarkExecPrepared(b *testing.B) { name string ctx context.Context }{ - {"background context", context.Background()}, + // Using and empty context other than context.Background() to compare. + {"empty context", context.TODO()}, {"nil context", nil}, } diff --git a/doc.go b/doc.go index 12ed6630..25382c68 100644 --- a/doc.go +++ b/doc.go @@ -22,9 +22,7 @@ Context Support All potentially blocking operations take a context.Context. If a context is canceled while the method is in progress the method immediately returns. In most circumstances, this will close the underlying connection. - -A nil context can be passed for convenience. This has the same effect as passing context.Background() with an additional -slight performance increase, if you don't need the operation to be cancellable. +A nil context can be passed for convenience. This has the same effect as passing context.Background(). The CancelRequest method may be used to request the PostgreSQL server cancel an in-progress query without forcing the client to abort. diff --git a/pgconn.go b/pgconn.go index 3b90b802..b8ea9df7 100644 --- a/pgconn.go +++ b/pgconn.go @@ -366,7 +366,9 @@ func (pgConn *PgConn) SendBytes(ctx context.Context, buf []byte) error { } defer pgConn.unlock() - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: select { case <-ctx.Done(): return &contextAlreadyDoneError{err: ctx.Err()} @@ -398,7 +400,9 @@ func (pgConn *PgConn) ReceiveMessage(ctx context.Context) (pgproto3.BackendMessa } defer pgConn.unlock() - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: select { case <-ctx.Done(): return nil, &contextAlreadyDoneError{err: ctx.Err()} @@ -497,7 +501,9 @@ func (pgConn *PgConn) Close(ctx context.Context) error { defer pgConn.conn.Close() - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: pgConn.contextWatcher.Watch(ctx) defer pgConn.contextWatcher.Unwatch() } @@ -596,7 +602,9 @@ func (pgConn *PgConn) Prepare(ctx context.Context, name, sql string, paramOIDs [ } defer pgConn.unlock() - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: select { case <-ctx.Done(): return nil, &contextAlreadyDoneError{err: ctx.Err()} @@ -695,7 +703,9 @@ func (pgConn *PgConn) CancelRequest(ctx context.Context) error { } defer cancelConn.Close() - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: contextWatcher := ctxwatch.NewContextWatcher( func() { cancelConn.SetDeadline(time.Date(1, 1, 1, 1, 1, 1, 1, time.UTC)) }, func() { cancelConn.SetDeadline(time.Time{}) }, @@ -730,7 +740,9 @@ func (pgConn *PgConn) WaitForNotification(ctx context.Context) error { } defer pgConn.unlock() - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: select { case <-ctx.Done(): return ctx.Err() @@ -772,7 +784,11 @@ func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader { ctx: ctx, } multiResult := &pgConn.multiResultReader - if ctx != nil { + switch ctx { + case nil: + pgConn.multiResultReader.ctx = context.Background() + case context.Background(): + default: select { case <-ctx.Done(): multiResult.closed = true @@ -782,8 +798,6 @@ func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader { default: } pgConn.contextWatcher.Watch(ctx) - } else { - pgConn.multiResultReader.ctx = context.Background() } buf := pgConn.wbuf @@ -885,7 +899,9 @@ func (pgConn *PgConn) execExtendedPrefix(ctx context.Context, paramValues [][]by return result } - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: select { case <-ctx.Done(): result.concludeCommand(nil, &contextAlreadyDoneError{err: ctx.Err()}) @@ -921,7 +937,9 @@ func (pgConn *PgConn) CopyTo(ctx context.Context, w io.Writer, sql string) (Comm return nil, err } - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: select { case <-ctx.Done(): pgConn.unlock() @@ -982,7 +1000,9 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co } defer pgConn.unlock() - if ctx != nil { + switch ctx { + case nil, context.Background(): + default: select { case <-ctx.Done(): return nil, &contextAlreadyDoneError{err: ctx.Err()} @@ -1376,7 +1396,11 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR ctx: ctx, } multiResult := &pgConn.multiResultReader - if ctx != nil { + switch ctx { + case nil: + pgConn.multiResultReader.ctx = context.Background() + case context.Background(): + default: select { case <-ctx.Done(): multiResult.closed = true @@ -1386,8 +1410,6 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR default: } pgConn.contextWatcher.Watch(ctx) - } else { - pgConn.multiResultReader.ctx = context.Background() } batch.buf = (&pgproto3.Sync{}).Encode(batch.buf)