spike

package
v0.1.30 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package GO-SQLDB is a deliberately minimal spike to validate the central thesis of the GO-SQLDB design: that an in-memory Go store with a canonical WAL can beat SQLite-in-memory on the hot OLTP path.

The spike implements ONE hardcoded table:

users(id TEXT PK, email TEXT, name TEXT)

The implementations are as simple as possible, but the types are the same types the full v1 design will use: RowID, RowRef, RowHead, Mutation, canonical WAL records. That way, adding partitions, ordered indexes, or checkpoints later does not require rewriting the existing code.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DB

type DB struct {
	// contains filtered or unexported fields
}

func Open

func Open(walPath string, syncWAL bool) (*DB, error)

Open creates or recovers a DB. If walPath exists, it is fully replayed.

func OpenMemory

func OpenMemory(sizeHint int) *DB

OpenMemory creates a memory-only DB with no WAL. Used to measure the ceiling of the in-process map+index path without any disk I/O. NOT durable — process exit loses all data. Useful for cache/scratch workloads where the source of truth lives elsewhere.

func OpenWithSize

func OpenWithSize(walPath string, syncWAL bool, sizeHint int) (*DB, error)

OpenWithSize is Open with an estimated row-count hint. The hint pre-sizes the in-memory maps so the hot Insert path doesn't pay for repeated bucket-grow allocations. Pass 0 for "no hint" (matches Open).

func (*DB) Close

func (db *DB) Close() error

func (*DB) Delete

func (db *DB) Delete(id string) error

func (*DB) Get

func (db *DB) Get(id string) (User, bool, error)

func (*DB) Insert

func (db *DB) Insert(u User) (RowRef, error)

func (*DB) InsertBatch

func (db *DB) InsertBatch(users []User) error

InsertBatch inserts a slice of users under a single db.mu hold and (when WAL is on) a single wal.mu hold around the bufio writes. Reduces per-call lock/unlock and function-call overhead vs N separate Inserts. Returns the first error encountered; any prior successful inserts in the batch are NOT rolled back.

func (*DB) Stats

func (db *DB) Stats() (rows, liveIndex int)

Stats returns rough counts for sanity checks in benchmarks.

func (*DB) UnsafeGet

func (db *DB) UnsafeGet(id string) (User, bool)

UnsafeGet skips db.mu entirely. Only valid if the caller GUARANTEES no concurrent writes (frozen dataset, read-only phase). Used to measure the lock-free ceiling of the Get path. NOT for production use.

func (*DB) Update

func (db *DB) Update(u User) error

type DBL3a

type DBL3a struct {
	// contains filtered or unexported fields
}

func OpenL3a

func OpenL3a(sizeHint int) *DBL3a

func (*DBL3a) Close

func (db *DBL3a) Close() error

func (*DBL3a) Get

func (db *DBL3a) Get(id string) (User, bool)

func (*DBL3a) Insert

func (db *DBL3a) Insert(u User) error

type DBL3b

type DBL3b struct {
	// contains filtered or unexported fields
}

func OpenL3b

func OpenL3b(sizeHint int) *DBL3b

func (*DBL3b) Close

func (db *DBL3b) Close() error

func (*DBL3b) Get

func (db *DBL3b) Get(id string) (User, bool)

func (*DBL3b) Insert

func (db *DBL3b) Insert(u User) error

type DBL3c

type DBL3c struct {
	// contains filtered or unexported fields
}

func OpenL3c

func OpenL3c(sizeHint int) *DBL3c

func (*DBL3c) Close

func (db *DBL3c) Close() error

func (*DBL3c) Get

func (db *DBL3c) Get(id string) (User, bool)

func (*DBL3c) Insert

func (db *DBL3c) Insert(u User) error

type DBL3e

type DBL3e struct {
	// contains filtered or unexported fields
}

func OpenL3e

func OpenL3e(sizeHint int) *DBL3e

func (*DBL3e) Close

func (db *DBL3e) Close() error

func (*DBL3e) Get

func (db *DBL3e) Get(id string) (User, bool)

func (*DBL3e) Insert

func (db *DBL3e) Insert(u User) error

func (*DBL3e) InsertBulk

func (db *DBL3e) InsertBulk(users []User) error

InsertBulk avoids the O(N) copy per insert by building the snapshot once. Use for setup/bench warmup where N inserts would otherwise be O(N^2). The snapshot is replaced atomically at the end.

type DBL3f

type DBL3f struct {
	// contains filtered or unexported fields
}

func OpenL3f

func OpenL3f(sizeHint int) *DBL3f

func (*DBL3f) Close

func (db *DBL3f) Close() error

func (*DBL3f) Get

func (db *DBL3f) Get(id string) (User, bool)

func (*DBL3f) Insert

func (db *DBL3f) Insert(u User) error

type Message

type Message struct {
	ID       UUIDv7
	ThreadID [16]byte
	Seq      int64
	Body     string
}

type MessagesDB

type MessagesDB struct {
	// contains filtered or unexported fields
}

func OpenMessagesDB

func OpenMessagesDB(sizeHint int) *MessagesDB

OpenMessagesDB — memory-only (no WAL).

func OpenMessagesDBWAL

func OpenMessagesDBWAL(walPath string, sizeHint int) (*MessagesDB, error)

OpenMessagesDBWAL — WAL-backed for the mixed workload test.

func (*MessagesDB) Close

func (db *MessagesDB) Close() error

func (*MessagesDB) FlushWAL

func (db *MessagesDB) FlushWAL() error

FlushWAL forces a bufio flush. Used by mixed-workload tests to bound durability windows during the bench.

func (*MessagesDB) GetByID

func (db *MessagesDB) GetByID(id UUIDv7, threadID [16]byte) (Message, bool)

GetByID — point lookup. Uses pk index, no ordered traversal.

func (*MessagesDB) Insert

func (db *MessagesDB) Insert(m Message) error

func (*MessagesDB) LastN

func (db *MessagesDB) LastN(threadID [16]byte, n int, dst []Message) []Message

LastN — the thesis query. Returns the last N messages of a thread in descending seq order. Single-shard read since we sharded by thread_id.

func (*MessagesDB) LastNSince

func (db *MessagesDB) LastNSince(threadID [16]byte, minSeq int64, limit int, dst []Message) []Message

LastNSince — variant: last N messages with seq > minSeq. Used to validate the index-driven range scan (vs full scan + filter).

type PartitionID

type PartitionID uint16

type RowHead

type RowHead struct {
	Row     User
	Deleted bool
}

RowHead is the indirection between RowID and the current row. V4 variant: stores the decoded User struct directly (no encoded bytes retained). Get becomes a pure struct copy with no decodeUser call. Encoded bytes are still produced on the Insert/Update path for the WAL write, but discarded after the WAL append returns.

type RowID

type RowID uint64

type RowRef

type RowRef struct {
	Table     TableID
	Partition PartitionID
	Row       RowID
}

RowRef is the stable logical row identity used across partitions and (later) global indexes. In the spike there is only one table and one partition, but every API still produces RowRefs so that adding partitions later does not change the index contracts.

type TableID

type TableID uint32

type UUIDv7

type UUIDv7 [16]byte

func NewUUIDv7

func NewUUIDv7() UUIDv7

type User

type User struct {
	ID    string
	Email string
	Name  string
}

User is the public Go shape. The spike has a hardcoded schema, so we use a struct directly instead of a generic column model. The codec is still schema-driven: every encoded row starts with a layout version and a null bitmap, exactly like the v1 EncodedRow.

type UserV2

type UserV2 struct {
	ID     UUIDv7
	Email  string
	Name   string
	Active bool
}

type UsersDB

type UsersDB struct {
	// contains filtered or unexported fields
}

func OpenUsersDB

func OpenUsersDB(sizeHint int) *UsersDB

func (*UsersDB) Close

func (db *UsersDB) Close() error

func (*UsersDB) GetByID

func (db *UsersDB) GetByID(id string) (User, bool)

GetByID — the compiled equivalent of "PREPARE get_user_by_id AS SELECT id,email,name FROM users WHERE id = ?". No parser, no plan, just the typed accessor.

func (*UsersDB) Insert

func (db *UsersDB) Insert(u User) error

type V1DB

type V1DB struct {
	// contains filtered or unexported fields
}

func OpenV1

func OpenV1(walPath string, sizeHint int) (*V1DB, error)

OpenV1 — durable WAL-backed.

func OpenV1Memory

func OpenV1Memory(sizeHint int) *V1DB

OpenV1Memory — no WAL, ceiling measurement.

func (*V1DB) Close

func (db *V1DB) Close() error

func (*V1DB) GetByID

func (db *V1DB) GetByID(id string) (User, bool)

func (*V1DB) Insert

func (db *V1DB) Insert(u User) error

Insert — typed in-memory, then WAL framing under walMu.

Order: WAL FIRST so that on crash mid-Insert the in-memory state reflects only what's durable. Spike order was the opposite; v1 gets it right.

func (*V1DB) InsertBatch

func (db *V1DB) InsertBatch(users []User) error

InsertBatch — N inserts under N shard-locks (one per shard's batch). More throughput than per-record Insert because WAL framing is amortised under a single walMu hold.

type V2DB

type V2DB struct {
	// contains filtered or unexported fields
}

func OpenV2

func OpenV2(sizeHint int) *V2DB

func (*V2DB) Close

func (db *V2DB) Close() error

func (*V2DB) GetByID

func (db *V2DB) GetByID(id UUIDv7) (UserV2, bool)

func (*V2DB) Insert

func (db *V2DB) Insert(u UserV2) error

type V3DB

type V3DB struct {
	// contains filtered or unexported fields
}

func OpenV3

func OpenV3(sizeHint int) *V3DB

func (*V3DB) BulkInsert

func (db *V3DB) BulkInsert(users []UserV2) error

BulkInsert — bypasses the drainer for warm-loads. Acquires shard mutexes, builds one new snapshot per shard with all rows inserted, atomic-stores. Avoids the O(N^2) cost of N sequential InsertSync.

func (*V3DB) Close

func (db *V3DB) Close() error

func (*V3DB) GetByID

func (db *V3DB) GetByID(id UUIDv7) (UserV2, bool)

GetByID — fully lock-free. Atomic load + map lookup.

func (*V3DB) Insert

func (db *V3DB) Insert(u UserV2) error

Insert — async. Returns when the write is enqueued, not when committed. For read-your-writes consistency, use InsertSync.

func (*V3DB) InsertSync

func (db *V3DB) InsertSync(u UserV2) error

InsertSync — blocks until the write has been applied to a snapshot.

type V4DB

type V4DB struct {
	// contains filtered or unexported fields
}

func OpenV4

func OpenV4(sizeHint int) *V4DB

func (*V4DB) BulkInsert

func (db *V4DB) BulkInsert(users []UserV2, ids []string) error

func (*V4DB) Close

func (db *V4DB) Close() error

func (*V4DB) GetByID

func (db *V4DB) GetByID(id string) (UserV2, bool)

func (*V4DB) Insert

func (db *V4DB) Insert(u UserV2, idStr string) error

type V5DB

type V5DB struct {
	// contains filtered or unexported fields
}

V5DB is generic over shard count via a runtime-sized slice. Compile- time constant would be ideal but Go doesn't let us parametrize struct fields by const easily. Runtime cost: one extra index op per shardOf, negligible.

func OpenV5

func OpenV5(numShards, sizeHint int) *V5DB

OpenV5 — shards must be a power of two.

func (*V5DB) Close

func (db *V5DB) Close() error

func (*V5DB) GetByID

func (db *V5DB) GetByID(id string) (UserV2, bool)

func (*V5DB) Insert

func (db *V5DB) Insert(u UserV2, id string) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL