From 21d69df22cc24c372c2ff0183de675d00b07e6bb Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Mon, 13 Jul 2026 15:23:41 +0200 Subject: [PATCH] perf: toStringAs appends digits and reverses once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit table.insert(t, 1, digit) shifts the whole accumulated table on every loop iteration — quadratic in the digit count (bounded at 32 for Int, so a constant-factor cost in practice). Append least-significant-first and reverse the joined string instead; each digit is a single ASCII byte, so string reverse is safe for every radix up to 36. Measured 1.5-1.6x on 31-digit binary rendering (LuaJIT and PUC 5.1). Refs purescript-lua/purescript-lua#186. --- changelog.d/20260713_150000_tostringas_append.md | 7 +++++++ src/Data/Int.lua | 9 ++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 changelog.d/20260713_150000_tostringas_append.md diff --git a/changelog.d/20260713_150000_tostringas_append.md b/changelog.d/20260713_150000_tostringas_append.md new file mode 100644 index 0000000..076e187 --- /dev/null +++ b/changelog.d/20260713_150000_tostringas_append.md @@ -0,0 +1,7 @@ +### Changed + +- `toStringAs` accumulates digits by appending and reverses the joined + string once, instead of shifting the whole digit table on every + iteration with `table.insert(t, 1, …)`. Same output; about 1.5× faster + on 31-digit binary rendering (Int digit counts are bounded, so this is a + constant-factor win). diff --git a/src/Data/Int.lua b/src/Data/Int.lua index f076615..aa9919c 100644 --- a/src/Data/Int.lua +++ b/src/Data/Int.lua @@ -61,7 +61,7 @@ return { end), toStringAs = (function(radix) return function(i) - local floor, insert = math.floor, table.insert + local floor = math.floor local n = floor(i) if radix == 10 then return tostring(n) end -- JS Number.prototype.toString(radix) uses lowercase digits. @@ -72,12 +72,15 @@ return { sign = "-" n = -n end + -- Digits come out least-significant first; append and reverse the + -- joined string (each digit is a single ASCII byte, so reverse is + -- safe) instead of shifting the table on every insert. repeat local d = (n % radix) + 1 n = floor(n / radix) - insert(t, 1, digits:sub(d, d)) + t[#t + 1] = digits:sub(d, d) until n == 0 - return sign .. table.concat(t, "") + return sign .. table.concat(t, ""):reverse() end end), quot = (function(x)