2015-04-30 19 views
10

Wpadłem dziś na ten problem i nie mogłem się domyślić, dlaczego tablica groovy nie skaluje się lepiej niż mapa, gdy staje się większa.Dlaczego Mapa Groovy jest lepsza niż Array?

W moim przykładzie tworzę mapę (LinkedHashMap) i tablicę ciągów (String []). Następnie powtarzam od 0 do 10^7 wstawiania i do mapy lub tablicy. Robię to 10 razy, aby mieć pewność, że wartości odstające nie zepsują wyników.

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}" 

Wyjście było nieoczekiwane, ponieważ mapa miał lepszą wydajność potem tablicy:

Map: 49361 
Array: 101123 

zrobiłem ten sam eksperyment w 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); 
    } 

i było oczekiwane wyjście (Array szybciej niż na mapie):

Map: 34564 
Array: 12822 

Moje pytanie brzmi: dlaczego mapa jest szybsza niż tablica podczas używania Groovy?

+1

Czy jest to spójne w przypadku wielu egzekucji? Po prostu pedantyczny. – christopher

+0

tak, to jest. Możesz ustawić maks. 10^6 lub 10^5, aby przykład działał szybciej. – lfrodrigues

+2

Upewnij się również, że jest to tablica; Groovy '[]' zwykle tworzy listę, 'ArrayList', która zmieni rozmiar kar. –

Odpowiedz

20

Podczas dodawania tekstu do tablicy w Groovy, podczas tworzenia matrycy String, który następnie przekształca się coraz powrotem na ciąg Java (po wzorcowe są zrobione), ponieważ musi zmieścić się w String[]

dla wersji Map, jesteś po prostu przechowywania matrycy ciąg, więc żadna ocena musi być zrobione ...

Poniższy kod benchmarking:

@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() 

Jeżeli nie używamy GroovyStrings w tys Metoda e-Array daje mi wynik:

* 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! Mapa: 38225 Array: 34171. Dzięki! – lfrodrigues

+6

źle odczytałem 'gperfutils' jako' grapefrutils'. – Will

+0

Lol, oba są niesamowite, jeden do profilowania, drugi do śniadania ;-) –

Powiązane problemy