Benchmarks
These numbers come from a reproducible go test -bench harness that lives
in benchmarks/
in the repository. It measures Quark's per-operation overhead against a
hand-written database/sql baseline and against GORM, on the same model,
schema, data, and operations.
The harness runs against in-memory SQLite so it isolates ORM and driver CPU/allocation overhead, not disk or network I/O. Against a networked database, that overhead is a small fraction of round-trip latency — do not read these microseconds as production request times. Numbers are also machine- and run-specific: treat the relative ratios as the signal and reproduce locally before drawing conclusions.
What is measured
Five operations, chosen because they exercise the reflect-based hot paths (row scanning, insert/update building) that Quark's planned code generation will replace:
| Benchmark | Operation |
|---|---|
InsertOne | Insert a single row |
InsertBatch | Insert 100 rows in one batch |
FindByPK | Select one row by primary key |
ListWhere | Select up to 50 rows with a WHERE age >= ? filter |
Update | Update one row (all non-PK columns) by primary key |
Each is implemented three ways against the same bench_users table:
hand-written database/sql (the floor), Quark's quark.For[T] API, and
GORM (the reflect-ORM peer).
How to reproduce
cd benchmarks
go test -run=^$ -bench=. -benchmem ./...
See the harness README for the full methodology, its limits, and how to add another ORM.
A representative run
Apple M4 Pro, macOS, go1.26.0 toolchain, modernc.org/sqlite v1.23.1,
gorm.io/gorm v1.31.0, in-memory SQLite. One -bench=. -benchmem run:
| Operation | Raw ns/op | Quark ns/op | GORM ns/op | Raw allocs | Quark allocs | GORM allocs |
|---|---|---|---|---|---|---|
| InsertOne | 6,038 | 12,293 | 21,212 | 20 | 62 | 78 |
| InsertBatch | 170,776 | 258,973 | 270,601 | 622 | 1,277 | 1,287 |
| FindByPK | 7,311 | 15,541 | 11,002 | 24 | 65 | 66 |
| ListWhere(50) | 38,604 | 71,172 | 50,134 | 365 | 474 | 705 |
| Update | 3,059 | 4,963 | 9,132 | 15 | 62 | 84 |
Reading the numbers
- Quark's reflect path runs about 1.5–2.1× the hand-written
database/sqlfloor on these operations. That gap is the overhead the planned generated path is meant to recover — and it bounds it, since generated code cannot beat hand-written SQL. - Quark and GORM are in the same performance class. Neither dominates: in this run Quark is faster on inserts and updates, GORM is faster on the single-row read and the filtered list.
- The reflection cache means model metadata is parsed once per type and reused; the remaining per-row cost is field-level reflection on scan and bind, which is what generated code removes.
Quark is not yet a v1.0 release and these results are not a claim of fastest-in-class. They exist to give an honest baseline that the code generation work will be measured against.