Статьи

Проникнуть в Groovy ++ — Что это? Почему это там?

В то время как некоторые находят язык Groovy все еще в зачаточном состоянии, другие знают, что сейчас есть Groovy ++, и все они следят за тем, что «++» языка принесет, что некоторые рекламируют как Java ++.

Мне было очень любопытно узнать об этом с тех пор, как первый анонс Groovy ++ был анонсирован в прошлом году (это было так давно? :-)). Первоначальные выпуски, которые вышли, были поддержаны минимальной (нет?) Документацией, и теперь есть вопросы в эфире, как —

  • Чего он пытается достичь?
  • Чего ждать людям, на что и почему?
  • Как это будет работать? Будет ли совместим с моим существующим Groovy код?

Понятно, что документации не хватает, потому что проект Groovy ++ очень, очень новый, но это не помогает. Итак, вместо того, чтобы ждать, пока документация станет доступной, я попытался взглянуть на Groovy ++ и найти ответы на свои вопросы. Вот небольшое описание нескольких вещей, которые я понимаю до сих пор. Я надеюсь, что это полезно для некоторых из вас.

Отказ от ответственности: содержание здесь выражает мое понимание и мнение по этому вопросу и подвержен человеческим ошибкам.

Итак, почему Groovy ++?

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

Чтобы взять очень маленький пример, если у меня есть «1 + 2» в groovy, чтобы позволить все динамизм и гибкость языка, проще говоря, он становится 1.plus (2), где вы можете изменить поведение «плюс» «и заставьте» 1 + 2 «сделать» 2 — 1 «, если хотите, и измените поведение» плюс «столько раз во время выполнения, сколько захотите. Таким образом, то, что в Java равно простой + операции, становится вызовом метода, который проходит различные проверки, чтобы увидеть, было ли изменено поведение метода «сейчас», и указать его текущее определение «+». Все это обходится производительностью, памятью и т. Д., И если даже в моих снах у меня никогда не было намерения переопределить «+», мне все равно пришлось бы нести расходы, связанные с соответствующей инфраструктурой Groovy.

Несмотря на то, что основной продукт всегда прилагает усилия для снижения этих затрат, то, чего сейчас не хватает, — это способ полностью избежать затрат.

На мой взгляд, самое большое преимущество Groovy ++ будет заключаться в том, что он позволит вам соблюсти баланс и избежать затрат на функции, которые вы не хотите использовать — насколько это возможно — поскольку он все еще должен оставаться отличным и не превращаться в Java , Это позволит вам выбрать части вашей программы, где вам нужен весь динамизм, гибкость основного ядра и вы готовы платить за него с точки зрения производительности, а также другие части, где вы можете делать это с меньшей динамичностью, но нуждаетесь в более высокой производительности и большем количестве. проверка времени компиляции.

Картинка, которую я имел в виду в Java-> Groovy-> Groovy ++ во время объявления Groovy ++, была такой:

 После небольшого пробуждения теперь оно меняется на:

Мне нравится, где находится Groovy ++, и я жду, когда он станет зрелым и еще больше из проекта.

Что такое Groovy ++?

Q. Это связано со стандартным Groovy?

О. Да, это просто расширение стандартного Groovy. Текущие выпуски Groovy ++ используют раскаленные снимки Groovy 1.8.x под капотами. Таким образом, все, что вы можете сделать на базовом groovy, доступно вам, если вы решите использовать статический компилятор groovy ++ для повышения производительности в любом месте.

Q. Где я могу найти это?

А. Вы можете скачать его здесь

В. Я установил Groovy ++. Как мне начать его использовать?

О. Пополнение groovy ++ для ядра groovy находится в groovypp.jar , который находится в папке lib в вашем каталоге установки. Чтобы начать использовать его, убедитесь, что он находится в classpath, а затем используйте аннотацию @Typed , предоставляемую groovy ++. Вы можете пометить выбранные методы, классы или пакеты как @Typed, и только те, которые статически компилируются groovy ++, в то время как для всего остального используется стандартный groovy.

Q. Как это работает внутри? Как его интеграция с groovy может быть такой простой?

О. Это достигается путем подключения к процессу Groovy — путем определения преобразования AST, которое запускается при использовании аннотации @Typed. Если вы не знакомы с основами этой техники, вам может пригодиться следующая статья — Метапрограммирование во время компиляции — Преобразования AST . Проще говоря, это то, что он делает:

  • Он перехватывает процесс компиляции, а затем обрабатывает все методы, выбранные с помощью @Typed — прямо или косвенно, через аннотированные классы / пакеты и выполняет их через более строгие проверки времени компиляции, методы вывода типов и
  • Изменяет AST, который генерируется Groovy-компилятором до этой точки, чтобы он выводил байт-код, который менее основан на динамической диспетчеризации и, следовательно, имеет лучшую производительность во время выполнения.

Плюсы и минусы использования Groovy ++

Q. Что я теряю?

A. Поведение метапрограммирования во время выполнения на языке Groovy, поскольку отправка методов становится более прямой и менее динамичной.

Q. Что я не теряю?

О. Большинство функций языка Groovy доступны «как есть» даже с Groovy ++, например —

  • Расширения Groovy для классов JDK
  • Менее многословная заводная кодировка
  • Поддержка таких функций, как категории, миксины, замыкания
  • Возможность подключиться к компиляции через преобразования AST

Q. Что я получу?

А. Такие вещи, как:

  • Лучшая производительность — за счет меньшего использования динамической отправки.
  • Еще менее подробный код — благодаря использованию вывода типов
  • Более безопасный код — благодаря более строгим проверкам времени компиляции

Сравнение Groovy / Groovy ++ через несколько примеров

Groovy ++ затрагивает прежде всего две области — производительность и более строгие проверки времени компиляции.

Поскольку изменения, которые он вносит для улучшения производительности, являются в основном внутренними (в генерируемом байт-коде — подробности о котором можно оставить для более поздней публикации), в этом разделе в основном делается попытка показать некоторые основные примеры, где различия более заметны снаружи — дать ощущение более строгих проверок времени компиляции и меньшее использование динамической отправки.

Пример 1: (статическая компиляция)

def addG(x, y) {
x + y
}

@Typed
def addGPP(x, y) {
x + y
}

println addG (2, 3)
println addGPP (2, 3)

В groovy ++ компиляция метода addGPP () завершается неудачно, потому что компилятор не знает статически, какую реализацию plus () вызывать, основываясь на типах параметров (groovy делает доступным ряд реализаций «плюс» и выбирает наиболее подходящую). на основе типов времени выполнения). В этом случае, Groovy ++ компилятор не может выводить типы тоже.

Пример 2: (метапрограммирование во время выполнения)

def addG(x, y) {
x + y
}

@Typed
def addGPP(Integer x, Integer y) {
x + y
}

// override plus to make '+' do multiplication instead
Integer.metaClass.plus = {Integer other -> delegate * other}

// because groovy uses runtime meta-programming to see the modified "+"
assert addG (2, 3) == 6

// because groovy++ does not use runtime meta-programming and instead binds to "+" at compile time
assert addGPP (2, 3) == 5

Пример 3: (Производительность)

Хотя этот пример почти ничего не делает, разница в производительности все еще указывает на направление, в котором работает Groovy ++. Разница в более реалистичном использовании может быть значительно выше.

def addG(x, y) {
x + y
}

@Typed
def addGPP(Integer x, Integer y) {
x + y
}

// override plus to make '+' do multiplication instead
Integer.metaClass.plus = {Integer other -> delegate * other}

def start = System.currentTimeMillis()
(1..1000000).each{
addG(2, 3)
}
def end = System.currentTimeMillis()
println "Groovy took ${end - start} milliseconds" // I got ~= 3.7 seconds

start = System.currentTimeMillis()
(1..1000000).each{
addGPP(2, 3)
}
end = System.currentTimeMillis()
println "Groovy++ took ${end - start} milliseconds" // I got ~= 1.8 seconds

Это всего лишь несколько очень простых примеров, чтобы подчеркнуть некоторые различия, обсуждаемые в этой статье. Я постараюсь охватить несколько более сложных примеров и более подробную информацию о Groovy ++ в следующих статьях.

Вывод

Я надеюсь, что статья послужила своей цели, познакомив с Groovy ++ и немного подогревая аппетит. Я чувствую, что Groovy ++ очень хорошо позиционируется между Java и Groovy, и я надеюсь, что он сможет удачно установить магический баланс и помочь Groovy стать еще более популярным языком.