1 // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
3 // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this file,
7 // You can obtain one at http://mozilla.org/MPL/2.0/.
28 func (tb *TB) check(err error) {
34 func (tb *TB) checkDB(db *sql.DB, err error) *sql.DB {
39 func (tb *TB) checkRows(rows *sql.Rows, err error) *sql.Rows {
44 func (tb *TB) checkStmt(stmt *sql.Stmt, err error) *sql.Stmt {
49 func initDB(b *testing.B, queries ...string) *sql.DB {
51 db := tb.checkDB(sql.Open("mysql", dsn))
52 for _, query := range queries {
53 if _, err := db.Exec(query); err != nil {
54 b.Fatalf("error on %q: %v", query, err)
60 const concurrencyLevel = 10
62 func BenchmarkQuery(b *testing.B) {
67 "DROP TABLE IF EXISTS foo",
68 "CREATE TABLE foo (id INT PRIMARY KEY, val CHAR(50))",
69 `INSERT INTO foo VALUES (1, "one")`,
70 `INSERT INTO foo VALUES (2, "two")`,
72 db.SetMaxIdleConns(concurrencyLevel)
75 stmt := tb.checkStmt(db.Prepare("SELECT val FROM foo WHERE id=?"))
80 wg.Add(concurrencyLevel)
84 for i := 0; i < concurrencyLevel; i++ {
87 if atomic.AddInt64(&remain, -1) < 0 {
93 tb.check(stmt.QueryRow(1).Scan(&got))
95 b.Errorf("query = %q; want one", got)
104 func BenchmarkExec(b *testing.B) {
108 db := tb.checkDB(sql.Open("mysql", dsn))
109 db.SetMaxIdleConns(concurrencyLevel)
112 stmt := tb.checkStmt(db.Prepare("DO 1"))
116 var wg sync.WaitGroup
117 wg.Add(concurrencyLevel)
121 for i := 0; i < concurrencyLevel; i++ {
124 if atomic.AddInt64(&remain, -1) < 0 {
129 if _, err := stmt.Exec(); err != nil {
137 // data, but no db writes
138 var roundtripSample []byte
140 func initRoundtripBenchmarks() ([]byte, int, int) {
141 if roundtripSample == nil {
142 roundtripSample = []byte(strings.Repeat("0123456789abcdef", 1024*1024))
144 return roundtripSample, 16, len(roundtripSample)
147 func BenchmarkRoundtripTxt(b *testing.B) {
149 sample, min, max := initRoundtripBenchmarks()
150 sampleString := string(sample)
153 db := tb.checkDB(sql.Open("mysql", dsn))
157 for i := 0; i < b.N; i++ {
162 test := sampleString[0:length]
163 rows := tb.checkRows(db.Query(`SELECT "` + test + `"`))
168 err := rows.Scan(&result)
181 func BenchmarkRoundtripBin(b *testing.B) {
183 sample, min, max := initRoundtripBenchmarks()
186 db := tb.checkDB(sql.Open("mysql", dsn))
188 stmt := tb.checkStmt(db.Prepare("SELECT ?"))
191 var result sql.RawBytes
192 for i := 0; i < b.N; i++ {
197 test := sample[0:length]
198 rows := tb.checkRows(stmt.Query(test))
203 err := rows.Scan(&result)
208 if !bytes.Equal(result, test) {
216 func BenchmarkInterpolation(b *testing.B) {
219 InterpolateParams: true,
222 maxAllowedPacket: maxPacketSize,
223 maxWriteSize: maxPacketSize - 1,
227 args := []driver.Value{
231 time.Unix(1423411542, 807015000),
232 []byte("bytes containing special chars ' \" \a \x00"),
233 "string containing special chars ' \" \a \x00",
235 q := "SELECT ?, ?, ?, ?, ?, ?"
239 for i := 0; i < b.N; i++ {
240 _, err := mc.interpolateParams(q, args)
247 func benchmarkQueryContext(b *testing.B, db *sql.DB, p int) {
248 ctx, cancel := context.WithCancel(context.Background())
250 db.SetMaxIdleConns(p * runtime.GOMAXPROCS(0))
253 stmt := tb.checkStmt(db.PrepareContext(ctx, "SELECT val FROM foo WHERE id=?"))
259 b.RunParallel(func(pb *testing.PB) {
262 tb.check(stmt.QueryRow(1).Scan(&got))
264 b.Fatalf("query = %q; want one", got)
270 func BenchmarkQueryContext(b *testing.B) {
272 "DROP TABLE IF EXISTS foo",
273 "CREATE TABLE foo (id INT PRIMARY KEY, val CHAR(50))",
274 `INSERT INTO foo VALUES (1, "one")`,
275 `INSERT INTO foo VALUES (2, "two")`,
278 for _, p := range []int{1, 2, 3, 4} {
279 b.Run(fmt.Sprintf("%d", p), func(b *testing.B) {
280 benchmarkQueryContext(b, db, p)
285 func benchmarkExecContext(b *testing.B, db *sql.DB, p int) {
286 ctx, cancel := context.WithCancel(context.Background())
288 db.SetMaxIdleConns(p * runtime.GOMAXPROCS(0))
291 stmt := tb.checkStmt(db.PrepareContext(ctx, "DO 1"))
297 b.RunParallel(func(pb *testing.PB) {
299 if _, err := stmt.ExecContext(ctx); err != nil {
306 func BenchmarkExecContext(b *testing.B) {
308 "DROP TABLE IF EXISTS foo",
309 "CREATE TABLE foo (id INT PRIMARY KEY, val CHAR(50))",
310 `INSERT INTO foo VALUES (1, "one")`,
311 `INSERT INTO foo VALUES (2, "two")`,
314 for _, p := range []int{1, 2, 3, 4} {
315 b.Run(fmt.Sprintf("%d", p), func(b *testing.B) {
316 benchmarkQueryContext(b, db, p)