mirror of https://github.com/jackc/pgx.git
323 lines
7.4 KiB
Go
323 lines
7.4 KiB
Go
package pgconn_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/jackc/pgx/v5/pgconn"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func BenchmarkConnect(b *testing.B) {
|
|
benchmarks := []struct {
|
|
name string
|
|
env string
|
|
}{
|
|
{"Unix socket", "PGX_TEST_UNIX_SOCKET_CONN_STRING"},
|
|
{"TCP", "PGX_TEST_TCP_CONN_STRING"},
|
|
}
|
|
|
|
for _, bm := range benchmarks {
|
|
bm := bm
|
|
b.Run(bm.name, func(b *testing.B) {
|
|
connString := os.Getenv(bm.env)
|
|
if connString == "" {
|
|
b.Skipf("Skipping due to missing environment variable %v", bm.env)
|
|
}
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
conn, err := pgconn.Connect(context.Background(), connString)
|
|
require.Nil(b, err)
|
|
|
|
err = conn.Close(context.Background())
|
|
require.Nil(b, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkExec(b *testing.B) {
|
|
expectedValues := [][]byte{[]byte("hello"), []byte("42"), []byte("2019-01-01")}
|
|
benchmarks := []struct {
|
|
name string
|
|
ctx context.Context
|
|
}{
|
|
// Using an empty context other than context.Background() to compare
|
|
// performance
|
|
{"background context", context.Background()},
|
|
{"empty context", context.TODO()},
|
|
}
|
|
|
|
for _, bm := range benchmarks {
|
|
bm := bm
|
|
b.Run(bm.name, func(b *testing.B) {
|
|
conn, err := pgconn.Connect(bm.ctx, os.Getenv("PGX_TEST_CONN_STRING"))
|
|
require.Nil(b, err)
|
|
defer closeConn(b, conn)
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
mrr := conn.Exec(bm.ctx, "select 'hello'::text as a, 42::int4 as b, '2019-01-01'::date")
|
|
|
|
for mrr.NextResult() {
|
|
rr := mrr.ResultReader()
|
|
|
|
rowCount := 0
|
|
for rr.NextRow() {
|
|
rowCount++
|
|
if len(rr.Values()) != len(expectedValues) {
|
|
b.Fatalf("unexpected number of values: %d", len(rr.Values()))
|
|
}
|
|
for i := range rr.Values() {
|
|
if !bytes.Equal(rr.Values()[i], expectedValues[i]) {
|
|
b.Fatalf("unexpected values: %s %s", rr.Values()[i], expectedValues[i])
|
|
}
|
|
}
|
|
}
|
|
_, err = rr.Close()
|
|
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if rowCount != 1 {
|
|
b.Fatalf("unexpected rowCount: %d", rowCount)
|
|
}
|
|
}
|
|
|
|
err := mrr.Close()
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkExecPossibleToCancel(b *testing.B) {
|
|
conn, err := pgconn.Connect(context.Background(), os.Getenv("PGX_TEST_CONN_STRING"))
|
|
require.Nil(b, err)
|
|
defer closeConn(b, conn)
|
|
|
|
expectedValues := [][]byte{[]byte("hello"), []byte("42"), []byte("2019-01-01")}
|
|
|
|
b.ResetTimer()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
mrr := conn.Exec(ctx, "select 'hello'::text as a, 42::int4 as b, '2019-01-01'::date")
|
|
|
|
for mrr.NextResult() {
|
|
rr := mrr.ResultReader()
|
|
|
|
rowCount := 0
|
|
for rr.NextRow() {
|
|
rowCount++
|
|
if len(rr.Values()) != len(expectedValues) {
|
|
b.Fatalf("unexpected number of values: %d", len(rr.Values()))
|
|
}
|
|
for i := range rr.Values() {
|
|
if !bytes.Equal(rr.Values()[i], expectedValues[i]) {
|
|
b.Fatalf("unexpected values: %s %s", rr.Values()[i], expectedValues[i])
|
|
}
|
|
}
|
|
}
|
|
_, err = rr.Close()
|
|
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if rowCount != 1 {
|
|
b.Fatalf("unexpected rowCount: %d", rowCount)
|
|
}
|
|
}
|
|
|
|
err := mrr.Close()
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkExecPrepared(b *testing.B) {
|
|
expectedValues := [][]byte{[]byte("hello"), []byte("42"), []byte("2019-01-01")}
|
|
|
|
benchmarks := []struct {
|
|
name string
|
|
ctx context.Context
|
|
}{
|
|
// Using an empty context other than context.Background() to compare
|
|
// performance
|
|
{"background context", context.Background()},
|
|
{"empty context", context.TODO()},
|
|
}
|
|
|
|
for _, bm := range benchmarks {
|
|
bm := bm
|
|
b.Run(bm.name, func(b *testing.B) {
|
|
conn, err := pgconn.Connect(bm.ctx, os.Getenv("PGX_TEST_CONN_STRING"))
|
|
require.Nil(b, err)
|
|
defer closeConn(b, conn)
|
|
|
|
_, err = conn.Prepare(bm.ctx, "ps1", "select 'hello'::text as a, 42::int4 as b, '2019-01-01'::date", nil)
|
|
require.Nil(b, err)
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
rr := conn.ExecPrepared(bm.ctx, "ps1", nil, nil, nil)
|
|
|
|
rowCount := 0
|
|
for rr.NextRow() {
|
|
rowCount++
|
|
if len(rr.Values()) != len(expectedValues) {
|
|
b.Fatalf("unexpected number of values: %d", len(rr.Values()))
|
|
}
|
|
for i := range rr.Values() {
|
|
if !bytes.Equal(rr.Values()[i], expectedValues[i]) {
|
|
b.Fatalf("unexpected values: %s %s", rr.Values()[i], expectedValues[i])
|
|
}
|
|
}
|
|
}
|
|
_, err = rr.Close()
|
|
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if rowCount != 1 {
|
|
b.Fatalf("unexpected rowCount: %d", rowCount)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkExecPreparedPossibleToCancel(b *testing.B) {
|
|
conn, err := pgconn.Connect(context.Background(), os.Getenv("PGX_TEST_CONN_STRING"))
|
|
require.Nil(b, err)
|
|
defer closeConn(b, conn)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
_, err = conn.Prepare(ctx, "ps1", "select 'hello'::text as a, 42::int4 as b, '2019-01-01'::date", nil)
|
|
require.Nil(b, err)
|
|
|
|
expectedValues := [][]byte{[]byte("hello"), []byte("42"), []byte("2019-01-01")}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
rr := conn.ExecPrepared(ctx, "ps1", nil, nil, nil)
|
|
|
|
rowCount := 0
|
|
for rr.NextRow() {
|
|
rowCount += 1
|
|
if len(rr.Values()) != len(expectedValues) {
|
|
b.Fatalf("unexpected number of values: %d", len(rr.Values()))
|
|
}
|
|
for i := range rr.Values() {
|
|
if !bytes.Equal(rr.Values()[i], expectedValues[i]) {
|
|
b.Fatalf("unexpected values: %s %s", rr.Values()[i], expectedValues[i])
|
|
}
|
|
}
|
|
}
|
|
_, err = rr.Close()
|
|
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if rowCount != 1 {
|
|
b.Fatalf("unexpected rowCount: %d", rowCount)
|
|
}
|
|
}
|
|
}
|
|
|
|
// func BenchmarkChanToSetDeadlinePossibleToCancel(b *testing.B) {
|
|
// conn, err := pgconn.Connect(context.Background(), os.Getenv("PGX_TEST_CONN_STRING"))
|
|
// require.Nil(b, err)
|
|
// defer closeConn(b, conn)
|
|
|
|
// ctx, cancel := context.WithCancel(context.Background())
|
|
// defer cancel()
|
|
|
|
// b.ResetTimer()
|
|
|
|
// for i := 0; i < b.N; i++ {
|
|
// conn.ChanToSetDeadline().Watch(ctx)
|
|
// conn.ChanToSetDeadline().Ignore()
|
|
// }
|
|
// }
|
|
|
|
func BenchmarkCommandTagRowsAffected(b *testing.B) {
|
|
benchmarks := []struct {
|
|
commandTag string
|
|
rowsAffected int64
|
|
}{
|
|
{"UPDATE 1", 1},
|
|
{"UPDATE 123456789", 123456789},
|
|
{"INSERT 0 1", 1},
|
|
{"INSERT 0 123456789", 123456789},
|
|
}
|
|
|
|
for _, bm := range benchmarks {
|
|
ct := pgconn.CommandTag(bm.commandTag)
|
|
b.Run(bm.commandTag, func(b *testing.B) {
|
|
var n int64
|
|
for i := 0; i < b.N; i++ {
|
|
n = ct.RowsAffected()
|
|
}
|
|
if n != bm.rowsAffected {
|
|
b.Errorf("expected %d got %d", bm.rowsAffected, n)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkCommandTagTypeFromString(b *testing.B) {
|
|
ct := pgconn.CommandTag("UPDATE 1")
|
|
|
|
var update bool
|
|
for i := 0; i < b.N; i++ {
|
|
update = strings.HasPrefix(ct.String(), "UPDATE")
|
|
}
|
|
if !update {
|
|
b.Error("expected update")
|
|
}
|
|
}
|
|
|
|
func BenchmarkCommandTagInsert(b *testing.B) {
|
|
benchmarks := []struct {
|
|
commandTag string
|
|
is bool
|
|
}{
|
|
{"INSERT 1", true},
|
|
{"INSERT 1234567890", true},
|
|
{"UPDATE 1", false},
|
|
{"UPDATE 1234567890", false},
|
|
{"DELETE 1", false},
|
|
{"DELETE 1234567890", false},
|
|
{"SELECT 1", false},
|
|
{"SELECT 1234567890", false},
|
|
{"UNKNOWN 1234567890", false},
|
|
}
|
|
|
|
for _, bm := range benchmarks {
|
|
ct := pgconn.CommandTag(bm.commandTag)
|
|
b.Run(bm.commandTag, func(b *testing.B) {
|
|
var is bool
|
|
for i := 0; i < b.N; i++ {
|
|
is = ct.Insert()
|
|
}
|
|
if is != bm.is {
|
|
b.Errorf("expected %v got %v", bm.is, is)
|
|
}
|
|
})
|
|
}
|
|
}
|