Skip to content

Instantly share code, notes, and snippets.

@markuswustenberg
Created December 8, 2022 18:42
Show Gist options
  • Save markuswustenberg/f35ab7e191137dca5f7ec112bfc887be to your computer and use it in GitHub Desktop.
Save markuswustenberg/f35ab7e191137dca5f7ec112bfc887be to your computer and use it in GitHub Desktop.
Go SQLite benchmark parallel
module sqlite
go 1.19
require github.com/mattn/go-sqlite3 v1.14.16
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
.PHONY: benchmark
benchmark:
go test -bench=.
package sqlite
import (
"database/sql"
"sync"
)
func Setup(db *sql.DB) error {
_, err := db.Exec(`
create table posts (
id integer primary key,
title text not null,
content text not null,
created text not null default (strftime('%Y-%m-%dT%H:%M:%fZ'))
)`)
return err
}
func WriteBlogPost(db *sql.DB, title, content string) error {
_, err := db.Exec(`insert into posts (title, content) values (?, ?)`, title, content)
return err
}
var m sync.Mutex
func WriteBlogPostMutexed(db *sql.DB, title, content string) error {
m.Lock()
defer m.Unlock()
_, err := db.Exec(`insert into posts (title, content) values (?, ?)`, title, content)
return err
}
package sqlite_test
import (
"database/sql"
"path"
"testing"
_ "github.com/mattn/go-sqlite3"
"sqlite"
)
func BenchmarkWriteBlogPost(b *testing.B) {
b.Run("write blog post without WAL", func(b *testing.B) {
db := setupDB(b, "?_timeout=5000&_fk=true")
b.SetParallelism(64)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if err := sqlite.WriteBlogPost(db, "Some title", "Some content"); err != nil {
b.Fatal(err)
}
}
})
})
b.Run("write blog post with WAL", func(b *testing.B) {
db := setupDB(b, "?_journal=WAL&_timeout=5000&_fk=true")
b.SetParallelism(64)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if err := sqlite.WriteBlogPost(db, "Some title", "Some content"); err != nil {
b.Fatal(err)
}
}
})
})
b.Run("write blog post with WAL and Go mutex", func(b *testing.B) {
db := setupDB(b, "?_journal=WAL&_timeout=5000&_fk=true")
b.SetParallelism(64)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if err := sqlite.WriteBlogPostMutexed(db, "Some title", "Some content"); err != nil {
b.Fatal(err)
}
}
})
})
}
func setupDB(b *testing.B, options string) *sql.DB {
dbPath := path.Join(b.TempDir(), "benchmark.db")
db, err := sql.Open("sqlite3", dbPath+options)
if err != nil {
b.Fatal(err)
}
if err := sqlite.Setup(db); err != nil {
b.Fatal(err)
}
return db
}
@komuw
Copy link

komuw commented Dec 12, 2022

Ben Johnson suggested .. to try different drivers as well,

I tried that at; https://gist.github.com/komuw/7fe652eece1850d2148e2bf3392101b0
I specifically tried with mattn/go-sqlite3 and modernc.org/sqlite. Unfortunately modernc.org/sqlite had too many database is locked errors.
I need to try out tailscale/sqlite. Their interface is a bit different from the other drivers so I might need to re-arrange the code.

edit: I have now included tailscale/sqlite in my gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment