Experiment 015: Cell Buffer Union (48 → 16 bytes)

Date: 2026-04-07

Status: Accepted (simplicity win, performance neutral)

Commit:52f1e4b

Hypothesis

Shrinking resqlite_cell from 48 bytes to 16 bytes using a C union would improve cache locality for the per-row cell buffer, especially for wide schemas and large result sets.

Changes

Previous layout (48 bytes):

 typedef struct { int type;              // 4 bytes + 4 padding long long int_val;     // 8 bytes double double_val;     // 8 bytes const char* text_ptr;  // 8 bytes int text_len;          // 4 bytes + 4 padding const void* blob_ptr;  // 8 bytes } resqlite_cell; 

New layout (16 bytes):

 typedef struct { int type;        // 4 bytes int len;         // 4 bytes (text/blob length) union { long long i; // 8 bytes double d;    // 8 bytes const void* p; // 8 bytes (text/blob pointer) }; } resqlite_cell; 

The Dart side was also simplified — 3 offset constants instead of 7, and all value types read from the same union offset.

Results

Compared against writer-tuning baseline: 0 meaningful wins, 0 meaningful regressions. All benchmarks within noise.

The buffer size reduction doesn't show up because even with the old 48-byte layout, a 10-column × 1-row buffer is only 480 bytes — well within L1 cache. The benefit would appear at much larger working sets (50k+ rows × 20+ columns).

Decision

Accepted — not for performance (neutral), but for code quality: