129 lines
2.8 KiB
Go
129 lines
2.8 KiB
Go
|
|
package testing
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"b612.me/stardb"
|
||
|
|
_ "modernc.org/sqlite"
|
||
|
|
)
|
||
|
|
|
||
|
|
func setupBenchmarkDB(b *testing.B) *stardb.StarDB {
|
||
|
|
b.Helper()
|
||
|
|
|
||
|
|
db := &stardb.StarDB{}
|
||
|
|
if err := db.Open("sqlite", ":memory:"); err != nil {
|
||
|
|
b.Fatalf("Failed to open database: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
_, err := db.Exec(`
|
||
|
|
CREATE TABLE users (
|
||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
email TEXT NOT NULL,
|
||
|
|
age INTEGER,
|
||
|
|
balance REAL,
|
||
|
|
active BOOLEAN,
|
||
|
|
created_at DATETIME
|
||
|
|
)
|
||
|
|
`)
|
||
|
|
if err != nil {
|
||
|
|
b.Fatalf("Failed to create table: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
_, err = db.Exec(`
|
||
|
|
INSERT INTO users (name, email, age, balance, active, created_at) VALUES
|
||
|
|
('Alice', 'alice@example.com', 25, 100.50, 1, '2024-01-01 10:00:00'),
|
||
|
|
('Bob', 'bob@example.com', 30, 200.75, 1, '2024-01-02 11:00:00'),
|
||
|
|
('Charlie', 'charlie@example.com', 35, 300.25, 0, '2024-01-03 12:00:00')
|
||
|
|
`)
|
||
|
|
if err != nil {
|
||
|
|
b.Fatalf("Failed to insert seed data: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
return db
|
||
|
|
}
|
||
|
|
|
||
|
|
func BenchmarkQueryX(b *testing.B) {
|
||
|
|
db := setupBenchmarkDB(b)
|
||
|
|
defer db.Close()
|
||
|
|
|
||
|
|
target := User{Name: "Alice"}
|
||
|
|
b.ReportAllocs()
|
||
|
|
b.ResetTimer()
|
||
|
|
|
||
|
|
for i := 0; i < b.N; i++ {
|
||
|
|
rows, err := db.QueryX(&target, "SELECT * FROM users WHERE name = ?", ":name")
|
||
|
|
if err != nil {
|
||
|
|
b.Fatalf("QueryX failed: %v", err)
|
||
|
|
}
|
||
|
|
_ = rows.Close()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func BenchmarkOrm(b *testing.B) {
|
||
|
|
db := setupBenchmarkDB(b)
|
||
|
|
defer db.Close()
|
||
|
|
|
||
|
|
b.ReportAllocs()
|
||
|
|
b.ResetTimer()
|
||
|
|
|
||
|
|
for i := 0; i < b.N; i++ {
|
||
|
|
rows, err := db.Query("SELECT * FROM users ORDER BY name")
|
||
|
|
if err != nil {
|
||
|
|
b.Fatalf("Query failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var users []User
|
||
|
|
if err := rows.Orm(&users); err != nil {
|
||
|
|
_ = rows.Close()
|
||
|
|
b.Fatalf("Orm failed: %v", err)
|
||
|
|
}
|
||
|
|
_ = rows.Close()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func BenchmarkScanEach(b *testing.B) {
|
||
|
|
db := setupBenchmarkDB(b)
|
||
|
|
defer db.Close()
|
||
|
|
|
||
|
|
b.ReportAllocs()
|
||
|
|
b.ResetTimer()
|
||
|
|
|
||
|
|
for i := 0; i < b.N; i++ {
|
||
|
|
count := 0
|
||
|
|
err := db.ScanEach("SELECT * FROM users ORDER BY name", func(row *stardb.StarResult) error {
|
||
|
|
_ = row.MustString("name")
|
||
|
|
count++
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
b.Fatalf("ScanEach failed: %v", err)
|
||
|
|
}
|
||
|
|
if count != 3 {
|
||
|
|
b.Fatalf("Unexpected row count: %d", count)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func BenchmarkBatchInsert(b *testing.B) {
|
||
|
|
db := setupBenchmarkDB(b)
|
||
|
|
defer db.Close()
|
||
|
|
|
||
|
|
columns := []string{"name", "email", "age", "balance", "active", "created_at"}
|
||
|
|
b.ReportAllocs()
|
||
|
|
b.ResetTimer()
|
||
|
|
|
||
|
|
for i := 0; i < b.N; i++ {
|
||
|
|
base := i * 2
|
||
|
|
values := [][]interface{}{
|
||
|
|
{fmt.Sprintf("bench_user_%d", base), fmt.Sprintf("bench_%d@example.com", base), 20 + (base % 20), 99.5, true, time.Now()},
|
||
|
|
{fmt.Sprintf("bench_user_%d", base+1), fmt.Sprintf("bench_%d@example.com", base+1), 20 + ((base + 1) % 20), 199.5, false, time.Now()},
|
||
|
|
}
|
||
|
|
if _, err := db.BatchInsert("users", columns, values); err != nil {
|
||
|
|
b.Fatalf("BatchInsert failed: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|