Skip to content

Sweep: constructor sizing, hash-part keys, iterators, concat and resume - #50

Merged
folbricht merged 5 commits into
mainfrom
table-sweep
Oct 20, 2026
Merged

folbricht merged 5 commits into
mainfrom
table-sweep

Conversation

@folbricht

@folbricht folbricht commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Results from profiling every suite script, looking for costs outside the interpreter loop. Each change is a separate commit. fast.go is unchanged, and asmgate passes.

Commit What Effect
Constructor size hint {f(), g()} sized its array without the open call, so SETLIST always reallocated it. The hint now keeps a slot for the open list's first value; a call that returns nothing leaves a nil slot, which length and traversal already handle. binarytrees -25% allocations, -9.7%
quickSet constSet becomes quickSet. SETTABLE and SETTABLEK now also use it for string keys and for integer keys outside the array part, such as perm[0]. GETTABLE's slow path looks such integer keys up directly, as it already did for strings. A key one past the array still goes through set, which appends it to the array part. fannkuch -10.5%
Built-in iterators clear on 2–3 Values was a runtime call with a bulk write barrier, about 7% of pairs. ipairs now reads the array part directly. pairs -17% (C Lua: 16–19 ms)
table.concat Items of a table without a metatable come straight from the array part. concat -1.7%
resume The caller's state is saved into prev.waiting once and restored from there, instead of going through a local copy. coroutine -4.6% instructions

Fast-loop times on the suite (ms, minimum of 3 interleaved runs):

Script main branch
binarytrees 29.5 26.6 -9.7%
fannkuch 52.0 46.6 -10.5%
pairs 22.8 18.9 -17.1%
all 21, geomean -2.8%

json (-6.0%), oop (-7.5%) and sort (-5.2%) also came out faster, but none of these changes clearly explains it, so treat those numbers, and the geomean they lift, as noise until a rerun confirms them. The other scripts are within ±3%. That includes fib and floatloop, which run only in the unchanged loop; their instruction counts didn't change.

New corpus cases, with expected output from C Lua:

  • compile.lua: constructors whose open last item gives no values.
  • meta.lua: integer and string keys outside the array part, with and without __newindex, and appending past the end of the array.

{f(), g()} sized its array for the items before the open call, so the
SETLIST that stored g's results always reallocated it. The size hint now
keeps a slot for the open list's first value: one allocation per such
table instead of two. A call that returns nothing leaves a nil slot, which
length and traversal already handle. binarytrees: -25% allocations, -8.7%
time.
constSet becomes quickSet, which SETTABLE and SETTABLEK also use for a
string key or an integer key outside the array part, as t[0] in fannkuch.
GETTABLE's slow path looks integer keys outside the array part up in the
hash part directly, as it did string keys. fannkuch: -7.7% time.
…rray part directly

clear on a few Values is a runtime call with a bulk write barrier, about 7%
of the pairs script. pairs: -17% instructions, -19% time.
resume copied the caller's state into a local and then into prev.waiting;
it now saves it into prev.waiting once and restores it from there.
coroutine: -4.6% instructions, -2.3% time.
@folbricht
folbricht merged commit 80f93c7 into main Oct 20, 2026
17 checks passed
@folbricht
folbricht deleted the table-sweep branch October 20, 2026 15:43
folbricht added a commit that referenced this pull request Oct 21, 2026
Benchmarks: rerun on main with #50 to #53, glua at 1.13x C Lua
ebarkie pushed a commit to ebarkie/glua that referenced this pull request Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant