2017-02-07 9 views
0

ich auf Big O Notation eine Hausaufgabe tue. Wir müssen Listen mit immer größer werdender Anzahl von ganzen Zahlen erstellen und dann Zeit, wie lange es dauert, die Liste zu sortieren, um zu bestimmen, welches Big O Collection.sort() ist.Out of Memory: Java Heap-Speicher

Ich habe Code geschrieben, um dies zu tun und Daten darüber zu erzeugen, wie lange die Sortiermethode den Verlauf einiger Iterationen jeder Listengröße übernimmt.

Ich bin in der Lage, eine Liste von 50.000 ganzen Zahlen zu sortieren, aber wenn ich versuche, genau die gleiche Operation wieder zu tun, werde ich nicht mehr genügend Speicher haben. Ich denke, dass der Müllsammler mein Gedächtnis zurückfordern sollte, also sollte es in der Theorie kein Problem geben, die Operation zu wiederholen.

Ich habe über die Einstellung meiner großen Variablen auf null zu lesen, und keine Verweise auf meine große Listen außerhalb des für Loop-Block zu speichern. Ich denke, es gibt keinen Grund, irgendeinen Verweis auf meine Integer-Liste am Leben zu erhalten.

Was mache ich falsch, dass Garbage Collector mein Gedächtnis nicht zurückfordern kann?

 private static TreeMap<Integer, ArrayList<Long>> doExperiment(int iterations, int step, int trials, List listType) { 
    TreeMap<Integer, ArrayList<Long>> results = new TreeMap(); 
    for (int i = 1; i <= iterations; i++) { 
     // Data size ranges from 1000 - 50,0000 if step = 1000 and iterations = 50 
     int dataSize = i * step; 
     ArrayList<Long> trialResults = new ArrayList<Long>(); 
     for (int j = 1; j <= trials; j++) { 
      // This may be LinkedList, ArrayList depending on the parameter. 
      List thisList = listType; 
      // dataSize works up to 50,000 Integers. 
      Testing t = new Testing(dataSize, thisList); 
      long nanos = t.timedSort(); 
      // Prints a formatted string to standard output. 
      processResults(nanos, j, trials, i, iterations); 
      // The large list exists only within this Testing instance. Set it to null 
      t = null; 
      // Please, garbage collection Gods... 
      System.gc(); 
     } 
     results.put(dataSize, trialResults); 
    } 
    return results; 
} 
+0

Etwas über 'Testing t = ...' und dann 't = null', gefolgt von' System.gc() 'in einer Schleife scheint nicht richtig. Zuallererst garantiert 'System.gc()' keine sofortige Speicherbereinigung, zweitens möchten Sie GC nicht Hunderte von Malen hintereinander ausführen. Ich denke, was passiert ist, dass Sie immer noch mit vielen Instanzen von Testing enden, weil GC nicht sofort ausgeführt wird. Ich würde 'Testing t = null;' aus allen Schleifen verschieben, entfernen Sie 't = null' und' System.gc() '. – kooker

+0

Zeigen Sie uns den vollständigen Code. Was macht 'Testing'? Was macht 'processResults'? Warum benutzen Sie nicht 'trialResults'? Wie viele Iterationen? Sie erstellen 'Iterations'-Anzahl von ArrayLists. Was machen Sie mit dem Ergebnis der Funktion? – NickL

+0

Wenn Sie nur die Ausführung Ihrer Sortierung planen, warum geben Sie Ihre sortierten Listen zurück ??? Just Time it und speichern Sie nicht die Listen. –

Antwort

3

System.gc(); - keine Garantie für Garbage Collector

List thisList = listType; zu starten - Kopien Referenz (Ich denke, dieser Fehler ist) so, wenn Sie Testing t = new Testing(dataSize, thisList); tun - das ist eigentlich das gleiche wie Testing t = new Testing(dataSize, listType);

Sie wahrscheinlich möchte tun: List thisList = new ArrayList(listType); - Ja. Dadurch wird eine neue Liste erstellt, aber in diesem Fall wird beim Testen eine neue Liste ausgeführt, aber nicht dieselbe.

ArrayList<Long> trialResults = new ArrayList<Long>(); // you create new list 
.... 
results.put(dataSize, trialResults); // do you want to put empty list in the result? 
+0

Schöner Fang. Dies behebt das Problem! Der listType sollte nur erfassen, ob das Experiment mit ArrayList oder LinkedList durchgeführt werden soll. d.h. ich würde dort eine neue LinkedList() übergeben. Ich denke, ein besserer Ansatz ist es, einen String oder Boolean zu verwenden und stattdessen zu verwenden. –

+0

Und ja, ich wollte die Nanos zu trialResults hinzufügen! Danke nochmal –

+1

JMH - http://openjdk.java.net/projects/code-tools/jmh/ - nettes Tool für Benchmarks – iMysak

1
public static void main(String[] args) { 
     // TODO code application logic here 
     doExperiment(50000, 5, "ArrayList"); 
     doExperiment(50000, 5, "LinkedList"); 

    } 

    private static void doExperiment(int iterations, int trials, String listType) { 
     List list = null; 
     List<Long> holdStartTimes = new ArrayList(); 
     List<Long> holdEndTimes = new ArrayList(); 

     switch(listType) 
     { 
      case"ArrayList": 
       list = new ArrayList(); 
       break; 
      case "LinkedList": 
       list = new LinkedList(); 
       break;   
     } 

     for(int t = 0; t < trials; t++) 
     { 
      Random random = new Random(); 
      //create list with random ints 
      for(int i = 0; i < iterations; i++) 
      { 
       list.add(random.nextInt(50001));//random number in range from 0 to 50000 
      } 

      final long startTime = System.currentTimeMillis();//start Timer 
      holdStartTimes.add(startTime); 
      Collections.sort(list);//sort list 
      final long endTime = System.currentTimeMillis();//end Timer 
      holdEndTimes.add(endTime); 
     } 

     //sum times 
     long sum = 0; 
     for(int i = 0; i < holdStartTimes.size(); i++) 
     { 
      sum = sum + (holdEndTimes.get(i) - holdStartTimes.get(i)); 
     } 

     System.out.println("Sorting " + listType + " with " + iterations + " iterations and " + trials + " trials takes " + sum + " milliseconds."); 
    }