Почему GPars runForkJoin работает медленно, даже если нет forkOffChild()?

Это последовательная версия:

void f(long n) {
   for (int i=1; i<n-1; i++) {
      // do nothing     
   }
}

List result = []
(1..99999).each {
   f(it)
   result << it
}

Выполнение кода занимает несколько секунд.

void f(long n) {
   for (int i=1; i<n-1; i++) {
      // do nothing
   }
}

withPool {
   runForkJoin(1,99999) { a, b ->
      List result = []
      (a..b).each {
         f(it)
         result << it
      }
      return result
   }
}

Код выше занимает несколько минут. Я еще не звонил ни forkOffChild(), ни childrenResults(). Я запускаю этот код в Windows и одноядерном процессоре с Intel Hyperthreading (2 логических процессора). Java Runtime.runtime.availableProcessors() возвращает 2.

Я не понимаю, почему код, который использует runForkJoin, намного медленнее, чем последовательный код (минуты против секунд).


person David Bower    schedule 17.05.2014    source источник


Ответы (1)


Метод runForJoin() не влияет на производительность фрагмента кода. Именно метод withPool() вызывает замедление. Это связано с тем, что метод withPool() добавляет несколько методов xxxParallel() в динамическую область Groovy Object, что затем замедляет разрешение метода.

Аннотирование метода f() как @CompileStatic даст вам ожидаемую производительность.

person Vaclav Pech    schedule 18.05.2014
comment
Добавление @CompileStatic действительно дало мне ожидаемую производительность. Спасибо, это решает мою проблему. Немного любопытна проблема: я сомневаюсь, что это разрешение метода, дублирование содержимого метода внутри закрытия withPool все равно приводит к значительному замедлению. - person David Bower; 18.05.2014