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.3
and
google-libphonenumber@3.2.44
(a community wrapper around Google's libphonenumber JS source).
Generated 2026-09-05T04:26:50.983Z.
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.5k | 196 | 214 | 12.76× | 11.67× |
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 | 2.0k | 158 | 119 | 12.71× | 16.83× |
isPossible | 2.1k | 182 | 209 | 11.53× | 10.02× |
isPossibleWithReason | 2.1k | 87 | 206 | 24.70× | 10.44× |
getNumberType | 2.0k | 150 | 124 | 13.28× | 16.05× |
getNationalNumber | 2.3k | 191 | 217 | 12.16× | 10.72× |
getCallingCode | 2.3k | 188 | 217 | 12.37× | 10.72× |
getRegion | 2.2k | 182 | 167 | 11.96× | 13.02× |
formatE164 | 1.9k | 184 | 204 | 10.52× | 9.53× |
formatRfc3966 | 846 | 177 | 130 | 4.79× | 6.51× |
formatNational | 908 | 122 | 135 | 7.45× | 6.74× |
formatInternational | 1.1k | 117 | 140 | 9.21× | 7.67× |
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 | 2.0k | 155 | 120 | 12.74× | 16.45× |
isPossible | 2.1k | 176 | 210 | 11.74× | 9.88× |
isPossibleWithReason | 2.1k | 86 | 205 | 24.59× | 10.34× |
getNumberType | 2.0k | 149 | 123 | 13.26× | 16.07× |
getNationalNumber | 2.1k | 187 | 213 | 11.01× | 9.66× |
getCallingCode | 2.2k | 186 | 210 | 11.79× | 10.49× |
getRegion | 2.2k | 189 | 179 | 11.49× | 12.19× |
formatE164 | 2.0k | 188 | 209 | 10.58× | 9.49× |
formatRfc3966 | 960 | 174 | 127 | 5.53× | 7.54× |
formatNational | 1.1k | 123 | 134 | 9.20× | 8.48× |
formatInternational | 1.3k | 117 | 138 | 10.70× | 9.11× |
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 | 39.5k | 911 | 288 | 43.40× | 137.39× |
isPossible | 38.6k | 3.1k | 5.5k | 12.62× | 7.03× |
isPossibleWithReason | 37.4k | 152 | 5.2k | 246.87× | 7.26× |
getNumberType | 42.6k | 802 | 293 | 53.09× | 145.09× |
getNationalNumber | 43.1k | 43.7k | 26.8k | 0.99× | 1.61× |
getCallingCode | 43.5k | 44.6k | 31.3k | 0.98× | 1.39× |
getRegion | 44.6k | 44.4k | 1.1k | 1.00× | 41.06× |
formatE164 | 42.9k | 36.0k | 11.9k | 1.19× | 3.61× |
formatRfc3966 | 36.2k | 2.9k | 315 | 12.34× | 115.07× |
formatNational | 35.9k | 384 | 365 | 93.56× | 98.36× |
formatInternational | 36.1k | 330 | 418 | 109.56× | 86.40× |
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) | 107 | 9.39 | 9.67 | ±0.34% |
| type-through + core PhoneNumber query methods per keystroke (corpus pass) | 54 | 18.49 | 19.80 | ±0.61% |
| backspace at caret after full type-through (corpus pass) | 57 | 17.42 | 18.03 | ±0.52% |
| type-through + undo + redo (corpus pass) | 104 | 9.60 | 10.00 | ±0.41% |
| full undo back to empty + redo to full (corpus pass) | 104 | 9.62 | 11.12 | ±0.69% |
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.12 µs | 1.06 µs | 2.12 µs | 2.97 µs |
| international: insert + 7 query methods per keystroke | 68,720 | 1.76 µs | 1.62 µs | 3.11 µs | 4.96 µ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 | 3,362× |
| 120 Hz | 8.33 ms | 1,681× |
| 240 Hz | 4.17 ms | 841× |
| 360 Hz (strictest) | 2.78 ms | 560× |
Across 137,440 sampled keystrokes, the 99th percentile is 4.96 µ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.