InfArray Benchmarks
Benchmarks comparing InfArray against a Luau table on the
same workloads. Every workload stays under Luau's 2^26 per-table limit so the
regular table is a fair baseline. These measure the overhead InfArray's
chunking adds, not the cases where a table simply can't compete (i.e. once you
cross 2^26 elements, the table stops being an option at all).
This page mirrors
benchmark/README.md. The results table is regenerated bylute run benchmark/run.luau --md.
Running
From the repo root, with Lute on your PATH:
# Print results to the console
lute run benchmark/run.luau
# Re-run and rewrite the results table in this file
lute run benchmark/run.luau --md
# Only the benchmarks whose title matches a substring
lute run benchmark/run.luau --filter get
# Trade speed for accuracy (more timed samples)
lute run benchmark/run.luau --samples 10
# Quick pass at 10% of each workload size
lute run benchmark/run.luau --scale 0.1
Adding a benchmark
- Copy an existing file in
cases/tocases/yourcase.bench.luau. - Fill in
title,n, and thevariants. - Add a
require("./cases/yourcase.bench")line to theSPECSlist inrun.luau.
Interpreting the numbers
InfArray will always be slower per element than a native table. It does index
math and an extra chunk lookup on every access. The point of the library is
capacity, not speed. It holds more than 2^26 elements, which a single Luau
table cannot. Use these benchmarks to keep that per-element overhead in check as
the implementation changes, not to "beat" the table.
Results
CPU: AMD Ryzen 9 9950X 16-Core Processor
OS: Windows_NT (x86_64)
Date: 2026-06-23 11:49
PushBack - append N elements
Workload size: n = 4_194_304
| Implementation | Time/op | Total | Throughput | vs baseline |
|---|---|---|---|---|
| InfArray | 48.6 ns | 203.96 ms | 20.56 M/s | 6.05× slower |
| Luau table | 8.0 ns | 33.71 ms | 124.44 M/s | 1.00× (baseline) |
Set - overwrite N in-range elements
Workload size: n = 4_194_304
| Implementation | Time/op | Total | Throughput | vs baseline |
|---|---|---|---|---|
| InfArray | 31.4 ns | 131.65 ms | 31.86 M/s | 9.72× slower |
| Luau table | 3.2 ns | 13.54 ms | 309.67 M/s | 1.00× (baseline) |
Get - sequential read of N elements
Workload size: n = 4_194_304
InfArray uses the hoisted free function
local Get = InfArray.Get.
| Implementation | Time/op | Total | Throughput | vs baseline |
|---|---|---|---|---|
| InfArray | 26.7 ns | 111.92 ms | 37.48 M/s | 8.33× slower |
| Luau table | 3.2 ns | 13.44 ms | 312.15 M/s | 1.00× (baseline) |
Get - random-access read of N elements
Workload size: n = 4_194_304
| Implementation | Time/op | Total | Throughput | vs baseline |
|---|---|---|---|---|
| InfArray | 104.4 ns | 437.80 ms | 9.58 M/s | 2.85× slower |
| Luau table | 36.7 ns | 153.76 ms | 27.28 M/s | 1.00× (baseline) |
Iterate - visit every present element
Workload size: n = 4_194_304
Iteratepays a callback per element
| Implementation | Time/op | Total | Throughput | vs baseline |
|---|---|---|---|---|
| InfArray | 13.7 ns | 57.65 ms | 72.75 M/s | 5.23× slower |
| Luau table | 2.6 ns | 11.02 ms | 380.59 M/s | 1.00× (baseline) |
for index, value in arr via __iter
Workload size: n = 4_194_304
__iter pays a closure call per element
| Implementation | Time/op | Total | Throughput | vs baseline |
|---|---|---|---|---|
| InfArray | 28.7 ns | 120.31 ms | 34.86 M/s | 11.29× slower |
| Luau table | 2.5 ns | 10.66 ms | 393.51 M/s | 1.00× (baseline) |
Find - linear search with needle at the end
Workload size: n = 4_194_304
| Implementation | Time/op | Total | Throughput | vs baseline |
|---|---|---|---|---|
| InfArray | 3.9 ns | 16.17 ms | 259.44 M/s | 2.07× slower |
| Luau table | 1.9 ns | 7.83 ms | 535.97 M/s | 1.00× (baseline) |
Results above are regenerated by
lute run benchmark/run.luau --md. They are machine-specific. Treat them as relative ratios.