Context
string.format with many specifiers is 1.85× slower than luerl (n=1000:
7.42ms vs 4.00ms in benchmarks/string_format.exs). The dominant per-call
cost is format_spec_float/2 at lib/lua/vm/stdlib/string.ex:454-501, which
calls :erlang.float_to_binary and then post-processes through
String.split, String.pad_trailing, and string interpolation in
expand_float/2.
Luerl (deps/luerl/src/luerl_lib_string_format.erl:248-250) delegates the
entire conversion to io_lib:format/2, handling precision, sign, and
rounding in a single native Erlang call.
Change
lib/lua/vm/stdlib/string.ex:454-501 (format_spec_float/2) and likely
format_spec_scientific/3 at line 503.
- Replace
:erlang.float_to_binary([{:decimals, P}, :compact]) + expand_float
with a direct :io_lib.format(~c\"%.*f\", [precision, val]).
- Apply the same pattern for
%e and %g.
- Delete
expand_float/2.
Compatibility check (required)
Confirm rounding matches C Lua across:
test/lua/vm/stdlib/string_test.exs (all existing format cases)
- Lua 5.3 suite tests touching format/literals
Add unit tests around: precision-0 rounding (sign matters at boundaries),
large precision, inf/nan formatting.
Verification
mix test (full suite)
mix run benchmarks/string_format.exs
Expected
Closes the remainder of the spec-heavy gap. May flip us ahead of luerl on
many specs.
Context
string.formatwith many specifiers is 1.85× slower than luerl (n=1000:7.42ms vs 4.00ms in
benchmarks/string_format.exs). The dominant per-callcost is
format_spec_float/2atlib/lua/vm/stdlib/string.ex:454-501, whichcalls
:erlang.float_to_binaryand then post-processes throughString.split,String.pad_trailing, and string interpolation inexpand_float/2.Luerl (
deps/luerl/src/luerl_lib_string_format.erl:248-250) delegates theentire conversion to
io_lib:format/2, handling precision, sign, androunding in a single native Erlang call.
Change
lib/lua/vm/stdlib/string.ex:454-501(format_spec_float/2) and likelyformat_spec_scientific/3at line 503.:erlang.float_to_binary([{:decimals, P}, :compact])+expand_floatwith a direct
:io_lib.format(~c\"%.*f\", [precision, val]).%eand%g.expand_float/2.Compatibility check (required)
Confirm rounding matches C Lua across:
test/lua/vm/stdlib/string_test.exs(all existing format cases)Add unit tests around: precision-0 rounding (sign matters at boundaries),
large precision,
inf/nanformatting.Verification
mix test(full suite)mix run benchmarks/string_format.exsExpected
Closes the remainder of the spec-heavy gap. May flip us ahead of luerl on
many specs.