github.com/jackc/pgx/v5@v5.5.5/pgconn/benchmark_test.go (about) 1 package pgconn_test 2 3 import ( 4 "bytes" 5 "context" 6 "os" 7 "testing" 8 9 "github.com/jackc/pgx/v5/pgconn" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func BenchmarkConnect(b *testing.B) { 14 benchmarks := []struct { 15 name string 16 env string 17 }{ 18 {"Unix socket", "PGX_TEST_UNIX_SOCKET_CONN_STRING"}, 19 {"TCP", "PGX_TEST_TCP_CONN_STRING"}, 20 } 21 22 for _, bm := range benchmarks { 23 bm := bm 24 b.Run(bm.name, func(b *testing.B) { 25 connString := os.Getenv(bm.env) 26 if connString == "" { 27 b.Skipf("Skipping due to missing environment variable %v", bm.env) 28 } 29 30 for i := 0; i < b.N; i++ { 31 conn, err := pgconn.Connect(context.Background(), connString) 32 require.Nil(b, err) 33 34 err = conn.Close(context.Background()) 35 require.Nil(b, err) 36 } 37 }) 38 } 39 } 40 41 func BenchmarkExec(b *testing.B) { 42 expectedValues := [][]byte{[]byte("hello"), []byte("42"), []byte("2019-01-01")} 43 benchmarks := []struct { 44 name string 45 ctx context.Context 46 }{ 47 // Using an empty context other than context.Background() to compare 48 // performance 49 {"background context", context.Background()}, 50 {"empty context", context.TODO()}, 51 } 52 53 for _, bm := range benchmarks { 54 bm := bm 55 b.Run(bm.name, func(b *testing.B) { 56 conn, err := pgconn.Connect(bm.ctx, os.Getenv("PGX_TEST_DATABASE")) 57 require.Nil(b, err) 58 defer closeConn(b, conn) 59 60 b.ResetTimer() 61 62 for i := 0; i < b.N; i++ { 63 mrr := conn.Exec(bm.ctx, "select 'hello'::text as a, 42::int4 as b, '2019-01-01'::date") 64 65 for mrr.NextResult() { 66 rr := mrr.ResultReader() 67 68 rowCount := 0 69 for rr.NextRow() { 70 rowCount++ 71 if len(rr.Values()) != len(expectedValues) { 72 b.Fatalf("unexpected number of values: %d", len(rr.Values())) 73 } 74 for i := range rr.Values() { 75 if !bytes.Equal(rr.Values()[i], expectedValues[i]) { 76 b.Fatalf("unexpected values: %s %s", rr.Values()[i], expectedValues[i]) 77 } 78 } 79 } 80 _, err = rr.Close() 81 82 if err != nil { 83 b.Fatal(err) 84 } 85 if rowCount != 1 { 86 b.Fatalf("unexpected rowCount: %d", rowCount) 87 } 88 } 89 90 err := mrr.Close() 91 if err != nil { 92 b.Fatal(err) 93 } 94 } 95 }) 96 } 97 } 98 99 func BenchmarkExecPossibleToCancel(b *testing.B) { 100 conn, err := pgconn.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE")) 101 require.Nil(b, err) 102 defer closeConn(b, conn) 103 104 expectedValues := [][]byte{[]byte("hello"), []byte("42"), []byte("2019-01-01")} 105 106 b.ResetTimer() 107 108 ctx, cancel := context.WithCancel(context.Background()) 109 defer cancel() 110 111 for i := 0; i < b.N; i++ { 112 mrr := conn.Exec(ctx, "select 'hello'::text as a, 42::int4 as b, '2019-01-01'::date") 113 114 for mrr.NextResult() { 115 rr := mrr.ResultReader() 116 117 rowCount := 0 118 for rr.NextRow() { 119 rowCount++ 120 if len(rr.Values()) != len(expectedValues) { 121 b.Fatalf("unexpected number of values: %d", len(rr.Values())) 122 } 123 for i := range rr.Values() { 124 if !bytes.Equal(rr.Values()[i], expectedValues[i]) { 125 b.Fatalf("unexpected values: %s %s", rr.Values()[i], expectedValues[i]) 126 } 127 } 128 } 129 _, err = rr.Close() 130 131 if err != nil { 132 b.Fatal(err) 133 } 134 if rowCount != 1 { 135 b.Fatalf("unexpected rowCount: %d", rowCount) 136 } 137 } 138 139 err := mrr.Close() 140 if err != nil { 141 b.Fatal(err) 142 } 143 } 144 } 145 146 func BenchmarkExecPrepared(b *testing.B) { 147 expectedValues := [][]byte{[]byte("hello"), []byte("42"), []byte("2019-01-01")} 148 149 benchmarks := []struct { 150 name string 151 ctx context.Context 152 }{ 153 // Using an empty context other than context.Background() to compare 154 // performance 155 {"background context", context.Background()}, 156 {"empty context", context.TODO()}, 157 } 158 159 for _, bm := range benchmarks { 160 bm := bm 161 b.Run(bm.name, func(b *testing.B) { 162 conn, err := pgconn.Connect(bm.ctx, os.Getenv("PGX_TEST_DATABASE")) 163 require.Nil(b, err) 164 defer closeConn(b, conn) 165 166 _, err = conn.Prepare(bm.ctx, "ps1", "select 'hello'::text as a, 42::int4 as b, '2019-01-01'::date", nil) 167 require.Nil(b, err) 168 169 b.ResetTimer() 170 171 for i := 0; i < b.N; i++ { 172 rr := conn.ExecPrepared(bm.ctx, "ps1", nil, nil, nil) 173 174 rowCount := 0 175 for rr.NextRow() { 176 rowCount++ 177 if len(rr.Values()) != len(expectedValues) { 178 b.Fatalf("unexpected number of values: %d", len(rr.Values())) 179 } 180 for i := range rr.Values() { 181 if !bytes.Equal(rr.Values()[i], expectedValues[i]) { 182 b.Fatalf("unexpected values: %s %s", rr.Values()[i], expectedValues[i]) 183 } 184 } 185 } 186 _, err = rr.Close() 187 188 if err != nil { 189 b.Fatal(err) 190 } 191 if rowCount != 1 { 192 b.Fatalf("unexpected rowCount: %d", rowCount) 193 } 194 } 195 }) 196 } 197 } 198 199 func BenchmarkExecPreparedPossibleToCancel(b *testing.B) { 200 conn, err := pgconn.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE")) 201 require.Nil(b, err) 202 defer closeConn(b, conn) 203 204 ctx, cancel := context.WithCancel(context.Background()) 205 defer cancel() 206 207 _, err = conn.Prepare(ctx, "ps1", "select 'hello'::text as a, 42::int4 as b, '2019-01-01'::date", nil) 208 require.Nil(b, err) 209 210 expectedValues := [][]byte{[]byte("hello"), []byte("42"), []byte("2019-01-01")} 211 212 b.ResetTimer() 213 214 for i := 0; i < b.N; i++ { 215 rr := conn.ExecPrepared(ctx, "ps1", nil, nil, nil) 216 217 rowCount := 0 218 for rr.NextRow() { 219 rowCount += 1 220 if len(rr.Values()) != len(expectedValues) { 221 b.Fatalf("unexpected number of values: %d", len(rr.Values())) 222 } 223 for i := range rr.Values() { 224 if !bytes.Equal(rr.Values()[i], expectedValues[i]) { 225 b.Fatalf("unexpected values: %s %s", rr.Values()[i], expectedValues[i]) 226 } 227 } 228 } 229 _, err = rr.Close() 230 231 if err != nil { 232 b.Fatal(err) 233 } 234 if rowCount != 1 { 235 b.Fatalf("unexpected rowCount: %d", rowCount) 236 } 237 } 238 } 239 240 // func BenchmarkChanToSetDeadlinePossibleToCancel(b *testing.B) { 241 // conn, err := pgconn.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE")) 242 // require.Nil(b, err) 243 // defer closeConn(b, conn) 244 245 // ctx, cancel := context.WithCancel(context.Background()) 246 // defer cancel() 247 248 // b.ResetTimer() 249 250 // for i := 0; i < b.N; i++ { 251 // conn.ChanToSetDeadline().Watch(ctx) 252 // conn.ChanToSetDeadline().Ignore() 253 // } 254 // }