Я не использовал Groovy в течение 2 лет, с момента моего последнего контакта с Grails . Я застрял в (жестком) ядре Enterprise Java с некоторыми аспектами производительности в фоновом режиме. Я почти упустил шанс изучить Спока , но, к счастью, варшавская Java User Group помогла мне избавиться от некоторых устаревших систем и вернуться к нормальному саморазвитию. На самом деле, я надеюсь, что такие фреймворки, как Spock или Geb , изменят подход к написанию тестов, сделав их проще и эффективнее. Обе платформы используют Groovy, а также новый король в инструментах сборки — Gradle . Наблюдая за тем, как Groovy влияет на нашу повседневную работу, я решил посмотреть на его производительность и сравнить его с Java 7.
Моя тестовая среда основана на Java 1.7.0_25 и Groovy 2.1.6. Как всегда в таких сравнениях, я использовал Caliper в версии 1.0-бета-1 (почти стабильной) и подготовил ряд (я надеюсь) репрезентативных микробенчмарков.
Первый бенчмарк, основанный на фреймворке Fork / Join, должен быть максимально похож на обоих языках, потому что он использует некоторые нативные механизмы Мой тест инициализирует массив некоторыми случайными данными типа int, а затем использует framework для поиска самого большого элемента в массиве. В Groovy мои вычислительные функции выглядят так:
@Override
Integer compute() {
def size = end - start
if (size == 1) {
Math.max(array[start], array[end])
} else {
int diff = size / 2
MaxValueSeeker left =
new MaxValueSeeker(array, start, start + diff)
left.fork()
MaxValueSeeker right =
new MaxValueSeeker(array, start + diff, end)
Math.max(right.compute(), left.join())
}
}
Java-версия, конечно, очень похожа. После десятка минут измерений я получаю очень многообещающий результат: Groovy медленнее всего … в 8 раз ?
Теперь пришло время проверить некоторые более реалистичные в повседневной разработке. Я выбрал простой POJO / POGO (да) с несколькими простыми операциями, просто чтобы быть уверенным, что JIT не устранит мой код (и поверьте мне, он любит делать такие шутки). Мой псевдо «бизнес-логика» метод в Groovy:
def int proceed(int reps) {
List<GroovyPojo> list = new ArrayList<>()
int sum = 0;
reps.times {
// first param is int and second is String
list.add(new GroovyPojo(value: it, stringValue: it))
}
list.each {
if (Integer.parseInt(it.stringValue) == it.value) {
sum += it.value
}
}
sum
}
Версия Java отличается в основном геттерами и ручным боксом строк в конструкторе POJO. Еще один раз дюжина минут потрачена на чтение новостей и … на этот раз Groovy медленнее всего в 7 раз
Последний тест должен быть стрессовым и проверять оба языка в более сложных вычислениях. Я решил и выбрал алгоритм быстрой сортировки. Несколько циклов, несколько операторов if должны работать. Я не собираюсь копировать и вставлять это здесь, потому что это хорошо известное решение. Стоит упомянуть, конечно же, временные результаты, превосходящие Groovy почти в 5 раз! Но я немного погуглил и заметил, что Groovy 2.0 представил аннотацию @CompileStatic, которая должна дать нам дополнительный прирост производительности. Итак, давайте проверим … Да, при статической компиляции преимущество Java упало до 220%.
В таблице ниже вы можете найти подробные результаты. Подводя итог — я не уверен, что использование Groovy в критически важных функциях — хорошая идея, но определенно это отличное решение для реализации тестов, создания прототипов и т. Д. Просто позвольте мне подчеркнуть, что написание анализатора результатов Caliper заняло около 6 строк в Groovy. (анализ json, итерация по измерениям и подсчет среднего)
метод | Java [ns] | Groovy [нс] | фактор |
---|---|---|---|
Вилка / Регистрация | 22,132 | 181,018 | 8,18 |
Pojos | 117,914 | 856,337 | 7,26 |
Quicksort | 68,728 | 330,159 | 4,80 |
Быстрая сортировка с @CompileStatic | 67,752 | 147,792 | 2,18 |