Benchmark Results

Last updated: 2026-03-01 | Deno 2.7.1

⚠️ Note: These benchmarks run in GitHub Actions CI (shared runners). Results show relative performance but may have high variability (CV% >20%). For research-grade measurements, run on dedicated hardware.

Performance Comparison

Comparing O(n) linear scan vs O(log n) R-tree across:

Key Question: When does O(log n) beat O(n)?

How to read: Lower time is better. "Relative" compares to RStarTree baseline:

Quick Comparison

Speed relative to RStarTree (lower is better):

Scenario lazypartitionedindex mortonlinearscan rstartree RStarTree
Sparse (n < 100) 0.2x 0.0x 0.1x 1.0x (baseline)
Large overlapping (n ≈ 1000) 156.1x 6.4x 16.0x 1.0x (baseline)
Large sequential (n ≈ 2500) 219.0x 21.1x 10.2x 1.0x (baseline)

Key insights:


Write-Heavy Workloads (Pure Inserts)

column-operations (n=20)

Implementation Time Relative
mortonlinearscan 0.00ms 0.00x
rstartree 0.02ms 0.02x
lazypartitionedindex 0.05ms 0.05x

diagonal-selection (n=30)

Implementation Time Relative
mortonlinearscan 0.02ms 0.02x
lazypartitionedindex 0.15ms 0.15x
rstartree 0.16ms 0.16x

large-grid (n=2500)

Implementation Time Relative
rstartree 10.70ms 10.70x
mortonlinearscan 18.50ms 18.50x
lazypartitionedindex 252.20ms 252.20x

large-overlapping (n=1250)

Implementation Time Relative
mortonlinearscan 6.40ms 6.40x
rstartree 16.00ms 16.00x
lazypartitionedindex 156.10ms 156.10x

large-ranges (n=500)

Implementation Time Relative
mortonlinearscan 1.60ms 1.60x
rstartree 5.20ms 5.20x
lazypartitionedindex 25.90ms 25.90x

large-sequential (n=2500)

Implementation Time Relative
rstartree 10.20ms 10.20x
mortonlinearscan 21.10ms 21.10x
lazypartitionedindex 219.00ms 219.00x

merge-like-blocks (n=15)

Implementation Time Relative
mortonlinearscan 0.00ms 0.00x
rstartree 0.01ms 0.01x
lazypartitionedindex 0.05ms 0.05x

row-operations (n=20)

Implementation Time Relative
mortonlinearscan 0.00ms 0.00x
rstartree 0.02ms 0.02x
lazypartitionedindex 0.05ms 0.05x

single-cell-edits (n=50)

Implementation Time Relative
mortonlinearscan 0.01ms 0.01x
rstartree 0.07ms 0.07x
lazypartitionedindex 0.19ms 0.19x

sparse-grid (n=60)

Implementation Time Relative
mortonlinearscan 0.02ms 0.02x
rstartree 0.10ms 0.10x
lazypartitionedindex 0.23ms 0.23x

sparse-large-ranges (n=30)

Implementation Time Relative
mortonlinearscan 0.01ms 0.01x
rstartree 0.04ms 0.04x
lazypartitionedindex 0.11ms 0.11x

sparse-overlapping (n=40)

Implementation Time Relative
mortonlinearscan 0.02ms 0.02x
lazypartitionedindex 0.30ms 0.30x
rstartree 0.33ms 0.33x

sparse-sequential (n=50)

Implementation Time Relative
mortonlinearscan 0.02ms 0.02x
rstartree 0.09ms 0.09x
lazypartitionedindex 0.16ms 0.16x

striping-alternating-rows (n=25)

Implementation Time Relative
mortonlinearscan 0.01ms 0.01x
rstartree 0.03ms 0.03x
lazypartitionedindex 0.10ms 0.10x

Read-Heavy Workloads (Frequent Queries)

column-operations (n=20) + 100 queries

Implementation Time Relative
mortonlinearscan 0.01ms 0.01x
rstartree 0.03ms 0.03x
lazypartitionedindex 0.06ms 0.06x

diagonal-selection (n=30) + 100 queries

Implementation Time Relative
mortonlinearscan 0.02ms 0.02x
lazypartitionedindex 0.16ms 0.16x
rstartree 0.17ms 0.17x

large-grid (n=2500) + 100 queries

Implementation Time Relative
rstartree 10.60ms 10.60x
mortonlinearscan 18.30ms 18.30x
lazypartitionedindex 247.50ms 247.50x

large-overlapping (n=1250) + 100 queries

Implementation Time Relative
mortonlinearscan 6.40ms 6.40x
rstartree 16.00ms 16.00x
lazypartitionedindex 155.00ms 155.00x

large-ranges (n=500) + 100 queries

Implementation Time Relative
mortonlinearscan 1.60ms 1.60x
rstartree 5.20ms 5.20x
lazypartitionedindex 25.70ms 25.70x

large-sequential (n=2500) + 100 queries

Implementation Time Relative
rstartree 10.10ms 10.10x
mortonlinearscan 21.20ms 21.20x
lazypartitionedindex 244.30ms 244.30x

merge-like-blocks (n=15) + 100 queries

Implementation Time Relative
mortonlinearscan 0.01ms 0.01x
rstartree 0.02ms 0.02x
lazypartitionedindex 0.06ms 0.06x

row-operations (n=20) + 100 queries

Implementation Time Relative
mortonlinearscan 0.01ms 0.01x
rstartree 0.03ms 0.03x
lazypartitionedindex 0.06ms 0.06x

single-cell-edits (n=50) + 100 queries

Implementation Time Relative
mortonlinearscan 0.02ms 0.02x
rstartree 0.08ms 0.08x
lazypartitionedindex 0.19ms 0.19x

sparse-grid (n=60) + 100 queries

Implementation Time Relative
mortonlinearscan 0.03ms 0.03x
rstartree 0.11ms 0.11x
lazypartitionedindex 0.24ms 0.24x

sparse-large-ranges (n=30) + 100 queries

Implementation Time Relative
mortonlinearscan 0.01ms 0.01x
rstartree 0.05ms 0.05x
lazypartitionedindex 0.12ms 0.12x

sparse-overlapping (n=40) + 100 queries

Implementation Time Relative
mortonlinearscan 0.03ms 0.03x
lazypartitionedindex 0.32ms 0.32x
rstartree 0.33ms 0.33x

sparse-sequential (n=50) + 100 queries

Implementation Time Relative
mortonlinearscan 0.02ms 0.02x
rstartree 0.10ms 0.10x
lazypartitionedindex 0.18ms 0.18x

striping-alternating-rows (n=25) + 100 queries

Implementation Time Relative
mortonlinearscan 0.01ms 0.01x
rstartree 0.04ms 0.04x
lazypartitionedindex 0.11ms 0.11x

Mixed Workloads (80% Write / 20% Read)

large-overlapping (n=500) 80/20

Implementation Time Relative
mortonlinearscan 1.20ms 1.20x
rstartree 5.50ms 5.50x
lazypartitionedindex 21.00ms 21.00x

large-sequential (n=1000) 80/20

Implementation Time Relative
rstartree 3.70ms 3.70x
mortonlinearscan 3.80ms 3.80x
lazypartitionedindex 30.70ms 30.70x

sparse-overlapping (n=40) 80/20

Implementation Time Relative
mortonlinearscan 0.03ms 0.03x
lazypartitionedindex 0.32ms 0.32x
rstartree 0.33ms 0.33x

sparse-sequential (n=50) 80/20

Implementation Time Relative
mortonlinearscan 0.02ms 0.02x
rstartree 0.10ms 0.10x
lazypartitionedindex 0.18ms 0.18x

Query-Only Benchmarks (Construction Not Measured)

large (n=5000, 10k queries)

Implementation Time Relative
rstartree 70.30ms 70.30x
mortonlinearscan 324.10ms 324.10x

overlapping (n=1000, 10k queries)

Implementation Time Relative
mortonlinearscan 5.60ms 5.60x
rstartree 24.50ms 24.50x
lazypartitionedindex 65.90ms 65.90x

sequential (n=1000, 10k queries)

Implementation Time Relative
mortonlinearscan 4.00ms 4.00x
rstartree 4.40ms 4.40x
lazypartitionedindex 32.20ms 32.20x

Summary

What do these numbers actually mean?

These benchmarks compare O(n) linear scan vs O(log n) R-tree for different data sizes and workload patterns.

Sparse data (n < 100): Typical for individual spreadsheet properties (backgrounds, borders, etc.) Large data (n > 1000): Consolidated or heavy usage scenarios

RStarTree is the baseline (1.0x) - numbers > 1.0x are slower, < 1.0x are faster.

lazypartitionedindex (2.1KB minified):

mortonlinearscan (2.4KB minified):

rstartree (6.1KB minified):

System: linux x86_64 Run: deno task bench:update to regenerate