String width calculation is a hot path in terminal rendering — it's called on every line of output in tools like Ink, cli-truncate, wrap-ansi, and log-update. With the growth of AI-powered terminal agents that stream large amounts of text, this is becoming even more performance-sensitive.
I profiled string-width and found two low-hanging optimizations: stripAnsi runs unconditionally even when no ANSI codes are present, and Intl.Segmenter runs on every call even for pure ASCII input where width = length.
ASCII + ANSI benchmarks (Apple M2 Max, Node 25.2.1)
| Input |
Before |
After |
Speedup |
| ascii short (11 chars) |
3.87 µs |
63.85 ns |
61x |
| ascii long (1000 chars) |
137.52 µs |
777 ns |
177x |
| ANSI short (5 visible) |
2.08 µs |
147.91 ns |
14x |
| ANSI heavy (101 chars) |
30.56 µs |
4.81 µs |
6.4x |
Non-ASCII inputs (CJK, emoji, mixed) are unaffected — they fall through to the existing Intl.Segmenter path.
PRs
Optimizations
-
ASCII fast path — regex /^[\u0020-\u007E]*$/ detects pure printable ASCII, returns string.length directly. Skips Intl.Segmenter, regex, and EAW lookup entirely. 61x faster for short ASCII, the most common input type.
-
stripAnsi guard — check string.includes('\x1B') || string.includes('\x9B') before calling stripAnsi. Avoids the overhead of strip-ansi's regex on strings that contain no ANSI escapes. 14x faster for ANSI-free short strings.
String width calculation is a hot path in terminal rendering — it's called on every line of output in tools like Ink, cli-truncate, wrap-ansi, and log-update. With the growth of AI-powered terminal agents that stream large amounts of text, this is becoming even more performance-sensitive.
I profiled string-width and found two low-hanging optimizations:
stripAnsiruns unconditionally even when no ANSI codes are present, andIntl.Segmenterruns on every call even for pure ASCII input where width = length.ASCII + ANSI benchmarks (Apple M2 Max, Node 25.2.1)
Non-ASCII inputs (CJK, emoji, mixed) are unaffected — they fall through to the existing
Intl.Segmenterpath.PRs
string.includes('\x1B')fast path to strip-ansiOptimizations
ASCII fast path — regex
/^[\u0020-\u007E]*$/detects pure printable ASCII, returnsstring.lengthdirectly. SkipsIntl.Segmenter, regex, and EAW lookup entirely. 61x faster for short ASCII, the most common input type.stripAnsi guard — check
string.includes('\x1B') || string.includes('\x9B')before callingstripAnsi. Avoids the overhead of strip-ansi's regex on strings that contain no ANSI escapes. 14x faster for ANSI-free short strings.