Skip to content

Commit f7d94ec

Browse files
authored
add BenchmarkReceive10kRowsCompress (#1704)
* Rename BenchmarkReceiveMassiveRows to BenchmarkReceive10kRows * Add BenchmarkReceive10kRowsCompress that run BenchmarkReceiveMassiveRows with compression * Other tiny benchmark improvements.
1 parent 7da50ff commit f7d94ec

File tree

2 files changed

+52
-33
lines changed

2 files changed

+52
-33
lines changed

.github/workflows/test.yml

+4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ jobs:
9696
run: |
9797
go test -v '-race' '-covermode=atomic' '-coverprofile=coverage.out' -parallel 10
9898
99+
- name: benchmark
100+
run: |
101+
go test -run '^$' -bench .
102+
99103
- name: Send coverage
100104
uses: shogo82148/actions-goveralls@v1
101105
with:

benchmark_test.go

+48-33
Original file line numberDiff line numberDiff line change
@@ -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 {
6464
const concurrencyLevel = 10
6565

6666
func 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",
@@ -93,7 +92,7 @@ func benchmarkQueryHelper(b *testing.B, compr bool) {
9392
defer wg.Wait()
9493
b.StartTimer()
9594

96-
for range concurrencyLevel {
95+
for i := 0; i < concurrencyLevel; i++ {
9796
go func() {
9897
for {
9998
if atomic.AddInt64(&remain, -1) < 0 {
@@ -115,8 +114,6 @@ func benchmarkQueryHelper(b *testing.B, compr bool) {
115114

116115
func 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,11 @@ func BenchmarkExec(b *testing.B) {
128125
var wg sync.WaitGroup
129126
wg.Add(concurrencyLevel)
130127
defer wg.Wait()
131-
b.StartTimer()
132128

133-
for range concurrencyLevel {
129+
b.ReportAllocs()
130+
b.ResetTimer()
131+
132+
for i := 0; i < concurrencyLevel; i++ {
134133
go func() {
135134
for {
136135
if atomic.AddInt64(&remain, -1) < 0 {
@@ -158,14 +157,15 @@ func initRoundtripBenchmarks() ([]byte, int, int) {
158157
}
159158

160159
func BenchmarkRoundtripTxt(b *testing.B) {
161-
b.StopTimer()
162160
sample, min, max := initRoundtripBenchmarks()
163161
sampleString := string(sample)
164-
b.ReportAllocs()
165162
tb := (*TB)(b)
166163
db := tb.checkDB(sql.Open(driverNameTest, dsn))
167164
defer db.Close()
168-
b.StartTimer()
165+
166+
b.ReportAllocs()
167+
b.ResetTimer()
168+
169169
var result string
170170
for i := 0; i < b.N; i++ {
171171
length := min + i
@@ -192,15 +192,15 @@ func BenchmarkRoundtripTxt(b *testing.B) {
192192
}
193193

194194
func BenchmarkRoundtripBin(b *testing.B) {
195-
b.StopTimer()
196195
sample, min, max := initRoundtripBenchmarks()
197-
b.ReportAllocs()
198196
tb := (*TB)(b)
199197
db := tb.checkDB(sql.Open(driverNameTest, dsn))
200198
defer db.Close()
201199
stmt := tb.checkStmt(db.Prepare("SELECT ?"))
202200
defer stmt.Close()
203-
b.StartTimer()
201+
202+
b.ReportAllocs()
203+
b.ResetTimer()
204204
var result sql.RawBytes
205205
for i := 0; i < b.N; i++ {
206206
length := min + i
@@ -345,7 +345,7 @@ func BenchmarkQueryRawBytes(b *testing.B) {
345345
for i := range blob {
346346
blob[i] = 42
347347
}
348-
for i := range 100 {
348+
for i := 0; i < 100; i++ {
349349
_, err := db.Exec("INSERT INTO bench_rawbytes VALUES (?, ?)", i, blob)
350350
if err != nil {
351351
b.Fatal(err)
@@ -385,10 +385,9 @@ func BenchmarkQueryRawBytes(b *testing.B) {
385385
}
386386
}
387387

388-
// BenchmarkReceiveMassiveRows measures performance of receiving large number of rows.
389-
func BenchmarkReceiveMassiveRows(b *testing.B) {
388+
func benchmark10kRows(b *testing.B, compress bool) {
390389
// Setup -- prepare 10000 rows.
391-
db := initDB(b, false,
390+
db := initDB(b, compress,
392391
"DROP TABLE IF EXISTS foo",
393392
"CREATE TABLE foo (id INT PRIMARY KEY, val TEXT)")
394393
defer db.Close()
@@ -399,11 +398,14 @@ func BenchmarkReceiveMassiveRows(b *testing.B) {
399398
b.Errorf("failed to prepare query: %v", err)
400399
return
401400
}
401+
402+
args := make([]any, 200)
403+
for i := 1; i < 200; i+=2 {
404+
args[i] = sval
405+
}
402406
for i := 0; i < 10000; i += 100 {
403-
args := make([]any, 200)
404-
for j := range 100 {
407+
for j := 0; j < 100; j++ {
405408
args[j*2] = i + j
406-
args[j*2+1] = sval
407409
}
408410
_, err := stmt.Exec(args...)
409411
if err != nil {
@@ -413,30 +415,43 @@ func BenchmarkReceiveMassiveRows(b *testing.B) {
413415
}
414416
stmt.Close()
415417

416-
// Use b.Run() to skip expensive setup.
418+
// benchmark function called several times with different b.N.
419+
// it means heavy setup is called multiple times.
420+
// Use b.Run() to run expensive setup only once.
421+
// Go 1.24 introduced b.Loop() for this purpose. But we keep this
422+
// benchmark compatible with Go 1.20.
417423
b.Run("query", func(b *testing.B) {
418424
b.ReportAllocs()
419-
420425
for i := 0; i < b.N; i++ {
421426
rows, err := db.Query(`SELECT id, val FROM foo`)
422427
if err != nil {
423428
b.Errorf("failed to select: %v", err)
424429
return
425430
}
431+
// rows.Scan() escapes arguments. So these variables must be defined
432+
// before loop.
433+
var i int
434+
var s sql.RawBytes
426435
for rows.Next() {
427-
var i int
428-
var s sql.RawBytes
429-
err = rows.Scan(&i, &s)
430-
if err != nil {
436+
if err := rows.Scan(&i, &s); err != nil {
431437
b.Errorf("failed to scan: %v", err)
432-
_ = rows.Close()
438+
rows.Close()
433439
return
434440
}
435441
}
436442
if err = rows.Err(); err != nil {
437443
b.Errorf("failed to read rows: %v", err)
438444
}
439-
_ = rows.Close()
445+
rows.Close()
440446
}
441447
})
442448
}
449+
450+
// BenchmarkReceive10kRows measures performance of receiving large number of rows.
451+
func BenchmarkReceive10kRows(b *testing.B) {
452+
benchmark10kRows(b, false)
453+
}
454+
455+
func BenchmarkReceive10kRowsCompressed(b *testing.B) {
456+
benchmark10kRows(b, true)
457+
}

0 commit comments

Comments
 (0)