Skip to content

Performance

Measured on a game project (~180 source files, LuaJIT target) as of April 2026. Times vary by machine.

ScenarioTime
Initial build~550ms
Incremental rebuild (watch mode)~6-18ms

Initial build phase breakdown:

PhaseTime
Parse + bind113ms
Type check203ms
Transform216ms
Print10ms
Write10ms

In watch mode (tslua -p tsconfig.json --watch), incremental rebuilds are fast because:

  • Incremental program update: typescript-go’s incremental.NewProgram diffs the changed file against its snapshot, avoiding a full reparse
  • Async diagnostics: type-checking runs in a background goroutine after .lua files are written. Diagnostics arrive ~20-50ms later without blocking output
  • Scoped semantic check: only the changed files are checked for import elision data, not the entire program
  • fsnotify: file changes are detected via OS notifications, not polling
PhaseTime
Program update~1-3ms
Transform~1-5ms
Print~0.1-0.5ms
Write~0.2-0.8ms
Build done~6-18ms
Diagnostics (async)+20-50ms

These benchmarks compare tstl (default) vs optimized emit mode as of April 2026. Optimized emit mode is early and only covers a few patterns so far (iterator allocation, tostring elision). The numbers below reflect what’s implemented today.

Terminal window
just bench # run with LuaJIT (default)
just bench-lua # show transpiled Lua output
BenchmarkTime (tstl)Time (opt)Garbage (tstl)Garbage (opt)
array_entries0.238ms0.028ms (8.5x)988 KB128 KB (-87%)
map_iterate0.080ms0.016ms (5.0x)355 KB96 KB (-73%)
set_iterate0.014ms0.011ms (1.3x)65 KB64 KB
BenchmarkTime (tstl)Time (opt)Garbage (tstl)Garbage (opt)
array_entries2.960ms0.373ms (7.9x)2600 KB256 KB (-90%)
map_iterate0.974ms0.463ms (2.1x)897 KB193 KB (-78%)
set_iterate0.807ms0.389ms (2.1x)551 KB129 KB (-77%)

Other benchmarks (array_iterate, array_push, string_iterate, string_concat) show no significant difference between modes. Run the full suite with just bench.

The wins come from iterator optimizations in optimized emit mode. Map/Set for-of loops use custom stateless Lua iterators that walk the internal linked list directly, avoiding per-step closure and table allocations. See Emit Mode for details.