Optimize string.split - #2981
Conversation
vrn-sn
left a comment
There was a problem hiding this comment.
Looks good, thanks! Could you please flag your changes (explained in this file)?
I think this is a good use case for LUAU_DYNAMIC_FASTFLAGVARIABLE, which will let us dynamically enable/disable the flag if there does turn out to be a bug. We try to ensure the "flag off" branch is identical to the original code, even if this means there will be quite a bit of duplicated logic in str_split.
|
To keep it simple, I would probably just do something like this: size_t haystackLen;
const char* haystack = luaL_checklstring(L, 1, &haystackLen);
size_t needleLen;
const char* needle = luaL_optlstring(L, 2, ",", &needleLen);
if (DFFlag::YourStringSplitFlagName)
{
// your new logic
}
else
{
// the old logic, verbatim
}
return 1; |
|
@vrn-sn Done, thanks! The new logic is now behind DFFlag::LuauOptimizeStringSplit (declared with LUAU_DYNAMIC_FASTFLAGVARIABLE, default off), and the flag-off branch is the original implementation verbatim. Tests pass with flags at their defaults and with all flags enabled. |
vrn-sn
left a comment
There was a problem hiding this comment.
Thanks for the contribution - especially appreciated the benchmarks!
string.splitcalledmemcmpat every byte offset and inserted results withlua_pushinteger+lua_settableinto an empty table. This change:memchrfor single-character separators, counting the pieces first so the result table is allocated at its final sizememcmpwhen both match, so no position does more work than beforelua_rawsetithroughoutOutput is unchanged: a differential fuzz of 20k random inputs, including embedded NULs and overlapping separators, matches the old implementation exactly. It also removes a pointer computation before the start of the buffer when the separator is longer than the string.
bench/micro_tests/test_string_split.luaThe last row is a deliberately adversarial input where both inline checks pass at every position; it performs the same
memcmpas before and runs at parity.Added conformance tests for edge cases (embedded NULs, overlapping separators, separator longer than the input).