Источник [Announcing Dart 2.2: Faster native code, support for set literals]
Сегодня (26 февраля 2019) мы объявляем о выпуске Dart 2.2 SDK — обновления для Dart 2, которое предлагает улучшенную производительность ahead-of-time (AOT) кода и поддержку Set литералов.
Повышение производительности Dart для разработки на Flutter
Мы продолжаем нашу работу, чтобы сделать AOT-скомпилированный код, вроде Flutter приложений, еще быстрее. В Dart 2.1 мы сократили издержки на проверку типов, значительно снизив стоимость проверки типов как для кода, скомпилированного AOT, так и для кода, выполняемого на виртуальной машине с JIT (just-in-time) компиляцией.
В Dart 2.2 мы сосредоточились на производительности AOT-скомпилированного кода, улучшив производительность на 11-16% на микробенчмарках (за счет увеличения размера кода на ~1%). Это улучшение является результатом работы в течение нескольких кварталов, с целью уменьшить издержки статических вызовов. Наш оптимизированный AOT код теперь может вызывать запрошенный объект напрямую с помощью вызова PC (то есть с помощью Program counter). До этого мы должны были провести несколько раз поиск в пуле объектов для определения необходимого адреса. Эти оптимизации особенно полезны, когда код содержит множество конструкторов и статических вызовов методов, таких как код пользовательского интерфейса Flutter, который содержит множество виджетов.
Поддержка Set литералов в Dart 2.2
Основная библиотека Dart (dart:core) содержит несколько классов коллекций: Maps, Lists, и Sets. Maps представляют собой наборы пар ключ-значение. Lists являются упорядоченными последовательностями значений, к каждому из которых может быть получен доступ с помощью индекса и которые могут встречаться несколько раз. Sets — это неупорядоченные коллекции значений, в которых каждое значение может встречаться только один раз и где можно эффективно проверить, есть ли значение в коллекции.
Коллекции Dart обычно инициализируются compile-time константами, и Dart предлагает удобный синтаксис для написания этой инициализации. В Dart List можно инициализировать следующим образом:
const List<String> releases = ['Dart 2.0', 'Dart 2.1', 'Dart 2.2'];
Ранее Dart поддерживал литеральный синтаксис только для List и Map, поэтому инициализация Set была громоздкой, так как нам приходилось инициализировать через список:
Set<String> currencies = Set.of(['EUR', 'USD', 'JPY']);
Этот код не просто неудобен и неэффективен; отсутствие поддержки литералов не позволяет создать неизменяемый Set во время компиляции. С добавлением поддержки Set литералов в Dart 2.2 инициализировать множество и сделать его неизменяемым, используя удобный новый синтаксис:
const Set<String> currencies = {'EUR', 'USD', 'JPY'};
Реальные примеры использования Set литералов командой Flutter можно посмотреть здесь. Для более подробного углубления в вопрос предлагаем ознакомиться с обновленным Dart 2.2 language tour.
Обеспечение нововведений с помощью Dart 2 Common Front-End (CFE)
Dart предлагает несколько своих реализаций: Dart VM, используемая Flutter, dart2js компилятор и Dart dev компилятор (dartdevc), — все они используют Common Front-End компилятор. Dart Common Front End, или CFE, парсит код Dart, выполняет вывод типов и транслирует Dart на промежуточный язык более низкого уровня, который back end компиляторы принимают в качестве входа.
Set литералы — пример языковой конструкции, которые мы смогли быстро реализовать благодаря CFE. Код для парсинга Set литералов и выполнение вывода типов были реализованы один раз с помощью CFE для всех реализаций. Кроме того, мы создали переходную реализацию, которая могла бы использоваться back end компиляторами на начальном этапе. В промежуточной реализации изменяемая версия указанных Set литералов переводилась в ходе компиляции в эквивалентную форму:
Set<String> currencies = Set<String>()..add('EUR')..add('USD')..add('JPY');
Промежуточная реализация константных Set литералов отличается тем, что не могут быть собраны постепенно по частям. Вместо этого мы реализовали это в терминах приватного неизменяемого Set класса, который оборачивает неизменяемый Map, где элементы Set являются ключами Map:
const Set<String> currencies =
_UnmodifiableSet<String>({'EUR': null, 'USD': null, 'JPY': null});
Неизменяемый Set класс реализует методы в интерфейсе Set, делегируя их во внутренний Map.
В целом, мы смогли реализовать Set литералы изначально как функцию исключительно CFE. Back end мог сразу использовать реализацию CFE, и реализовать свою собственную поддержку позднее. Это позволило back end компиляторам отложить свою поддержку до тех пор, пока аспекты производительности этой функции не стали поняты лучше.
Спецификация Dart 2.2
Dart 2 был настолько существенным обновлением Dart, что нам потребовалось некоторое время, чтобы обновить официальную спецификацию языка, чтобы соответствовать всем изменениям, которые мы сделали. Мы, наконец, завершили эту работу, и спецификация обновлена до версии Dart 2.2. Мы также переместили спецификацию языка в новый репозиторий и добавили непрерывную интеграцию, чтобы обеспечить постоянное обновление спецификации в формате PDF по мере развития будущих версий языка Dart. И 2.2, и будущие Dart 2.x спецификации доступны на странице спецификации Dart.
Как установить Dart 2.2
Dart SDK 2.2 доступен на домашней странице Dart с сегодняшнего дня. Если вы Flutter разработчик, Dart 2.2 уже включен. (Примечание: на консольную команду «flutter doctor» текущие каналы Flutter master и dev сообщат о Dart 2.2. Сегодняшняя стабильная версия Flutter 1.2 выведет Dart 2.1.2; данная версия имеет те же возможности, что и Dart 2.2).
На данный момент это все. Мы надеемся, что вам понравится Dart 2.2!
Огромное спасибо за помощь в переводе PsyHaSTe
Автор: Кирилл Матросов