# String nicht im String literal pool speichern - Parser



## vimar (24. Apr 2012)

Hallo,

aus performancegründen (ca 18 Mio String Objekte zur laufzeit) will ich verhindern dass so gut wie alle Strings im String literal pool sind damit System.gc() den kram auch mal löscht und nicht meinen ram zumüllt mit strings die ich nicht mehr brauche (so gut wie alle). ich muss sehr viele textfiles parsen und kriege dadurch viele stringobjekte, aber ansich sind es nur zahlen die ich in einer arraylist speichere.

ich weiss auch dass es ansich sinnvoll ist den String literal pool zu nutzen(wegen den referenzen ansich weniger speicher bei stringobjekten mit selbem content) aber scheinbar läuft das nicht so wie ich will.

kann ich explizit sagen dass ich einen String NICHT in dem pool haben will? 

ich erzeuge pro textfile immer eine parserinstanz, die line für line die zahlen ausliest und in einer globalen arraylist<integer> speichert. (derzeit mit strToKenizer, schreibe gerade auf scanner kram um)

FRAGE:
jemand eine konkrete idee (vllt codeschnipsel/pseudocode) wie ich eine textfile auslese, die werte NICHT als string zwischenspeichern muss und die auch intern nicht in den string literal pool kommen weil ich brauch die werte einfach nur in einer arraylist<integer> und garnicht als string.


vielen dank für jegliche hilfe im vorraus!


----------



## nillehammer (24. Apr 2012)

Wie der Name schon sagt, landen im String *literal* pool nur String-Literale. Das ist ein Konstrukt, dass bereits zur Compilezeit erkannt wird so wie das hier:

```
String literal = "aLiteralString";
```
Ein String, den Du mit einem Reader einliest landet nicht im pool. Hier gibt es eine ganz gute Erklärung zum Thema: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html


----------



## vimar (24. Apr 2012)

Danke ich hab mir das eben durchgelesen.


```
for (String[] line; (line = in.readLine().split("\\s")) != null;){
```

meiner meinung nach erzeugt der kopf dieser vorschleife doch durchaus enorm viele strings in diesem Stringarray. werden die wohl nun auch alle im stringpool gespeichert oder? selbst wenn ich dann die instanz = null setzte in der diese forschleife ist, so ist ja dennoch eine referenz vorhanden auf den heap von dem string pool.

und wenn ich 

```
for (String line; line = in.readLine() != null;){
```
mache dann müsste doch wegen "String line" auch jede einzelne zeile der textfile im stringpool landen. und wenn ich dann noch anschliessend den string splitte, dann hätte ich doch alle substrings auch noch im pool und insgesamt werden die doch einfach nicht gelöscht.



ich meine ich müsste doch dann logischerweise irgendwie sowas schreiben:


```
while (in.readLine() != null){

// genau diese aktuelle zeile die ich jetzt nicht als string zwischenspeicher irgendwie splitten und in //meine arraylist<integer> packen
}
```

ich begreife gerade dann nicht wie ich in.readLine() in der while benutze wenn ich keinen String auf die line verweise? soll ich zunächst die zeilen zählen? also ne while schleife while != null zeileCount++ und dann wieder an den anfang der datei springen und mit ner forschleife (x=0; x < zeileCount; x++) dann dort einfach in.readLine().split usw? 

plz help -.-


----------



## vimar (24. Apr 2012)

Wird nicht hier jede "line" in den pool getan? (zeile 7) :


```
for (int m =0; m < 3; m++){

         vcount = 0;
         while (vcount < 7){
          vcount++;

          line = in.readLine().split("\\D");
           for (int x=1; x<line.length; x++){ // 0 = ""
                 kPoint.getList().add(Integer.valueOf(line[x]));
            }
  
                          }
                            AAO_kPointList.add(kPoint.getList());
                            
  
}
```


----------



## Volvagia (24. Apr 2012)

Nein. readLine benutzt einen StringBuffer:


```
public synchronized String toString() {
	return new String(value, 0, count);
}
```

String.split benutzt einen Pattern der wiederrum subSequence benutzt:


```
public String substring(int beginIndex, int endIndex) {
	if (beginIndex < 0) {
		throw new StringIndexOutOfBoundsException(beginIndex);
	}
	if (endIndex > count) {
		throw new StringIndexOutOfBoundsException(endIndex);
	}
	if (beginIndex > endIndex) {
		throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
	}
	return ((beginIndex == 0) && (endIndex == count)) ? this :
	    new String(offset + beginIndex, endIndex - beginIndex, value);
    }
```


----------



## SlaterB (24. Apr 2012)

Code wie deinen verwendet jeder und nichts davon landet im Pool normalerweise,
Speicherprobleme erhälst du vielleicht, wenn du selber die Strings irgendwo merkst

im folgenden Testprogramm gibt es bei mir mit Standard-Speicher einen OutOfMemoryError bei cache nach 700.000,
der hier unsauber abgefangen wird, ohne cache läuft es  es bis 2 Mio. durch


```
public class Test {
    public static void main(final String[] args) {
        try   {
            test(true);
        }    catch (Throwable t)  {
            System.out.println(t.toString());
        }
        test(false);
    }

    static void test(boolean cache)  {
        List l = new ArrayList();
        for (int i = 0; i < 2000000; i++)    {
            String st = "hallo String " + i;
            if (cache)   {
                l.add(st);
            }
            if (i % 100000 == 0)  {
                System.out.println("i: " + i);
            }
        }
    }
}
```


----------



## vimar (24. Apr 2012)

Also falls jemand den "fehler" sieht, genau diese klasse haut mir den heap voll mit 18 Mio String Objekten. Sieht irgendjemand den fehler?

von dieser klasse werden aktuell ca 350 instanzen erstellt. 


```
import SIFT.siftKeyPoint;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import SIFT.siftKeyPoint;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author vimar
 */
public class csiftparser {

    String filename;
    int vcount;
    String firstline;
    String temp;
    FileReader fr;
    LineNumberReader in;
    ArrayList<ArrayList<Integer>> AAO_kPointList;
    siftKeyPoint kPoint;
    double akt_X;
    double akt_Y;
    double akt_Scale;
    double akt_Orientation;

    public csiftparser(String filename) throws InterruptedException {

        this.filename = filename;

        AAO_kPointList = new ArrayList<ArrayList<Integer>>();

        try {
            in = new LineNumberReader(fr = new FileReader(filename));

            vcount = 0;

            in.readLine(); // skip first line cause noneed

            for (String[] line; (line = in.readLine().split("\\s")) != null;) {

                akt_X = Double.parseDouble(line[0]);
                akt_Y = Double.parseDouble(line[1]);
                akt_Scale = Double.parseDouble(line[2]);
                akt_Orientation = Double.parseDouble(line[3]);

                for (int m = 0; m < 3; m++) {
                    kPoint = new siftKeyPoint();
                    kPoint.setX(akt_X);
                    kPoint.setY(akt_Y);
                    kPoint.setScale(akt_Scale);
                    kPoint.setOrientation(akt_Orientation);

                    vcount = 0;
                    while (vcount < 7) {
                        vcount++;
                        line = in.readLine().split("\\D"); // vllt die ursache string pool?

                        for (int x = 1; x < line.length; x++) { // 0 = ""
                            kPoint.getList().add(Integer.valueOf(line[x]));

                        }

                    }
                    AAO_kPointList.add(kPoint.getList());

                }

            }

        } catch (NullPointerException e) {
            System.out.println("Fertig mit Datei");
            System.out.println(filename + "Fertig bearbeitet!");
        } catch (IOException ex) {
            Logger.getLogger(csiftparser.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (fr != null) {
                try {
                    System.out.println("allet weg");
                    fr.close();
                    in.close();

                    //System.gc();

                } catch (IOException e) {
                }
            }
        }

    }

    public synchronized ArrayList<ArrayList<Integer>> getKeyPointList() {

        //return KeyPointList;
        return AAO_kPointList;
    }
}
```

als input habe ich solche files: 

372 128 3
277.65 513.45 55.57 1.032
 42 141 67 3 0 0 0 0 62 47 13 14 26 54 12 12 0 0 2 8
 98 104 7 0 0 1 4 5 15 7 0 0 134 101 19 0 0 0 10 55
 141 73 4 1 7 54 57 87 11 6 7 13 141 141 61 19 0 2 21 23
 95 31 0 0 57 11 3 0 0 0 5 18 141 141 80 3 4 6 5 28
 9 54 49 13 117 65 5 4 0 0 2 5 35 8 0 0 0 2 2 0
 0 0 0 0 1 22 16 0 0 0 0 0 0 3 1 0 0 0 0 0
 0 0 0 0 0 0 0 0
 31 49 22 121 94 17 4 16 8 7 21 81 51 22 15 7 169 83 4 6
 4 15 13 15 47 26 0 0 0 0 0 0 4 0 0 66 154 53 10 14
 74 1 0 19 67 37 48 130 101 37 0 0 0 89 131 57 82 44 0 0
 0 0 12 15 3 0 1 42 15 0 12 57 57 0 0 10 7 5 56 227
 14 0 0 0 0 28 66 29 7 0 0 0 0 0 10 6 0 0 0 0
 0 0 5 8 0 0 0 0 0 0 23 20 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 113 29 7 20 33 29 8 80 59 34 15 5 6 6 10 66 5 20 10 12
 160 83 2 4 0 0 0 0 49 25 0 0 170 83 20 16 2 0 0 72
 82 51 45 120 44 1 0 19 0 95 114 49 100 32 0 0 0 1 9 11
 87 43 0 0 19 0 22 56 0 0 0 48 11 13 110 223 12 0 0 12
 0 34 68 26 4 0 0 0 0 1 7 5 8 0 0 0 0 0 6 8
 0 0 0 0 0 3 30 17 0 0 0 0 0 0 1 0 0 0 0 0
 0 0 0 0 0 0 0 0
448.92 204.94 25.59 2.843
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 7 1 0 0 22 0 0 0 4 2 2 34 9 0 0 0 38 68 2 2
 126 35 0 0 6 20 4 11 59 11 0 1 71 29 12 18 71 5 3 0
 20 14 23 126 9 5 24 16 98 126 47 14 126 11 0 0 7 75 126 126
 84 8 0 0 12 40 87 57 58 49 14 2 1 16 19 76 26 10 34 11
 6 19 113 110 16 8 26 22 11 20 126 126 28 33 19 5 8 50 96 30
 28 7 0 0 9 54 32 71
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3
 13 0 0 0 5 0 0 3 11 0 0 2 11 13 1 6 24 8 0 0
 3 11 8 11 35 26 14 3 0 5 11 59 117 50 30 1 10 0 0 17
 67 29 72 92 36 81 64 77 25 4 0 0 4 81 54 97 40 17 18 4
 8 78 55 5 14 70 98 9 15 49 12 0 4 31 211 140 10 65 89 26
 2 0 1 6 2 55 41 42 9 0 0 0 4 96 106 10 0 0 0 1
 46 194 64 0 0 0 6 12
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 0 0
 0 0 0 3 15 1 0 4 4 0 0 1 34 11 0 0 15 18 3 8
 53 41 22 2 3 8 8 13 101 55 35 0 0 4 11 58 70 36 88 72
 4 0 0 8 35 6 0 0 48 95 82 104 57 28 27 3 2 85 67 128
 10 79 94 5 4 67 71 7 3 31 198 84 6 39 22 0 2 0 0 5
 10 61 109 38 7 0 0 0 0 55 54 54 0 0 0 0 1 77 133 9
 0 0 5 5 27 139 84 0


----------



## fastjack (24. Apr 2012)

Nein, die landen auf dem Heap. Wenn ein "line" Objekt nicht mehr benutzt wird, wird es irgendwann, whl. nach einem Schleifendurchlauf bei dir,  vom GC abgeräumt.
Dein Problem sind die 18 Mio Zeilen, die dann auch irgendwann in die Listen wandern. Versuch doch mal häppchenweise die Daten zu verarbeiten, also immer 1000, 10000 oder so...


----------



## SlaterB (24. Apr 2012)

gibt es schon einen OutOfMemoryError?
wenn nicht, dann reicht doch der Speicher, wann die nicht benötigten Strings aufgeräumt werden kann Java selber entscheiden,
notfalls erst dann wenn Platz gebraucht wird, 
solange du zu 100% die CPU mit deiner Schleife usw. belastest ist es ja nicht unbedingt nötig, diese Arbeit für evtl. unwichtige Aufräumarbeiten, die auch später noch in Pausen passieren können, zu unterbrechen


----------



## vimar (24. Apr 2012)

es gibt keinen outofmemory derzeit weil ich die trainingsmenge verringern musste genua damit ich keinen outofmemory bekomme + musste extra ram kaufen gehen damit ich überhaupt was machen kann.....







aber wenn ich meine richtige trainigsmenge benutzen will bräuchte ich an die 12-13 GB ram und mein mainboard unterstützt garnicht soviel ram.

deswegen muss ich das unbedingt lösen -.-.-.- ich les nochmal was ihr allegeschrieben habt -.-


hier von visualvm:


----------



## SlaterB (24. Apr 2012)

die Object[] kommen sicherlich von den vielen ArrayLists, machen in dem Screenshot einen bedeutenden Anteil aus,
viel mehr als die Strings,

die ArrayLists gehen auch nicht weg da du sie ja merkst, wie schließt du aus dass die das Problem sind?

Integer sind nur relativ wenige, da die zum Glück bei Integer.valueOf() gecacht werden bis 128,
verwende testweise new Integer(), dann dürfte sich dein Speicher-Bild nochmal kräftig verändern,

falls du auch größere Zahlen hast, aber dennoch nur 1000 verschiedene, wäre ein eigener Cache ein Speicher-Wunder, 
zumindest die 80 MB aktuell ließen sich noch zu 99% drücken

-------

was man da sonst optimieren kann ist vorerst nicht so leich zu sehen,
mit einfachen int[] wärst du sicher besser dran wie auch immer du das irgendwo einbauen kannst,

nicht zig Millionen bis Milliarden Daten gleichzeitig im Speicher zu halten ist der schon genannte Standardtipp,
wozu braucht du sie, kannst du sie nicht direkt bei der Berechnung laden?


----------



## fastjack (24. Apr 2012)

Starte mal das Programm mit GC-Ausgaben. Ich würde auch mal nach XXX-Läufen die GC selber mal triggern (System.gc()) und dann mal einfach schaun, was passiert. Ob überhaupt was da ist zum abräumen und so...


----------



## vimar (24. Apr 2012)

fastjack hat gesagt.:


> Starte mal das Programm mit GC-Ausgaben. Ich würde auch mal nach XXX-Läufen die GC selber mal triggern (System.gc()) und dann mal einfach schaun, was passiert. Ob überhaupt was da ist zum abräumen und so...



ich habe das gerade mal gemacht vielen dank! :


```
filecount++;
       if(filecount%5 == 0){
        System.gc();
           System.out.println("aufgeräumt -.-");
        }
```


hab somit halbwegs den speed von voher und das ganze String gedöns verschwindet auch   

vielen dank nochmal an alle!


----------



## Gast2 (24. Apr 2012)

```
System.gc();
           System.out.println("aufgeräumt -.-");
```
Der System.gc() Aufruf stellt nicht sicher dass die JVM tatsächlich den GC gestartet hat, das ist lediglich ne bitte. Selbst wenn dann Speicher freigemacht wird würde ich den Aufruf trotzdem rausnehmen. Die JVM startet den GC schon wenns mal eng wird mitm Speicher.


----------



## vimar (24. Apr 2012)

eike ich habe von dieser theorie gehört und ich kann nur im selbsttest feststellen: es mag allgemein sein, aber scheinbar kriegt die vm es nicht gebacken bei 18 Mio Strings. ich bin auch deiner meinung aber der selbe umfang an inout ohne selbstständiges aufrufen von system.gc() endet mit einem outofmemory error. jedesmal wenn der heap voll ist seh ich im output auch wegen der latenz dass der gc versucht aufzuräumen - schafft es auch - aber irgendwie schaufelt der dann nur ca 300 MB frei. nach dem motto:
schaufel 300 mb frei, lade alles voll, schaufel 300MBfrei, lade alles voll, lade zuviel -> heapsizeerror.
es werden nicht die gesamten stringobjekte gelöscht die gelöscht werden sollten.

durch den manuellen aufruf löscht der jedenfalls derzeit wenigstens konsequent immer diese 300-500MB die überhaupt anfallen und es kommt niemals zu dieser 18 Mio Stringobjekte ansammlung.

in der theorie stimme ich dir vollkommen zu. allerdings sehe ich in der praxis dass der gc nur mist macht wenn man den nicht "bittet".


----------



## SlaterB (24. Apr 2012)

du schaffst also eine Exception zu bekommen, die nur durch gc()-Aufruf dann weg geht?
interessante Info, hat mich schon länger interessiert, aber hier im Forum war glaube ich (länger) kein Beispiel zu sehen,

deins ist freilich für andere auch nicht nachprüfbar, aber immerhin eine Aussage


----------



## vimar (24. Apr 2012)

slaterB ich bin kein java-experte wie ihr alle. ich kann nur aus den praxisbeispiel sagen was ich sehe.

ich sehe einen gc der sich nicht die mühe macht wenn der heap voll ist, einfach mal richtig zu schauen, sondern einfach nur "ein bissl" freimacht und auf gutes wetter hofft. und effektiv erscheint mir das auch nicht, 6 GB vollzuschaufeln, davon 3 GB StringObjekte die keiner mehr braucht, und gc macht mal nur schnell 300MB frei die dann im nächsten durchlauf sowieso wieder voll sind wodurch der gc mehr oder weniger sich sowieso aufrufen muss ohne ende.

durch einen System.gc() in den pausen (in meinem fall vor der erstellung der nächsten parserinstanz bzw mod 5 -> nach 5 parserinstanzen) schaufelt system.gc() halt seine was weiss ich 300-500MB frei die er sonst scheinbar auch nur hinkriegt. vllt kann man aber den "grad der freischauflung" irgendwie über diese vm optionen freeratio oder so bestimmen ich weiss es nicht bin dafür einfach zu wenig bewandert in java.


nach der theorie über System.gc() "bitte ich" dass System.gc() überhaupt passiert und es gäbe wohl keine garantie. kann es sein dass sich hier was geändert hat in java 7? nach visualvm ignoriert er NIE meine "Bitte".

Java HotSpot VM Options

-XX:MaxHeapFreeRatio=70 	Maximum percentage of heap free after GC to avoid shrinking.
-XX:MinHeapFreeRatio=40 	Minimum percentage of heap free after GC to avoid expansion.

die beiden hatte ich drin, aber hat scheinbar nix genutzt!


----------



## maki (24. Apr 2012)

*hier stand blödsinn  *


----------



## vimar (24. Apr 2012)

Hier steht nochmal genau warum eine OutofMemory Exception kommt!:

5.2.3 Out-of-Memory Exceptions

The throughput collector will throw an out-of-memory exception if too much time is being spent doing garbage collection. For example, if the JVM is spending more than 98% of the total time doing garbage collection and is recovering less than 2% of the heap, it will throw an out-of-memory expection. The implementation of this feature has changed in 1.5. The policy is the same but there may be slight differences in behavior due to the new implementation.


also ziemlich logisch, bei 18 Mio StringObjekten braucht der GC scheinbar zu lange UM alles zu löschen, er würde es schaffen aber weil er da zu lange braucht kommt ein outofmemory exception

nur wens interessiert


----------



## fastjack (24. Apr 2012)

@vimar Dein Beispiel ist schon richtig

Whl. wird der Speicher so schnell voll, daß die GC gar nicht mehr zum Zug kommt. Das man sich nicht darauf verlassen soll, daß die GC auch manuell ausgeführt wird ist schon klar, allerdings wird sie bei den meisten Implementierungen auch ausgeführt (Oracle selbst als Beispiel, auch OpenJDK), wenn man sie manuell triggert  Das ist seit mindestens Java 1.4 so der Fall.


----------



## Spacerat (24. Apr 2012)

Waaaahhhh soviel Thread, wegen ein paar Zahlen, die man aus Textdateien filtern will?
Sieh' mal hier.  Fast ohne Strings!
http://www.java-forum.org/java-basi...-nummern-text-string-bekommen.html#post809206

Oder nimm die RegEx-Methode, die dort vorgeschlagen wird... Obwohl, die belastet den Pool auch noch ein wenig.


----------



## SlaterB (24. Apr 2012)

nur weil das in einer Klasse StreamTokenizer steht, muss da nicht heißen, dass dort nicht intern auch ne Menge Strings anfallen,
stimmt aber wohl, sieht effizienter aus,
selber hätte man dann auch mit chars rechnen können


----------



## Spacerat (24. Apr 2012)

Natürlich verwendet der StreamTokenizer auch Strings aber für Zahlen halt double. Und mit [c]tokenizer.ordinaryChars(0, 255); tokenizer.parseNumbers();[/c] ist's mit der String-Erzeugung vollkommen vorbei und man bekommt nur noch Zahlen. Diese müssen nur noch in ints gewandelt werden und per Autoboxing in die List<Integer> eingefügt werden.
Und wenn man noch einen Draufsetzen will, speichert man die ints nicht in einer List<Integer> sondern in einem java.nio.IntBuffer mit dem Attribut direct. Da muss man allerdings aufpassen, wann man ihn vergrössern muss, weil diese Buffer sind leider nicht dynamisch.


----------



## irgendjemand (24. Apr 2012)

ich beziehe mich mal auf das bereits gesagte : ist es sinnvoll so viele daten GLEICHZEITIG im RAM zu haben ...
ich beziehe mich jetzt hierbei nur mal auf die geparseten listen ...

vielleicht mal ein "standard" beispiel um zu zeigen das es eigentlich sinnlos ist selbst so viele geparsete daten im RAM zu haben

wenn man mit 4 Threads arbeitet kann ein 4kern-cpu 4 berechnung zeitgleich ausführen ...
wenn man mit 8 Threads arbeitet kann ein 2kern-cpu trotzdem nur 2 berechnung gleichzeitig ausführen

ich denke hier sieht man schon : um den sinn hinter deiner daten-haltung zu begründen müsstest du alles gleichzeitig machen : daten einlesen , prasen , weiterverarbeiten *was auch immer du damit vorhast* ergebnisse wieder rausschreiben ... und was nicht noch ...
damit sich das dann bei der datenmenge auch überhaupt lohnt bräuchtest du schon ein paar dutzent cpu-cores die alle relativ hoch getaktet sind , extrem viel und schnellen RAM und vor allem auch gute anbindung an daten-quelle und -ziel *in der regel platten ... *die ausrede : übers netz ... zählt hier nicht da schließlich auch der server und vor allem das netz selbst mit dieser datenflut klarkommen müssten*


daraus kann man ableiten : wenn du jetzt jedes file einzeln einliest ... und das auch nur zeile für zeile ... und dann auch immer nur eine zeile gleichzeitig parset ... warum musst du dann zig millionen datensätze im RAM speichern ? verarbeite die daten doch dierekt nach dem einlesen *soweit möglich* und schreibe die ergebnisse wieder raus auf platte in ein file ...

mit dieser methode könnte man sogar mir standard-VM *glaube 64MB oder was das waren ?* die aufgabe bewältigen ... und das auch gar nicht mal so viel langsamer als mit der methode die du atm verwendest ... dafür aber deutlich resourcen-schonender was die wiederum mehr spielraum für parallelisierung lässt ...
du könntest dann z.b. 2 oder mehr instanzen deines programmes laufen lassen und halt nur unterschiedliche daten verarbeiten *z.b. instanz 1 verarbeitet alles aus ordner 1 usw ...*

wie gesagt : ich kann mir halt einfach nicht vorstellen das du deine aber millionen von geparsten daten überhaupt alle gleichzeitig im RAM brauchst ...
und wenn du dich danach richtest ... also wirklich nur die daten im RAM hast mit denen du in diesem moment auch wirklich arbeitest ... dann passieren dir solche fehler nicht ...
denn alles erstmal in den RAM laden ... stück für stück ... nur um dann mit diesen daten auch wieder nur stück für stück weiter zu arbeiten ... und dann noch mehr daten im RAM zu haben nur um dann vielleicht eine ausgabe zu erzeugen ... die man an sich auch genau so gut wieder in ein file schreiben könnte ... das ist einfach ein konzeptfehler ... und kann man so eben auch nur umsetzen wenn man eben diese riesigen resourcen hat ...

*z.b. 8C/16T XEON , 64GB RAM und 2 nVid karten für CUDA *also anstatt auf der CPU halt auf der GPU rechnen* , großes RAID ... dann kann man z.b. mit der power des CPU alles von den platten in den RAM schieben und von da die eigentlichen *vermutlich numerischen* berechnung von den grakas erledigen lassen ...
aber da du ein solches monster nun mal nicht hast ... musst du dich mit dem abfinden was du hast ... und entsprechend dein programm und dessen arbeitsweise an das vorhandene system anpassen ... und nicht so lange dein system aufrüsten bis dein konzeptionell völlig aus dem ruder gelaufenes programm laufen zu lassen ...


----------



## vimar (25. Apr 2012)

irgendwas auf disk schreiben frisst einfach nur zeit, und ich schreibe sicherlich nicht einzeln den kram auf disk. ich könnte es. ich kann es auch sein lassen. ich will meine nested arraylist mit meinen 300.000 128-dim vektoren einfach komplett im ram haben weil der kmeans algo sowieso schon ewig braucht und ich ne iterationsgrenze setzten musste. jetzt noch disk read und write muss da einfach nciht sein.


----------



## Spacerat (25. Apr 2012)

Ja isses denn? ArrayList... Schnik Schnak...

```
import java.io.FileReader;
import java.io.StreamTokenizer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
 
public final class StreamSearch
{
	public static void main(String[] args)
	throws Throwable
	{
		StreamTokenizer st;
		IntBuffer ib = ByteBuffer.allocateDirect(4000).asIntBuffer();
		IntBuffer tmp;
		while((st = getNextFile()) != null) {
			st.ordinaryChars(0, 255);
			st.parseNumbers();
			int token;
			do {
				token = st.nextToken();
				ib.put((int) st.nval);
				if(!ib.hasRemaining()) {
					tmp = ByteBuffer.allocateDirect(ib.capacity() * 8).asIntBuffer();
					ib.flip();
					tmp.put(ib);
					ib = tmp;
				}
			} while(token != StreamTokenizer.TT_EOF);
		}
	}

	private static StreamTokenizer getNextFile()
	throws Throwable
	{
		StreamTokenizer st = new StreamTokenizer(new FileReader("./test.txt"));
		return st;
	}
}
```
In so einen Buffer passen 536870911 Intwerte... vorrausgesetzt man hat genug Speicher. Im Beispiel ist der Buffer alledings nicht begrenzt und das Proggi liefert eine Exception, wenn die Zahl überschritten wird. Mit [c]get(int index)[/c] und [c]put(int index, int value)[/c] lässt sich darauf sogar ArrayList ähnlich zugreifen. Wenn einem nun auch noch Feld-Schrittweiten (Strides) für mehrdimensionale Arrays aus Assembler oder C++ geläufig sind, gibt es keine Probleme mehr mit Speicher oder gar Performance, weil der StringTokenizer mit dieser Konfiguration bis auf ein Bytearray kein einziges Objekt mehr instanziert. Ferner liegt der Buffer auch noch ausserhalb des Heaps (im Hauptspeicher) und man muss die JVM nicht mal mit mehr zugewiesenem Speicher starten. Versuch' mal, was draus zu machen.
[EDIT]Eins noch: Der IntBuffer kann hier maximal den halben Hauptspeicher bzw. überhaupt nur Integer.MAX_VALUE Bytes (2GB) belegen. Sofern man nur 4GB im Rechner hat, empfiehlt es sich ihn gleich mit Integer.MAX_VALUE zu allocieren und auf die dynamische Vergrössereung zu verzichten.[/EDIT]


----------



## irgendjemand (25. Apr 2012)

vimar hat gesagt.:


> irgendwas auf disk schreiben frisst einfach nur zeit, und ich schreibe sicherlich nicht einzeln den kram auf disk. ich könnte es. ich kann es auch sein lassen. ich will meine nested arraylist mit meinen 300.000 128-dim vektoren einfach komplett im ram haben weil der kmeans algo sowieso schon ewig braucht und ich ne iterationsgrenze setzten musste. jetzt noch disk read und write muss da einfach nciht sein.



auf die gefahr hin das ich mich wiederhole : wenn du ein solches vorhaben umsetzen willst musst du halt deine hardware um dein programm rumbauen ...

sry ... aber anders kann ich es nicht mehr ausdrücken ...
auch wenn es halt "einfach zeit frisst" wenn man halt nur die daten im RAM hat mit denen man gerade rechnet und den rest auf platte schreibt ... ist es dennoch die sinnvollere methode ... und auch eine die in der praxis deutlich häufiger anzutreffen ist als alles in schnellen RAM packen ...

oder was meinst du warum z.b. für hochkomplizierte rechnungen jahre dran gerechnet wird ... weil halt einfach die resourcen fehlen um eben alles im schnellen RAM zu haben und halbwegs intiligent parallel laufen zu lassen ...

wenn du also die anforderungen die du mit deinem programm an deine hardware stellst nicht erfüllen kannst brauchst du nun mal zeit ... da in der IT der grundsatz gilt : weniger zeit wird durch mehr resourcen erkauft ... und andersrum ... -> wenn du eins nicht erfüllen kannst musst du halt mehr vom anderen nehmen


----------



## JohannisderKaeufer (25. Apr 2012)

```
ArrayList<ArrayList<Integer>> AAO_kPointList;
```

Ich vermute mal das das letztendlich die 300.000 128-Dimensionalen Vektoren sind.

Wenn die größen schon feststehen, warum dann kein 

```
int[][] aaoKPointArray = new int[300000][128];
```

Oder wenn die 128 feststehen dann eine List<int[]>


----------



## vimar (25. Apr 2012)

irgendjemand: du hast schon recht keine frage, nur ich habe die zeit nicht um zulange zu warten daher will ich das so -.-

johannes: 300.000 steht nicht fest, aber 128 schon. ich muss beizeiten mal dafür nen int array machen und den ganzen code dann anpassen. das ist auf jedenfall besser. 

es geht auch "nur" um nen db aufbau. später braucht mein programm beim laden der dbs nicht viel ram. ich bin ehrlich gesagt einfach nur glücklich dass es überhaupt nun funktioniert. ^^


----------



## Landei (25. Apr 2012)

Du kannst auch "mixen", also z.B. [c]ArrayList<int[]>[/c].


----------



## irgendjemand (25. Apr 2012)

naja ... ob du es willst ist die eine sache ... nur ob du es umsetzen kannst die andere ...

der ganze thread läuft ja auf die tatsache hinaus das du durch das interne caching der VM in speicher-probleme rennst weil du die zeit nicht opfern willst / kannst um diese zu vermeiden ...

und da musst du halt genau die mitte treffen ... höchste performance bei niedrigster zeit ohne fehler ... klingt einfach ... ist aber verdammt schwer ... und manchmal ist der grad so schmal das man sich mit einzelnen bytes im nanosekundenbereich bewegt ...

mehr als dir sagen das du vielleicht ETWAS mehr zeit opfern solltest um das ganze etwas stabiler zu bekommen und am ende nicht in speicher-probleme zu rennen kann ich leider nicht ... und ich weis auch nicht in wie fern sich die VM tweaken lässt das der GC schneller und vor allem MEHR aufräumt ... aber bin der meinung erst in den letzten tagen bei nem ähnlichen problem ne kilometerlange command-line gesehen zu haben mit der wohl genau das problem was du hast teilweise lösbar sein soll ... aber da müsste ich jetzt auch noch mal suchen ...


----------

