@@ -46,10 +46,10 @@ func (tb *TB) checkStmt(stmt *sql.Stmt, err error) *sql.Stmt {
4646 return stmt
4747}
4848
49- func initDB (b * testing.B , useCompression bool , queries ... string ) * sql.DB {
49+ func initDB (b * testing.B , compress bool , queries ... string ) * sql.DB {
5050 tb := (* TB )(b )
5151 comprStr := ""
52- if useCompression {
52+ if compress {
5353 comprStr = "&compress=1"
5454 }
5555 db := tb .checkDB (sql .Open (driverNameTest , dsn + comprStr ))
@@ -64,16 +64,15 @@ func initDB(b *testing.B, useCompression bool, queries ...string) *sql.DB {
6464const concurrencyLevel = 10
6565
6666func BenchmarkQuery (b * testing.B ) {
67- benchmarkQueryHelper (b , false )
67+ benchmarkQuery (b , false )
6868}
6969
70- func BenchmarkQueryCompression (b * testing.B ) {
71- benchmarkQueryHelper (b , true )
70+ func BenchmarkQueryCompressed (b * testing.B ) {
71+ benchmarkQuery (b , true )
7272}
7373
74- func benchmarkQueryHelper (b * testing.B , compr bool ) {
74+ func benchmarkQuery (b * testing.B , compr bool ) {
7575 tb := (* TB )(b )
76- b .StopTimer ()
7776 b .ReportAllocs ()
7877 db := initDB (b , compr ,
7978 "DROP TABLE IF EXISTS foo" ,
@@ -115,8 +114,6 @@ func benchmarkQueryHelper(b *testing.B, compr bool) {
115114
116115func BenchmarkExec (b * testing.B ) {
117116 tb := (* TB )(b )
118- b .StopTimer ()
119- b .ReportAllocs ()
120117 db := tb .checkDB (sql .Open (driverNameTest , dsn ))
121118 db .SetMaxIdleConns (concurrencyLevel )
122119 defer db .Close ()
@@ -128,9 +125,17 @@ func BenchmarkExec(b *testing.B) {
128125 var wg sync.WaitGroup
129126 wg .Add (concurrencyLevel )
130127 defer wg .Wait ()
131- b .StartTimer ()
132128
129+ << << << < HEAD
133130 for i := 0 ; i < concurrencyLevel ; i ++ {
131+ || || || | parent of f7d94ec (add BenchmarkReceive10kRowsCompress (#1704 ))
132+ for range concurrencyLevel {
133+ == == == =
134+ b .ReportAllocs ()
135+ b .ResetTimer ()
136+
137+ for i := 0 ; i < concurrencyLevel ; i ++ {
138+ >> >> >> > f7d94ec (add BenchmarkReceive10kRowsCompress (#1704 ))
134139 go func () {
135140 for {
136141 if atomic .AddInt64 (& remain , - 1 ) < 0 {
@@ -158,14 +163,15 @@ func initRoundtripBenchmarks() ([]byte, int, int) {
158163}
159164
160165func BenchmarkRoundtripTxt (b * testing.B ) {
161- b .StopTimer ()
162166 sample , min , max := initRoundtripBenchmarks ()
163167 sampleString := string (sample )
164- b .ReportAllocs ()
165168 tb := (* TB )(b )
166169 db := tb .checkDB (sql .Open (driverNameTest , dsn ))
167170 defer db .Close ()
168- b .StartTimer ()
171+
172+ b .ReportAllocs ()
173+ b .ResetTimer ()
174+
169175 var result string
170176 for i := 0 ; i < b .N ; i ++ {
171177 length := min + i
@@ -192,15 +198,15 @@ func BenchmarkRoundtripTxt(b *testing.B) {
192198}
193199
194200func BenchmarkRoundtripBin (b * testing.B ) {
195- b .StopTimer ()
196201 sample , min , max := initRoundtripBenchmarks ()
197- b .ReportAllocs ()
198202 tb := (* TB )(b )
199203 db := tb .checkDB (sql .Open (driverNameTest , dsn ))
200204 defer db .Close ()
201205 stmt := tb .checkStmt (db .Prepare ("SELECT ?" ))
202206 defer stmt .Close ()
203- b .StartTimer ()
207+
208+ b .ReportAllocs ()
209+ b .ResetTimer ()
204210 var result sql.RawBytes
205211 for i := 0 ; i < b .N ; i ++ {
206212 length := min + i
@@ -385,10 +391,9 @@ func BenchmarkQueryRawBytes(b *testing.B) {
385391 }
386392}
387393
388- // BenchmarkReceiveMassiveRows measures performance of receiving large number of rows.
389- func BenchmarkReceiveMassiveRows (b * testing.B ) {
394+ func benchmark10kRows (b * testing.B , compress bool ) {
390395 // Setup -- prepare 10000 rows.
391- db := initDB (b , false ,
396+ db := initDB (b , compress ,
392397 "DROP TABLE IF EXISTS foo" ,
393398 "CREATE TABLE foo (id INT PRIMARY KEY, val TEXT)" )
394399 defer db .Close ()
@@ -399,11 +404,14 @@ func BenchmarkReceiveMassiveRows(b *testing.B) {
399404 b .Errorf ("failed to prepare query: %v" , err )
400405 return
401406 }
407+
408+ args := make ([]any , 200 )
409+ for i := 1 ; i < 200 ; i += 2 {
410+ args [i ] = sval
411+ }
402412 for i := 0 ; i < 10000 ; i += 100 {
403- args := make ([]any , 200 )
404413 for j := 0 ; j < 100 ; j ++ {
405414 args [j * 2 ] = i + j
406- args [j * 2 + 1 ] = sval
407415 }
408416 _ , err := stmt .Exec (args ... )
409417 if err != nil {
@@ -413,30 +421,43 @@ func BenchmarkReceiveMassiveRows(b *testing.B) {
413421 }
414422 stmt .Close ()
415423
416- // Use b.Run() to skip expensive setup.
424+ // benchmark function called several times with different b.N.
425+ // it means heavy setup is called multiple times.
426+ // Use b.Run() to run expensive setup only once.
427+ // Go 1.24 introduced b.Loop() for this purpose. But we keep this
428+ // benchmark compatible with Go 1.20.
417429 b .Run ("query" , func (b * testing.B ) {
418430 b .ReportAllocs ()
419-
420431 for i := 0 ; i < b .N ; i ++ {
421432 rows , err := db .Query (`SELECT id, val FROM foo` )
422433 if err != nil {
423434 b .Errorf ("failed to select: %v" , err )
424435 return
425436 }
437+ // rows.Scan() escapes arguments. So these variables must be defined
438+ // before loop.
439+ var i int
440+ var s sql.RawBytes
426441 for rows .Next () {
427- var i int
428- var s sql.RawBytes
429- err = rows .Scan (& i , & s )
430- if err != nil {
442+ if err := rows .Scan (& i , & s ); err != nil {
431443 b .Errorf ("failed to scan: %v" , err )
432- _ = rows .Close ()
444+ rows .Close ()
433445 return
434446 }
435447 }
436448 if err = rows .Err (); err != nil {
437449 b .Errorf ("failed to read rows: %v" , err )
438450 }
439- _ = rows .Close ()
451+ rows .Close ()
440452 }
441453 })
442454}
455+
456+ // BenchmarkReceive10kRows measures performance of receiving large number of rows.
457+ func BenchmarkReceive10kRows (b * testing.B ) {
458+ benchmark10kRows (b , false )
459+ }
460+
461+ func BenchmarkReceive10kRowsCompressed (b * testing.B ) {
462+ benchmark10kRows (b , true )
463+ }
0 commit comments