2015-04-30 5 views
10

Я пришел в эту проблему сегодня, и я не мог понять, почему массивный массив не масштабируется лучше, чем Map, когда он становится больше.Почему карта Groovy масштабируется лучше, чем Array?

В моем примере я создаю карту (LinkedHashMap) и массив String (String []). Затем я повторяю от 0 до 10^7, вставляя i в Map или Array. Я делаю это 10 раз, чтобы быть уверенным, что выбросы не испортили результаты.

int max = 10**7 
int numTests = 10 

long totalTimeMap = 0 
long totalTimeArray = 0 

numTests.times{ 
    long start = System.currentTimeMillis() 

    Map m = [:] 
    max.times { 
     m[it] = "${it}" 
    } 

    long end = System.currentTimeMillis() 
    totalTimeMap += (end-start) 
} 

numTests.times { 
    long start = System.currentTimeMillis() 

    String[] s = new String[max] 
    max.times{ 
     s[it] = "${it}" 
    } 

    long end = System.currentTimeMillis() 
    totalTimeArray += (end-start) 
} 

println "Map: ${totalTimeMap}" 
println "Array: ${totalTimeArray}" 

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

Map: 49361 
Array: 101123 

я сделал тот же самый эксперимент в Java:

public static void main(String[] args) { 

     int max = 10000000; 
     int numTests = 10; 

     long totalTimeMap = 0; 
     long totalTimeArray = 0; 

     for(int i=0; i<numTests; i++){ 
      long start = System.currentTimeMillis(); 

      Map m = new LinkedHashMap(); 
      for(int j=0; j<max; j++){ 
       m.put(j, "" + j); 
      } 

      long end = System.currentTimeMillis(); 
      totalTimeMap += (end-start); 
     } 

     for(int i=0; i<numTests; i++){ 
      long start = System.currentTimeMillis(); 

      String[] s = new String[max]; 
      for(int j=0; j<max; j++){ 
       s[j] = "" + j; 
      } 

      long end = System.currentTimeMillis(); 
      totalTimeArray += (end-start); 
     } 

     System.out.println("Map: " + totalTimeMap); 
     System.out.println("Array: " + totalTimeArray); 
    } 

и выход ожидался (Array быстрее, чем Карта):

Map: 34564 
Array: 12822 

Мой вопрос: почему Карта работает быстрее, чем Массив при использовании Groovy?

+1

И это согласовано между несколькими казнями? Просто быть педантичным. – christopher

+0

да есть. Вы можете установить max до 10^6 или 10^5, чтобы пример работал быстрее. – lfrodrigues

+2

Также убедитесь, что это массив; Groovy '[]' обычно создает список, 'ArrayList', который будет изменять размер штрафов. –

ответ

20

При добавлении строки в массив в Groovy, вы создаете шаблонный String, который затем получить преобразуется обратно в строку Java (после того, как шаблонный делается), как она должна вписываться в String[]

для версии Map, вы просто хранить шаблонного строку, поэтому никакой оценки не должно быть сделано ...

следующий код бенчмаркинг:

@Grab('org.gperfutils:gbench:0.4.3-groovy-2.4') 

int max = 10000 

new groovyx.gbench.BenchmarkBuilder().run { 
    'Array' { 
     String[] s = new String[max] 
     max.times { int idx -> 
      s[idx] = Integer.toString(idx) 
     } 
    } 
    'List' { 
     def s = [] 
     max.times{ 
      s << "${it}" 
     } 
    } 
    'Map' { 
     Map m = [:] 
     max.times { 
      m[it] = "${it}" 
     } 
    } 
}.prettyPrint() 

Где мы не используем GroovyStrings в e Метод массива дает мне результат:

* Groovy: 2.4.3 
* JVM: Java HotSpot(TM) 64-Bit Server VM (25.45-b02, Oracle Corporation) 
    * JRE: 1.8.0_45 
    * Total Memory: 800.5 MB 
    * Maximum Memory: 1820.5 MB 
* OS: Mac OS X (10.10.3, x86_64) 

Options 
======= 
* Warm Up: Auto (- 60 sec) 
* CPU Time Measurement: On 

      user system  cpu  real 

Array 1819502 6491 1825993 1833209 
List 1697948 6533 1704481 1724448 
Map 2040521 8932 2049453 2116760 
+1

Bravo! Карта: 38225 Array: 34171. Спасибо! – lfrodrigues

+6

Я неправильно читаю 'gperfutils' как' grapefrutils'. – Will

+0

Lol, оба потрясающие, один для профилирования, другой для завтрака ;-) –

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