Я не использовал 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 мои вычислительные функции выглядят так:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
@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:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
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 |