Performance
Telixon’s cost profile follows from its shape: digits drive one deterministic automaton compiled from Google’s metadata. The pattern matching that Google libphonenumber performs with regular expressions at query time is instead performed once, at build time, when the automaton is compiled (Engine). What remains at runtime divides into three budgets: a one-time decode at startup, a per-query walk in steady state, and one engine’s worth of memory per process.
Startup cost
Section titled “Startup cost”All deferred work happens in one place: ensureEngineReady. It imports the compressed engine modules, decompresses them, and parses the layers into the typed arrays that every query reads from. After the arrays exist, the provider makes one linear pass over the region table to build its index maps (region code to index, calling code to index), and initialization is complete. The artifact layout itself is described in Engine.
Decompression is delegated to the platform rather than reimplemented:
- The Node entry decodes with native zlib on the libuv threadpool, off the JavaScript thread.
- The browser and edge entries decode with
DecompressionStream, off the main thread. - The
@telixon/core/sync-initentry bundles the modules statically and decodes them with a pure-JavaScript inflate on the calling thread, for callers that need a ready engine without awaiting.
Nothing runs at import time. The decode starts when the consumer calls ensureEngineReady (or ensureEngineReadySync), so the consumer decides where in application startup the cost lands; Load the engine covers placing it per environment. Once the engine is ready, further calls return immediately, and concurrent calls share a single in-flight load. Before it is ready, every query throws EngineNotReadyError:
import { parsePhoneNumber } from '@telixon/core';
parsePhoneNumber('+1 415-555-0132');// throws EngineNotReadyError: initialization is explicit, nothing decodes implicitlySteady-state cost
Section titled “Steady-state cost”After ensureEngineReady resolves, every query is synchronous. Parsing is one automaton walk: each digit is one state transition, a handful of bit operations on a Uint32Array word. Validity is an accepting state, so isValid() is a property of the state the walk ends in, read from a verdict table, not a pattern evaluated against the digit string. Number type, candidate regions, and format selection are further typed-array reads indexed by that same end state.
import { ensureEngineReady, parsePhoneNumber } from '@telixon/core';
await ensureEngineReady(); // the decode happens here, once
const phone = parsePhoneNumber('+1 415-555-0132'); // one automaton walk, synchronousphone.isValid(); // truephone.getRegion(); // 'US'phone.formatNational(); // '(415) 555-0132'phone.formatE164(); // '+14155550132'PhoneNumber memoizes each derived answer on the instance: the first formatNational() computes the string, repeated calls return the cached one. Querying the same instance from a render loop or change-detection cycle therefore costs a cached read, not a recompute.
Two runtime regular expressions
Section titled “Two runtime regular expressions”Exactly two regular expressions execute at query time. Both are prefix rewrites that libphonenumber defines as substitution rules rather than acceptance patterns, which is why they are not representable as automaton transitions:
- The national-prefix rewrite, built from the region’s national-prefix parsing rule. A first-digit bitmask check rejects inputs whose first digit cannot begin the region’s prefix, so most inputs never reach the expression.
- The IDD strip, built from the region’s international dialling prefix. It applies only to national-mode input, and the compiled expression is memoized per region.
Every other pattern in Google’s metadata, the validation patterns, the possible-length rules, and the leading-digit rules that drive format selection, is compiled into the automaton and its tables at build time. No regular expression is compiled from a validation pattern at runtime.
The per-keystroke path
Section titled “The per-keystroke path”parsePhoneNumber and the input controller are the same shared resolve layer, queried in batch versus per keystroke. Because a keystroke budget bounds the layer, it avoids allocation on the step path: one resolver instance is reused across resolves, input is scanned by character code instead of being tokenized, no spread copies occur on getPhoneNumber or the controller step methods, and region and number-type filters are compiled into bitmask arrays once when set, not evaluated per step. The input controller page describes what each step computes.
In CI benchmarks, parsing measures about 4x faster than the google-libphonenumber npm wrapper, a third-party npm packaging of Google’s JavaScript implementation. Speed and accuracy are separate claims: accuracy is established by the conformance suite described in Verified, which runs against Google’s own source at the engine’s pinned commit.
Memory
Section titled “Memory”A process holds one engine. The decoded engine lives in a provider stored on globalThis under Symbol.for('telixon.core.resourceProvider'), so duplicate copies of the module in one process (two bundles, federated chunks, a dependency shipping its own copy) resolve to the same key and share the single instance. A module-local reference keeps the hot-path lookup a single read. The engine’s memory cost is paid once per process regardless of how many entry points initialize it.
The engine data stays in the typed arrays it decoded into, and queries index into those arrays in place. Steady-state caches are bounded: the IDD matcher memo holds at most one compiled expression per region, the shared resolver is a single reused instance, and PhoneNumber caches live on the instance and are released with it.
See also
Section titled “See also”- Engine: the artifact layout and how the automaton is compiled from Google’s metadata
- The model: the vocabulary the whole library is built on
- Load the engine: placing the one-time decode per environment
- Verified: the conformance suite behind the accuracy claim