Статьи

Сравнение производительности Java 7 и Groovy 2.1

Я не использовал 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

Сравнение производительности