Experiment 032: Row Map Facade Overrides

Date: 2026-04-09

Status: Accepted

Problem

resqlite's transport/result shape is strong: one shared RowSchema, one flat

values list, and lazy Row wrappers. But Row itself uses MapMixin, and

many of the default MapBase operations are intentionally skeletal rather than

optimal.

That means Row can be excellent at transport and still pay avoidable cost on

the main isolate for common Map-style operations like:

Hypothesis

Keep the transport shape exactly as-is, but override the hot Map members on

Row so they operate directly on the flat values list instead of going through

generic MapMixin behavior.

This should improve main-isolate row consumption without hurting the isolate

transfer story that makes ResultSet fast in the first place.

What We Built

In lib/src/row.dart:

Importantly:

Benchmark

Added targeted microbenchmark:

This compares resqliteRow against a LinkedHashMap built from the same row

data for the operations we care about.

Before

CaseRow median (ms)Map median (ms)Delta (ms)
hot lookup5.7325.299+0.433
containsKey16.2669.806+6.460
iterate keys + lookup12.60014.741-2.141
forEach15.2076.994+8.213
entries iteration15.1629.029+6.133
values iteration20.1464.931+15.215
Map.from clone7.2465.896+1.350

After

CaseRow median (ms)Map median (ms)Delta (ms)
hot lookup5.6835.189+0.494
containsKey11.5459.170+2.375
iterate keys + lookup12.35214.484-2.132
forEach6.6706.892-0.222
entries iteration8.0248.911-0.887
values iteration3.2334.943-1.710
Map.from clone5.2615.838-0.577

Result

This is a clear improvement.

The transport shape already seemed right. The problem really was the

main-isolate MapMixin facade.

What improved materially:

What did not change much:

Why Accepted

This keeps the best part of the current design โ€” the result transport shape โ€”

while making Row behave much more like a performant Map on the main

isolate.