Перейти к основному содержимому

Более быстрые и функциональные API интернационализации

· 5 мин. чтения
[சத்யா குணசேகரன் (Сатья Гунасекаран)](https://twitter.com/_gsathya)

Спецификация API интернационализации ECMAScript (ECMA-402, или Intl) предоставляет ключевые функции, зависящие от локали, такие как форматирование дат, чисел, выбор формы множественного числа и сортировка. Команды Chrome V8 и Google Internationalization работали над добавлением новых функций в реализацию ECMA-402 в V8, при этом устраняя технические долги и улучшая производительность и совместимость с другими браузерами.

Улучшения архитектуры

Изначально спецификация ECMA-402 была реализована в основном на JavaScript с использованием расширений V8 и находилась вне кода V8. Использование внешнего API Extension означало, что несколько внутренних API V8, используемых для проверки типов, управления временем жизни внешних объектов C++ и внутреннего хранения приватных данных, не могли быть использованы. В рамках повышения производительности запуска эта реализация позже была перемещена в кодовую базу V8 для включения снапшотов этих встроенных функций.

V8 использует специализированные JSObject с настраиваемыми формами (скрытые классы) для описания встроенных объектов JavaScript, указанных в ECMAScript (например, Promise, Map, Set и т.д.). Такой подход позволяет V8 заранее выделить необходимое количество внутренних слотов и обеспечить быстрый доступ к ним, вместо роста объекта по одному свойству, что приводит к снижению производительности и увеличению использования памяти.

Реализация Intl не была построена на такой архитектуре в силу исторического разделения. Вместо этого все встроенные объекты JavaScript, указанные в спецификации интернационализации (такие как NumberFormat, DateTimeFormat), были общими JSObject, которые должны были переходить через несколько добавлений свойств для своих внутренних слотов.

Другим недостатком отсутствия специализированных JSObject заключалось в усложнении проверки типов. Информация о типах хранилась под приватным символом и проверялась как на стороне JS, так и на стороне C++ с использованием затратного доступа к свойствам, вместо простого обращения к их форме.

Обновление кода

С учетом текущего отхода от написания встроенных функций в V8, было логично использовать эту возможность для модернизации реализации ECMA402.

Уход от самохостинга JS

Хотя самохостинг обеспечивает лаконичный и читаемый код, частое использование медленных вызовов времени выполнения для доступа к API ICU вызывало проблемы с производительностью. В результате некоторая функциональность ICU была дублирована в JavaScript для сокращения числа таких вызовов.

Переписав встроенные функции на C++, мы добились гораздо более быстрого доступа к API ICU, так как больше не существует накладных расходов на вызовы времени выполнения.

Улучшение ICU

ICU — это набор библиотек C/C++, используемый множеством приложений, включая все основные движки JavaScript, для поддержки Unicode и глобализации. В процессе перехода реализации Intl на ICU в V8 мы обнаружили и исправили несколько ошибок ICU.

В процессе внедрения новых предложений, таких как Intl.RelativeTimeFormat, Intl.ListFormat и Intl.Locale, мы расширили ICU, добавив несколько новых API для поддержки этих новых предложений ECMAScript.

Все эти дополнения помогают другим движкам JavaScript быстрее внедрять эти предложения, ускоряя развитие веба! Например, в Firefox в настоящее время идет разработка нескольких новых API Intl на основе нашей работы с ICU.

Производительность

В результате этой работы мы повысили производительность API интернационализации, оптимизировав несколько быстрых путей и кэшируя инициализацию различных объектов Intl и методов toLocaleString у Number.prototype, Date.prototype и String.prototype.

Например, создание нового объекта Intl.NumberFormat стало примерно в 24 раза быстрее.

Микротесты для проверки производительности создания различных объектов Intl

Обратите внимание, что для повышения производительности рекомендуется явно создавать и повторно использовать объект Intl.NumberFormat, Intl.DateTimeFormat или Intl.Collator, а не вызывать методы, такие как toLocaleString или localeCompare.

Новые функции Intl

Вся эта работа обеспечила отличную основу для разработки новых функций, и мы продолжаем внедрять все новые предложения по интернационализации, которые находятся на этапе 3.

Intl.RelativeTimeFormat был выпущен в Chrome 71, Intl.ListFormat был выпущен в Chrome 72, Intl.Locale был выпущен в Chrome 74, а dateStyle и timeStyle опции для Intl.DateTimeFormat и поддержка BigInt для Intl.DateTimeFormat выпущены в Chrome 76. Intl.DateTimeFormat#formatRange, Intl.Segmenter, и дополнительные опции для Intl.NumberFormat в настоящее время разрабатываются в V8, и мы надеемся, что они скоро будут внедрены!

Многие из этих новых API, а также другие, находящиеся на дальнейших этапах разработки, стали возможны благодаря нашей работе по стандартизации новых функций для помощи разработчикам в интернационализации. Intl.DisplayNames — это предложение на этапе 1, которое позволяет пользователям локализовать отображение имен языков, регионов или скриптовых имен. Intl.DateTimeFormat#formatRange — это предложение на этапе 3, которое определяет способ форматирования диапазонов дат в краткой форме с учетом локализации. Унифицированное предложение API Intl.NumberFormat — это предложение на этапе 3, которое улучшает Intl.NumberFormat путем добавления поддержки единиц измерений, валют и политик отображения знаков, а также научной и компактной нотации. Вы также можете участвовать в разработке ECMA-402, внося вклад в его репозиторий на GitHub.

Заключение

Intl предоставляет насыщенный функциями API для выполнения нескольких операций, необходимых для интернационализации вашего веб-приложения, оставляя всю трудоемкую работу браузеру, без необходимости передачи большого объема данных или кода по сети. Продуманное использование этих API может сделать ваш пользовательский интерфейс более эффективным в разных локалях. Благодаря работе команд Google V8 и i18n в сотрудничестве с TC39 и его подгруппой ECMA-402, вы теперь можете получить доступ к большему количеству функций с повышенной производительностью и ждать дальнейших улучшений со временем.