Intl API в JavaScript опирается на ICU (International Components for Unicode), поэтому его производительность определяется не только движком JavaScript, но и слоем нативных библиотек. В результате бенчмарки Intl требуют аккуратного подхода: измеряется не только скорость выполнения JS-кода, но и стоимость переходов в нативный слой, аллокаций локализационных структур и кеширования внутри движка.
Ключевые компоненты, влияющие на производительность:
Intl.NumberFormat,
Intl.DateTimeFormat, Intl.Collator);format,
formatToParts);Создание экземпляра Intl-объекта является одной из наиболее затратных операций в API. Причина заключается в необходимости:
Пример:
const fmt = new Intl.NumberFormat("ru-RU", {
style: "currency",
currency: "RUB"
});
Стоимость этого вызова существенно выше, чем последующее использование:
fmt.format(123456.78);
fmt.format(98765.43);
В бенчмарках часто наблюдается порядок различий:
Наиболее значимый фактор ускорения Intl-кода — переиспользование объектов форматирования.
Создание внутри горячих циклов приводит к деградации производительности:
for (let i = 0; i < 100000; i++) {
const f = new Intl.NumberFormat("en-US");
f.format(i);
}
Оптимизированный вариант:
const f = new Intl.NumberFormat("en-US");
for (let i = 0; i < 100000; i++) {
f.format(i);
}
Разница в бенчмарках обусловлена устранением повторной инициализации ICU-структур и аллокаций.
Метод formatToParts заметно тяжелее, чем
format, так как возвращает структурированный массив:
const f = new Intl.NumberFormat("en-US");
f.format(12345);
f.formatToParts(12345);
Причины дополнительной нагрузки:
В бенчмарках разница может достигать 2–5× в зависимости от движка и типа данных.
Не все локали обрабатываются одинаково быстро. Сложность зависит от:
Примеры:
"en-US" — минимальная нагрузка;"ru-RU" — умеренная;"ar-EG" — более сложная обработка числовых систем;"zh-Hant-TW-u-ca-chinese" — повышенная
стоимость резолва.Бенчмарки часто демонстрируют разницу не в форматировании, а именно в создании объекта.
Опции напрямую влияют на внутренние ветвления ICU.
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 2
});
Каждое дополнительное правило увеличивает сложность:
style: "currency" добавляет валютные таблицы;compactDisplay активирует компактные формы;signDisplay усложняет логику знаков.new Intl.DateTimeFormat("en-US", {
dateStyle: "full",
timeStyle: "long"
});
Каждый формат активирует дополнительные шаблоны ICU, что влияет на время инициализации.
Современные JS-движки применяют частичное кэширование:
Однако кэширование не гарантирует полного устранения накладных расходов при создании объектов.
Измерение Intl требует аккуратности из-за влияния JIT и оптимизаций.
Типичный шаблон:
const start = performance.now();
for (let i = 0; i < 1000000; i++) {
formatter.format(i);
}
const end = performance.now();
console.log(end - start);
Проблемы такого подхода:
Перед измерением критически важно выполнение warm-up фаз:
for (let i = 0; i < 10000; i++) {
formatter.format(i);
}
Это позволяет:
Без warm-up результаты часто завышают стоимость операций.
Intl API часто сравнивается с ручным форматированием строк:
// Intl
formatter.format(12345);
// manual
"12345".replace(/\B(?=(\d{3})+(?!\d))/g, ",");
Бенчмарки показывают, что:
Сортировка с использованием Intl.Collator имеет
собственную модель затрат:
const collator = new Intl.Collator("en", { sensitivity: "base" });
["z", "a", "c"].sort(collator.compare);
Особенности бенчмаркинга:
compare вызывается многократно внутри
sort;a - b;Оптимизация достигается созданием одного collator на всю операцию сортировки.
Intl API генерирует:
formatToParts);Частые вызовы приводят к росту нагрузки на garbage collector, особенно в сценариях:
Поведение Intl API зависит от реализации:
Различия проявляются в:
formatToParts;Типичные результаты микробенчмарков:
Intl.NumberFormat.format быстрее
formatToParts в 2–6 раз;Основные источники замедления:
formatToParts;Intl.Collator без
кеширования;Оптимизация почти всегда сводится к: