Große datenmengen speichern und effizient zugreifen



  • Hi...

    Und zwar habe ich einen datensatz von ca 500.000 daten. Ein array dieser größe geht leider nicht (OutOfMemory).
    Jetzt stellt sich mir die frage, ob es eine andere möglichkeit gibt die mir auch die möglichkeit gibt über einen index sehr schnell einen wert zu finden... Das verwendete Array hätte ungefähr 500.000 zeilen und ca 5 spalten.

    Gibts da was schönes mit index-zugriff, oder muss ich mir da was mit Listen zurecht-pfuschen?

    Danke schon mal für Tipps!
    Sqwan



  • HashMap fällt mir spontan ein, weiß nicht ob das nicht auch Array-Probleme macht.

    Kannst du nicht einfach den Heap von Java größer werden lassen? Also der VM mehr Raum nach oben bieten?

    MfG SideWinder



  • Um wie viel MByte handelt es sich?



  • um wie viel MByte es sich handelt weiß ich nicht genau.
    ist ein Array von 500.000 x 3, wobei jede stelle ein Double ist.
    Mit Hashmaps habe ich noch nie gearbeitet. Lese ich mir jetzt mal durch...

    Kann man der VM von java denn zur laufzeit mehr speicher geben? Mein Prof will auf ein JAR doppel klicken und es soll laufen.

    Danke schon mal für die antworten!
    Sqwan



  • Ist dein Programm ansonsten schon recht groß?

    500.000 * 3 * 8 = 12000000 Byte = 11,44 MB sollten sich locker anlegen lassen. Es sei denn du bist in irgendeiner Embedded-Umgebung/Handy, aber das hier klingt mir eher nach Desktop (Doppelklick).

    Nein, zur Laufzeit geht das nicht. Starte mal in deinem JDK/bin-Ordner das JVisualVM-Programm und analysiere damit den Speicherverbrauch deines Programms...

    MfG SideWinder



  • Mein programm existiert so zur Zeit noch garnicht. Jedenfalls nicht mit der Fülle an daten.
    Ich habe gestern von meinem Prof zwei txt files bekommen von dieser größe.
    Wollt die dann in der console testweise einfach mal einlesen, und habe direkt nen OutOfMemoryError bekommen.
    Nun bin ich dabei das als liste zu realisieren.
    Den Speicherverbrauch kann ich gleich mal testen. Bin mit meiner Liste noch nicht ganz fertig.
    Seine Java VM stellt der Prof aber nicht um.

    Ein Handy ist es nicht. Am ende muss es auf dem MacBook meines Profs laufen...



  • Na, jetzt mal raus mit der Sprache, wieviele MB sind diese beiden Textdateien groß?

    Edit: Textdateien? Die Zahlen sind da drin als String? Quasi ala:

    34.34
    55.321
    1.0
    3.14
    

    ??

    MfG SideWinder



  • Die dateien sind 5 und 6 mb groß und sehen so aus:

    174952 5092.044434 6833.604492
    174953 3412.151123 4687.510254
    174954 5472.041504 7318.250488
    174955 3999.741943 5436.662598
    
    222996 1923 1930 4.472933
    222997 1915 1923 4.473317
    222998 2494 2500 5.606911
    222999 711 712 0.509093
    223000 743 745 1.433449
    

    kann man sich auch selber angucken.
    http://www.cs.fsu.edu/~lifeifei/research/tpq/SF.cnode
    http://www.cs.fsu.edu/~lifeifei/research/tpq/SF.cedge

    Sind in diesem fall nur 200K einträge, aber für 500K muss ich platz bieten...

    PS: Hab mal nen kleinen anfang gemacht.
    Da ich zwischen durch aber auch in der Vorlesung aufpassen muss komm ich nicht so schnell vorran...

    public class Edges {
    
    	private Node first = null;
    	private Node last = first;
    	private int nodeCount = 0;
    
    	public void add(int id, int startNode, int endNode, double l2D)
    	{
    		if(this.first == null)
    		{
    			this.first = new Node();
    			this.first.add(id,startNode,endNode,l2D);
    			this.last= this.first;
    			this.nodeCount++;
    		}
    		else
    		{
    			this.last.nextNode = new Node();
    			this.last = last.nextNode;
    			this.last.add(id,startNode,endNode,l2D);
    			this.nodeCount++;
    		}
    	}
    
    	class Node
    	{
    		private int id;
    		private Nodes startID;
    		private Nodes endID;
    		private int iStartNodeID;
    		private int iEndNodeID;
    		private double l2Distance;
    
    		public Node nextNode;
    
    		public void add(int id, int startNode, int endNode, double l2D)
    		{
    			this.id = id;
    			this.iStartNodeID = startNode;
    			this.iEndNodeID = endNode;
    			this.l2Distance = l2D;
    		}
    	}
    }
    


  • Interessant wär zu sehen wie du die Dateien einliest.



  • Ich finde ja grade alles interessant nur DAS nicht.
    Ich kann dir aber versichern das es geht. Ich kriege dann ein Sring array der größe 4 raus.
    Jedenfalls für die Edges...

    das programm JVisualVM-Programm gibt es bei mir weder im JDK/bin noch im JRE/bin
    16.748K sagt mir der taskmanager dazu.



  • a) Der Einlesemechanismus ist deswegen interessant weil vielleicht dort das Speicherproblem begründet liegt. Wenn das Einlesen funktioniert dann hast du die Daten ja schon in einer Datenstruktur und auch kein Speicherproblem.

    b) Welches JDK nutzt du denn? Hier findest du zu JVisualVM mehr Infos (evtl. auch Einzel-Download-Link): http://download.oracle.com/javase/6/docs/technotes/tools/share/jvisualvm.html

    c) String-Array der Größe 4? Weil deine Testdateien nur 4 Zeilen haben? Wie kann es mit den 4 Zeilen jemals jemals zu einem Speicherproblem kommen?

    MfG SideWinder



  • Der fehler tritt auf wenn ich sage:

    double werte = new double[500000][4];
    

    Dann kriege ich einen OutOfMemoryError.

    In der tat kann ich alle Zeilen einlesen. Allerdings nur in einer Liste speichern.
    Wie diese in etwa auzssieht habe ich ja schon gezeigt. Dann kriege ich auch keine probleme mehr.
    nur kann ich damit nicht über [x][y] zugreifen. Was ich halt schön gefunden hätte.
    Bzw eigentlich weniger schön, aber dafür einfach.

    Warum ein String array der größe 4?

    222996 1923 1930 4.472933
    222997 1915 1923 4.473317
    222998 2494 2500 5.606911
    222999 711 712 0.509093
    223000 743 745 1.433449
    

    Die Zeilen werden am Leerzeichen gesplittet. Übrig bleibt ein String array der größe 4.
    Eingetragen wird das dann in die vor kurtzen gepostete Edges-Klasse.

    Ähnliche klasse werde ich jetzt wohl für die Nodes erzeugen müssen.



  • Das ist direkt "strange", das Array sollte am Heap liegen und dort dementsprechend weniger Platz als andere Collections nutzen. Mit ArrayList klappt alles?

    Was passiert wenn du myList.toArray() aufrufst? Wieder OOM? Poste mal den genauen Fehler den die JVM wirft.

    MfG SideWinder



  • Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    	at Main.Navi.main(Navi.java:16)
    

    Das ist der genaue Fehler....

    public class Navi 
    {
    	public static void main(String args[])
    	{
    		double a[][] = new double[500000][4];
    	}
    }
    

    Sind noch ein paar kommentare drin. Und eine packageanweisung...
    Deshalb die 16. Das ist aber das was ausgeführt schon den fehler gibt.

    Ich benutze z.T. keine ArrayList...

    im mom nutze ich:

    public class Edges {
    
        private Node first = null;
        private Node last = first;
        private int nodeCount = 0;
    
        public void add(int id, int startNode, int endNode, double l2D)
        {
            if(this.first == null)
            {
                this.first = new Node();
                this.first.add(id,startNode,endNode,l2D);
                this.last= this.first;
                this.nodeCount++;
            }
            else
            {
                this.last.nextNode = new Node();
                this.last = last.nextNode;
                this.last.add(id,startNode,endNode,l2D);
                this.nodeCount++;
            }
        }
    
        class Node
        {
            private int id;
            private Nodes startID;
            private Nodes endID;
            private int iStartNodeID;
            private int iEndNodeID;
            private double l2Distance;
    
            public Node nextNode;
    
            public void add(int id, int startNode, int endNode, double l2D)
            {
                this.id = id;
                this.iStartNodeID = startNode;
                this.iEndNodeID = endNode;
                this.l2Distance = l2D;
            }
        }
    }
    


  • Füge mal folgenden Code direkt *vor* der Zeile ein die dann den Absturz bringt (quasi vor dem Array anlegen):

    import java.lang.management.ManagementFactory;
    import java.lang.management.MemoryMXBean;
    import java.lang.management.MemoryUsage;
    
    ...
    
    final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
    
    final MemoryUsage heap = memoryBean.getHeapMemoryUsage();
    final MemoryUsage nonHeap = memoryBean.getNonHeapMemoryUsage();
    
    final long heapMax = heap.getMax() / (1024 * 1024);
    final long heapUsed = heap.getUsed() / (1024 * 1024);
    final long heapFree = heapMax - heapUsed;
    
    final long nonHeapMax = nonHeap.getMax() / (1024 * 1024);
    final long nonHeapUsed = nonHeap.getUsed() / (1024 * 1024);
    final long nonHeapFree = nonHeapMax - nonHeapUsed;
    
    System.err.println("MEMORY USAGE: Heap (Used: " + heapUsed + "MB Free: " + heapFree + "MB Max: " + heapMax + "MB)");
    System.err.println("MEMORY USAGE: Non-Heap (Used: " + nonHeapUsed + "MB Free: " + nonHeapFree + "MB Max: " + nonHeapMax + "MB)");
    

    Und sag uns was als Ausgabe in der Konsole erscheint.

    Edit: Wenn ich ein Array wie deines anlege und diesen Code *danach* einfüge, erhalte ich folgende Ausgabe:

    MEMORY USAGE: Heap (Used: 31MB Free: 865MB Max: 896MB)
    MEMORY USAGE: Non-Heap (Used: 2MB Free: 130MB Max: 132MB)
    

    D.h. bei dir müsste Max irgendwo bei 32 MB dümpeln, das wäre *sehr* komisch.

    MfG SideWinder



  • Nochmal ich: Benutzt du überhaupt die Sun VM?? Vielleicht hast du ja irgendwas verrücktes wie OpenJDK im Programm?

    MfG SideWinder



  • So... bin jetzt zuhause. Kann also nicht nachvollziehen was in der FH eingetsellt ist.
    Integressanter weise funktioniert es auf meinem Heimrechner problemlos.
    Sogar mit 1.000.000 felder gehts zuhause. Selbst mein Laptop kann die 500.000

    Welche java VM ich nutze weiß ich nicht. Aber sie geht.
    In der FH haben wir iwas von IBM glaube ich.


Anmelden zum Antworten