-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbench_test.go
More file actions
98 lines (90 loc) · 2.41 KB
/
Copy pathbench_test.go
File metadata and controls
98 lines (90 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package sqlite
import (
"context"
"database/sql"
"errors"
"testing"
)
// BenchmarkAuthorizer_NoOp measures the per-statement overhead of installing
// a no-op authorizer compared to running the same statements with no
// authorizer attached. The authorizer is invoked for every parse/compile
// event (table reads, columns, pragmas, etc.) so the constant factor here
// scales with statement complexity, not row count.
//
// To compare:
//
// go test -run=^$ -bench=BenchmarkAuthorizer -benchmem -count=5
//
// The two sub-benchmarks share fixture setup so the only delta is the
// authorizer install.
func BenchmarkAuthorizer_NoOp(b *testing.B) {
db, err := sql.Open(DriverNameSQLite3, ":memory:")
if err != nil {
b.Fatal(err)
}
defer db.Close()
db.SetMaxOpenConns(1)
ctx := context.Background()
if _, err := db.ExecContext(ctx, `
CREATE TABLE t (id INTEGER PRIMARY KEY, a INTEGER, b INTEGER, c INTEGER);
INSERT INTO t (a, b, c) VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9);
`); err != nil {
b.Fatal(err)
}
// Pin the conn we install the authorizer on.
sc, err := db.Conn(ctx)
if err != nil {
b.Fatal(err)
}
defer sc.Close()
var c *Conn
if err := sc.Raw(func(dc any) error {
gc, ok := dc.(*Conn)
if !ok {
return errors.New("driver conn is not *sqlite.Conn")
}
c = gc
return nil
}); err != nil {
b.Fatal(err)
}
const query = `SELECT a, b, c FROM t WHERE a > ? AND b < ?`
// Reusable scan target so the benchmark doesn't measure allocator churn.
var av, bv, cv int
b.Run("WithoutAuthorizer", func(b *testing.B) {
c.RegisterAuthorizer(nil) // ensure clean baseline
b.ResetTimer()
for range b.N {
rows, err := sc.QueryContext(ctx, query, 0, 100)
if err != nil {
b.Fatal(err)
}
for rows.Next() {
if err := rows.Scan(&av, &bv, &cv); err != nil {
b.Fatal(err)
}
}
rows.Close()
}
})
b.Run("WithAuthorizer", func(b *testing.B) {
// No-op authorizer that allows everything. The point is to measure
// the trampoline + map-lookup cost on every authorize call, not the
// logic inside the callback.
c.RegisterAuthorizer(func(op int, a, b, dbName, trigger string) int { return SQLITE_OK })
defer c.RegisterAuthorizer(nil)
b.ResetTimer()
for range b.N {
rows, err := sc.QueryContext(ctx, query, 0, 100)
if err != nil {
b.Fatal(err)
}
for rows.Next() {
if err := rows.Scan(&av, &bv, &cv); err != nil {
b.Fatal(err)
}
}
rows.Close()
}
})
}