luau-lang / luau

A fast, small, safe, gradually typed embeddable scripting language derived from Lua
https://luau-lang.org
MIT License
3.8k stars 352 forks source link

Make table.concat faster #1243

Closed zeux closed 2 months ago

zeux commented 2 months ago

table.concat is idiomatic and should be the fastest way to concatenate all table array elements together, but apparently you can beat it by using string.format, string.rep and table.unpack:

string.format(string.rep("%*", #t), table.unpack(t))

... this just won't do, so we should fix table.concat performance.

The deficit comes from two places:

This change fixes this by using a fast path for in-bounds array lookup for a string. Note that table.concat also supports numbers (these need to be converted to strings which is a little cumbersome and has innate overhead), and out-of-bounds accesses*. In these cases we fall back to the old implementation.

To trigger out-of-bounds accesses, you need to skip the past-array-end element (which is nil per array invariant), but this is achievable because table.concat supports offset+length arguments. This should almost never come up in practice but the per-element branches et al are fairly cheap compared to the eventual string copy/alloc anyway.

This change makes table.concat ~2x faster when the separator is empty; the table.concat benchmark shows +40% gains but it uses a variety of string separators of different lengths so it doesn't get the full benefit from this change.