2014-02-09 3 views
1

Возможно ли, что у Groovy нет автоматической коробки каждый раз в моем приложении?Groovy очень медленный на примитивах

Следующий код ...

public class SumTest { 
    public static void main(String[] args) { 
     long[] longs = new long[100000000]; 

     long nanoStart = System.nanoTime(); 
     long counter = 1; 
     for (int i = 0; i < longs.length; i++) { 
      longs[i] = counter++; 
     } 

     double msPop = (System.nanoTime() - nanoStart)/1000000d; 
     System.out.println("Time taken, population: " + msPop + "ms."); 

     nanoStart = System.nanoTime(); 
     long sum = 0; 
     for (int i = 0; i < longs.length; i++) { 
      sum += longs[i]; 
     } 
     double msSum = (System.nanoTime() - nanoStart)/1000000d; 
     System.out.println("Time taken, sum: " + msSum + "ms, total: " + (msPop + msSum) + "ms"); 
     System.out.println(" (sum: " + sum + ")"); 
    } 
} 

... Экспонаты совершенно разные времена, когда пробег переименована в '.groovy' от '.java':

Java:

Time taken, population: 94.793746ms. 
Time taken, sum: 65.172605ms, total: 159.966351ms 
(sum: 5000000050000000) 

Groovy:

Time taken, population: 2233.995965ms. 
Time taken, sum: 2203.64302ms, total: 4437.638985ms 
(sum: 5000000050000000) 

.., что составляет 30 раз.

Ситуация усугубляется когда я придерживаюсь долго внутри объекта (как это происходит в моем реальном коде):

public class SumTest { 
    static class Holder { 
     long l; 
     Holder(long l) { this.l = l; } 
     long getL() { return l; } 
    } 

    public static void main(String[] args) { 
     Holder[] longs = new Holder[100000000]; 

     long nanoStart = System.nanoTime(); 
     long counter = 1; 
     for (int i = 0; i < longs.length; i++) { 
      longs[i] = new Holder(counter++); 
     } 

     double msPop = (System.nanoTime() - nanoStart)/1000000d; 
     System.out.println("Time taken, population: " + msPop + "ms."); 

     nanoStart = System.nanoTime(); 
     long sum = 0; 
     for (int i = 0; i < longs.length; i++) { 
      sum += longs[i].getL(); 
     } 
     double msSum = (System.nanoTime() - nanoStart)/1000000d; 
     System.out.println("Time taken, sum: " + msSum + "ms, total: " + (msPop + msSum) + "ms"); 
     System.out.println(" (sum: " + sum + ")"); 
    } 
} 

Run раз (обратите внимание, что я бегу с -Xms16384M -Xmx16384M здесь) :

Java

Time taken, population: 1083.784927ms. 
Time taken, sum: 180.518991ms, total: 1264.3039179999998ms 
(sum: 5000000050000000) 

Groovy:

Time taken, population: 9816.007447ms. 
Time taken, sum: 8685.506864ms, total: 18501.514311ms 
(sum: 5000000050000000) 

.. который на общей сложности ~ в 15 раз быстрее, , но самое важное отличие заключается в фактическом использовании этого объекта (представленном суммированием): ~ 50x.

Можно ли это как-то исправить? Могу ли я уговорить Groovy не автоблокировать каждую операцию с примитивами, когда только операции касается примитивов и примитивных операций? (Странно Ого, как тщательно формулируя вопрос почти мгновенно приводит к ответу ?!!)

ответ

2

Fix: Написать @CompileStatic на верхней части класса.

Time taken, population: 1562.978726ms. 
Time taken, sum: 183.388353ms, total: 1746.367079ms 
(sum: 5000000050000000) 
+1

'@ CompileStatic' будет делать то, что вы хотите, но это также делает немного больше. Это означает, что вы полностью обходите все динамические черты groovy. Во многих случаях это может привести к увеличению производительности. Однако есть много особенностей языка, которые полагаются на динамические методы и свойства, и не будут работать с @CompileStatic. Просто FYI. – allTwentyQuestions

Смежные вопросы