Skip to content

Instantly share code, notes, and snippets.

@benweint
Created December 12, 2023 06:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benweint/a73c073a0d101627450a8cbccaa9f4b0 to your computer and use it in GitHub Desktop.
Save benweint/a73c073a0d101627450a8cbccaa9f4b0 to your computer and use it in GitHub Desktop.
Go maps vs. SQLite for very simple ops
module github.com/benweint/sqlite-demo
go 1.20
require github.com/mattn/go-sqlite3 v1.14.18 // indirect
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
package main
import (
"fmt"
"log"
"testing"
"math/rand"
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
// This benchmark demonstrates the performance difference between an in-process
// Go map with no synchronization and an in-memory SQLite database for the very
// simple use case of storing short strings under short string keys.
const tableSize = 10000
var result string
func generateKeyValuePair(i int) (string, string) {
key := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
return key, value
}
func getRandomKey() string {
return fmt.Sprintf("key%d", rand.Intn(tableSize))
}
// BenchmarkMap inserts tableSize key/value pairs into a Go map[string]string,
// then looks up random entries from the map b.N times.
func BenchmarkMap(b *testing.B) {
m := map[string]string{}
for i := 0; i < tableSize; i++ {
key, val := generateKeyValuePair(i)
m[key] = val
}
b.ResetTimer()
var val string
for i := 0; i < b.N; i++ {
key := getRandomKey()
var ok bool
val, ok = m[key]
if !ok {
log.Fatal(fmt.Sprintf("not found: %s", key))
}
}
result = val
}
// BenchmarkSqlite inserts tableSize key/value pairs into an in-memory SQLite DB table
// with a TEXT PRIMARY KEY column plus a TEXT value column, then looks up random
// entries from the table b.N times using a prepared statement.
func BenchmarkSqlite(b *testing.B) {
db, err := sql.Open("sqlite3", ":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS t (id TEXT PRIMARY KEY, value TEXT)`)
if err != nil {
log.Fatal(err)
}
for i := 0; i < tableSize; i++ {
id := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
_, err := db.Exec("INSERT INTO t (id, value) VALUES (?, ?)", id, value)
if err != nil {
log.Fatal(err)
}
}
stmt, err := db.Prepare("SELECT value FROM t WHERE id=?")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
b.ResetTimer()
var val string
for i := 0; i < b.N; i++ {
err = stmt.QueryRow(getRandomKey()).Scan(&val)
if err != nil {
log.Fatal(err)
}
}
result = val
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment