В начале сентября 2021 года вышел 3-й релиз языка программирования Scala, который разработчики называют полностью переработанным из-за модернизации системы типов и добавления новых функций. Текущая версия Apache Spark 3.2.0, выпущенная месяцем позже, поддерживает Scala 2.13 и 3.0 с ограничением некоторых возможностей. Читайте далее, как разработчикам распределенных Spark-приложений писать задания на Scala 3.
Apache Spark 3.2.0 и Scala 3.0: главные новинки
13 октября вышла новая версия Apache Spark 3.2.0, которая поддерживает уровень API Pandas, RocksDB StateStore, сеансовые окна, push-перемешивания, типы INTERVAL в ANSI SQL и общую доступность этого стандарта запросов, а также включение адаптивного выполнения запросов (AQE, Adaptive Query Execution) по умолчанию. Впервые AEQ-структура, которая повышает производительность и упрощает настройку, создавая лучший план во время выполнения, была введена в выпуске Apache Spark 3.0, о чем мы писали здесь. Видимо, успех практического применения этой структуры адаптивного выполнения SQL-запросов, стал причиной включения этого режима по умолчанию. Также в выпуске Apache Spark 3.2.0 снижено время компиляции запросов и добавлена поддержка Scala 2.13, что позволяет разработчику писать задания на 3-ей версии этого языка программирования из-за использования общих библиотек [1].
Таким образом, первым условием реализации Spark-приложения на Scala 3 является версия фреймворка, совместимая с релизом 2.13 этого языка программирования. Однако, переход на новые версии все же сопровождается некоторыми сложностями, о чем мы поговорим далее, а пока отметим некоторые ключевые особенности 3-го релиза.
Scala 3 — это улучшенная версия языка Scala 2: некоторые конструкции упрощены, ограничены или полностью исключены. Новый синтаксис для управляющих структур позволяет записывать условие if-выражения, условие цикла while или генераторы выражения for без заключения скобок. Синтаксис отступов делает фигурные скобки {…} ненужными во многих случаях: тела классов и методов, выражения if, выражения соответствия и т.д. [2]
Добавлена новая среда метапрограммирования, которая заменяет экспериментальные макросы Scala 2, где вызов метода макроса выполнялся на этапе компиляции для создания абстрактного синтаксического дерева. В 3–ей версии используется другой подход к метапрограммированию для обеспечения стабильности: генерация кода, оптимизация, эргономичные DSL.
Во 2-ой версии подписи хранятся в Pickle-формате, а 3-ей в формате TASTy (Typed Abstract Syntax Trees), который является высокоуровневым формато обмена для языка программирования. Файлы TASTy генерируются компилятором scalac и содержат всю информацию об исходном коде приложения, включая синтаксическую структуру программы, а также полную информацию о типах, позициях и даже документацию. TASTy-файлы содержат больше информации, чем файлы .class, которые создаются для работы на JVM и имеют проблему стирания типов. Подобные проблемы существуют для всех остальных конструкций Scala, о которых JVM не знает, включая соединения, пересечения и многие другие функции 3-ей версии языка.
Вместо этого формат TASTy сохраняет полное абстрактное синтаксическое дерево (AST, Abstract Syntax Tree) после проверки типа, чтобы выполнять раздельную компиляцию, перекомпиляцию для другой версии JVM, статический анализ программ и пр. [3, 4]
Проблемы перехода на новые версии
API метапрограммирования Scala используется в Apache Spark для реализации некоторых неявных преобразований. В частности, Spark sql API предоставляет абстракцию Dataset [T], для большинства методов этого типа требуется неявный экземпляр Encoder [T], которые создаются автоматически:
scala import sqlContext.implicits [3].
Этот код не поддерживается в Scala 3, поэтому чтобы перейти с версии 2.13 на 3.0 можно использовать открытую библиотеку spark-scala3 [5], которая добавляет необходимые экземпляры (имплициты в Scala 2). Библиотека предоставляет альтернативный вывод runtime-компилятора, который можно включить с помощью следующего импорта: import scala3encoders.given
После этого можно транслировать код приложения на Scala версии 2.13 в версию 3.0, вручную добавив недостающие экземпляры. Например, преобразовать классы case в форму, которую может обрабатывать spark-scala3, заменив Array [Byte] на строки в кодировке Base64 и Option [String] на строки со значимым значением String для None. Пример рассмотрен в источнике [1].
Читайте в нашей новой статье, как открытая ML-библиотека Spark NLP поддерживает сам фреймворк Apache Spark и PySpark 3.2.x на Scala 2.12.
Станьте специалистом по Apache Spark для разработки распределенных приложений аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
- Основы Apache Spark для разработчиков
- Анализ данных с Apache Spark
- Потоковая обработка в Apache Spark
- Машинное обучение в Apache Spark
- Графовые алгоритмы в Apache Spark
Источники
- https://medium.com/virtuslab/scala-3-and-spark-389f7ecef71b
- https://spark.apache.org/releases/spark-release-3-2-0.html
- https://docs.scala-lang.org/scala3/new-in-scala3.html
- https://docs.scala-lang.org/scala3/guides/migration/compatibility-metaprogramming.html
- https://libraries.io/maven/io.github.vincenzobaz:spark-scala3_3