Engine compiled from Google's libphonenumber source at
github.com/google/libphonenumber@ba2a029.
Corpus: 1,132 phone numbers, one Google example per region per type (the example set the conformance
corpus is derived from).
Every library runs its built package, the same code a consumer installs.
Compared against the npm packages
libphonenumber-js@1.13.15
and
google-libphonenumber@3.2.47
(a community wrapper around Google's libphonenumber JS source).
Generated 2026-10-18T01:30:41.112Z.
Parse cost only.
| Operation | Telixon (ops/s) | libphonenumber-js (ops/s) | google-libphonenumber (ops/s) | vs libphonenumber-js | vs google-libphonenumber |
|---|---|---|---|---|---|
parsePhoneNumber (corpus pass) | 2.0k | 147 | 183 | 13.41× | 10.77× |
Parse + one method call. Telixon module caches cleared per iteration.
| Method | Telixon (ops/s) | libphonenumber-js (ops/s) | google-libphonenumber (ops/s) | vs libphonenumber-js | vs google-libphonenumber |
|---|---|---|---|---|---|
isValid | 1.6k | 120 | 98 | 13.67× | 16.75× |
isPossible | 1.7k | 140 | 173 | 11.97× | 9.71× |
isPossibleWithReason | 1.7k | 64 | 172 | 26.07× | 9.76× |
getNumberType | 1.5k | 111 | 86 | 13.96× | 18.05× |
getNationalNumber | 1.5k | 138 | 180 | 11.02× | 8.41× |
getCallingCode | 1.7k | 140 | 180 | 12.32× | 9.55× |
getRegion | 1.7k | 139 | 147 | 12.05× | 11.44× |
formatE164 | 1.6k | 140 | 175 | 11.23× | 8.98× |
formatRfc3966 | 671 | 129 | 101 | 5.20× | 6.66× |
formatNational | 722 | 87 | 106 | 8.28× | 6.83× |
formatInternational | 847 | 80 | 111 | 10.65× | 7.60× |
Parse + one method call. Caches retained across iterations.
| Method | Telixon (ops/s) | libphonenumber-js (ops/s) | google-libphonenumber (ops/s) | vs libphonenumber-js | vs google-libphonenumber |
|---|---|---|---|---|---|
isValid | 1.6k | 114 | 97 | 13.95× | 16.52× |
isPossible | 1.6k | 134 | 173 | 12.19× | 9.43× |
isPossibleWithReason | 1.7k | 64 | 171 | 26.83× | 10.04× |
getNumberType | 1.6k | 107 | 98 | 14.49× | 15.83× |
getNationalNumber | 1.8k | 139 | 181 | 13.08× | 10.08× |
getCallingCode | 1.8k | 140 | 181 | 13.22× | 10.18× |
getRegion | 1.7k | 138 | 146 | 12.55× | 11.83× |
formatE164 | 1.6k | 139 | 176 | 11.38× | 8.95× |
formatRfc3966 | 771 | 129 | 99 | 5.97× | 7.77× |
formatNational | 923 | 86 | 105 | 10.69× | 8.83× |
formatInternational | 993 | 81 | 110 | 12.33× | 9.04× |
Pre-parsed value, method called repeatedly. Where libphonenumber-js stores the value as a direct property after
parse (nationalNumber, countryCallingCode, number, country),
the warm comparison is a property read against Telixon's cached method call; the table below shows the measured
numbers.
| Method | Telixon (ops/s) | libphonenumber-js (ops/s) | google-libphonenumber (ops/s) | vs libphonenumber-js | vs google-libphonenumber |
|---|---|---|---|---|---|
isValid | 23.5k | 676 | 224 | 34.82× | 105.26× |
isPossible | 22.5k | 3.7k | 3.9k | 6.10× | 5.82× |
isPossibleWithReason | 21.8k | 118 | 3.6k | 184.75× | 5.96× |
getNumberType | 23.0k | 596 | 229 | 38.64× | 100.57× |
getNationalNumber | 23.2k | 23.9k | 17.1k | 0.97× | 1.36× |
getCallingCode | 24.4k | 24.4k | 19.4k | 1.00× | 1.26× |
getRegion | 23.4k | 23.6k | 839 | 0.99× | 27.83× |
formatE164 | 23.4k | 24.6k | 8.2k | 0.95× | 2.84× |
formatRfc3966 | 24.8k | 2.2k | 247 | 11.04× | 100.55× |
formatNational | 24.3k | 304 | 283 | 79.96× | 85.81× |
formatInternational | 29.3k | 258 | 324 | 113.60× | 90.26× |
Telixon only: competitor formatters have no comparable API (no caret, no deletion, no undo, no per-keystroke queries). One iteration is a full corpus pass: every digit of all 1,132 corpus numbers, typed end to end through the controller. Read the mean column as "what typing the entire corpus costs"; single keystrokes are profiled in the next section.
| Scenario | ops/s | mean (ms) | p99 (ms) | ±rme |
|---|---|---|---|---|
| type-through full number (corpus pass) | 85 | 11.82 | 12.28 | ±0.38% |
| type-through + core PhoneNumber query methods per keystroke (corpus pass) | 44 | 22.63 | 24.00 | ±0.87% |
| backspace at caret after full type-through (corpus pass) | 46 | 21.72 | 22.16 | ±0.36% |
| type-through + undo + redo (corpus pass) | 84 | 11.89 | 12.47 | ±0.40% |
| full undo back to empty + redo to full (corpus pass) | 84 | 11.92 | 12.29 | ±0.38% |
The number that decides whether an input feels instant: the cost of one keystroke, sampled individually (process.hrtime.bigint()
after warmup). For scale, the panel below measures that latency against one display frame across common refresh
rates (60-360 Hz); the benchmark itself runs headless, so it assumes no single display.
| Scenario | samples | mean | p50 | p95 | p99 |
|---|---|---|---|---|---|
| international: insert per keystroke | 68,720 | 1.16 µs | 1.21 µs | 1.75 µs | 2.84 µs |
| international: insert + 7 query methods per keystroke | 68,720 | 2.03 µs | 1.86 µs | 3.49 µs | 5.78 µs |
Worst-case (p99) keystroke against one frame, at common display refresh rates:
| Display refresh rate | One frame | p99 keystroke headroom |
|---|---|---|
| 60 Hz | 16.67 ms | 2,884× |
| 120 Hz | 8.33 ms | 1,442× |
| 240 Hz | 4.17 ms | 721× |
| 360 Hz (strictest) | 2.78 ms | 481× |
Across 137,440 sampled keystrokes, the 99th percentile is 5.78 µs. The maximum and deep tail are omitted: they are dominated by OS scheduling, not the code, and grow with sample count.
Phone-number processing alone stays orders of magnitude under one frame at every standard refresh rate.