problem mit speicherbedarf von arrays

mainzoop

Mitglied
hallo,

ich schreibe gerade ein java programm und benutze dabei arrays. mein aktuelles programm wurde gleich beim ausführen mit einem outofmemory: java heap space fehler kommentiert. ich habe dann mit dem parameter -Xmx1300M das programm zum laufen gebracht. das programm reserviert folgende arrays:

Java:
double[] ada = new double[45];
double[][] aada = new double[45][45];
double[][][] aaada = new double[45][45][101];
double[][][][] aaaada = new double[45][45][101][101];
double[][][][][] aaaaada = new double[45][45][101][101][3];

wenn ich mal die zwei größten nehme: 45 * 45 * 101 * 101 * (1 + 3) = 82628100
datentyp ist double (8 byte): 82628100 * 8 = 661024800 bytes = 630,x MB

den rest vom programm kann man wohl pi * daumen vernachlässigen. speicherplatzbedarf von java also knapp unter 1,3 GB. meine frage: ist das normal das java doppelt so viel speicherplatz für seine arrays braucht wie effektiv daten vorhanden sind? kann man das eventuell besser machen, und wenn nicht ist es möglich das mit der programiersprache c besser zu lösen ?
 
Das größte Array braucht btw wenn ich mich nicht verrechnet habe genau 996495496 Bytes da Java keine mehrdimensionalen Arrays kennt sondern nur Arrays von Arrays. Wenn man versuchen würde das als ein großes Arrays zu erstellen käme vermutlich auch ein OOME weil nicht genug zusammenhängender Speicher zur Verfügung steht. Mit C wäre es warscheinlich noch schwerer genug zusammenhängenden Speicher für so ein Monsterarray zu bekommen da dort normalerweise ja kein kompaktierender Garbagecollector benutzt wird.

Brauchst du wirklich so eine große Array Struktur oder ließe sich das nicht besser mit einer passenden Collection lösen. Meistens sind so große verschachtelte Arrays ein Hinweis darauf das man irgendwo einen Denkfehler hat.
 
Das mit den Arrays von Arrays wäre auch mein erster Tipp, warum das mehr Speicher braucht als man anhand der double's vermuten würde, aber... der andere Punkt war viel wichtiger:

Das ist doch Bogus!

Was willst du denn mit solchen Arrays?

(OK, ich hatte mir für sowas sogar mal eine "MultiDimArray"-Klasse geschrieben, die die Daten intern als einen Block speichert, und die Index-Umrechnung kapselt, aber... wozu weiß ich auch nicht mehr 😳 😀 )
 
also grundsätzlich will ich folgendes machen. ich rechne etwas aus und speicher in den arrays das ergebnis. später werde ich etwas anderes ausrechnen was aber sehr zeitaufwendig ist und deshalb ist es wichtig das ich die ergebnisse die ich schon habe einfach aus dem speicher abrufen kann, auch weil ich sie mehrfach brauche. mit collections habe ich keine erfahrung. für mich ist vor allem wichtig das ich möglichst viele daten in den speicher packen kann damit der zeitverbrauch des programms noch halbwegs akzeptabel ist.
 
das hört sich aber verdächtig nach nem denkfehler an ... denn ich glaube kaum das du mehr als 1GB auch wirklich gleichzeitig BERECHNEST ! es macht daher also gar keinen sinn so viel kram gleichzeitig im RAM zu haben wenn man nicht durch unzählige threads die ihrereseits noch mehr RAM fressen vorhat diese datenmenge auch wirklich zeitgleich zu berechnen ...

ergo : wäre es sinnvoller wenn du deine ergbenisse raus auf die platte schreibst und dann immer nur die daten einliest und im RAM hast mit denen du auch wirklich rechnest ... und danach wieder alles raus auf die platte schreibst ...

auch wäre mal etwas mehr code sicher hilfreich um vielleicht noch andere speicherlöcher aufzudecken durch die du auf insgesamt was um die 1,3GB kommst ...


wie bereits von Lumaraf angedeutet : du hast einen großen denkfehler drin da du denkst das du ALLES im RAM halten musst nur um schnell zu sein ... das macht aber dadurch das java dann so unglaublich viel speicher zu verwalten hat nur wenig sinn ... effektiver ist es wirklich nur die daten im RAM zu haben mit denen man rechnet und den rest auf die platte zu schreiben
 
ich hab mal folgendes experiment gemacht, folgendes programm:

Java:
public class test
{ 
  public test()
  {
    byte [][][][][] aaaaada = new byte[45][45][101][101][3]; 

    while (true)
    {
    }   
  }

  public static void main(String[] paramArrayOfString)
  {
    new test();
  }
}

3 versionen. einmal mit double, einmal int und einmal byte. als erstes gebe ich den effektiven speicherplatz an, danach den mit java visualvm ermittelten.

double : eff.: 472MB / java: 953 MB
integer: eff.: 236MB / java: 612 MB
byte : eff.: 59MB / java: 444 MB

das finde ich gelinde gesagt besch...
ich glaube kaum das ich eine lösung mit festplattenzwischenspeicher nehmen kann. die berechnungen die ich durchführe sind eigentlich sehr einfach nur ich durchlaufe die arrays sehr häufig. ich duchlaufe die arrays und komme zu einem ergebnis, dann durchlaufe ich abermals die arrays und habe ein anderes ergebnis (was ich mit dem alten vergleiche) und so weiter. da sind ladevorgänge mittels festplatte meiner meinung nach viel zu langsam.
 
habe gerade festgestellt das wenn ich nicht ein mehrdimensionale array verwende sondern nur einen index dann verbraucht java bei byte nur ca. 5% mehr speicherplatz als effektiv daten vorhanden sind. damit kann ich dann wohl leben.
 
Warum sollte festplatte zu langsam sein?

wenn es wirklich durchläufe sind, dann kannst du die werte doch sequenziell lesen und schreiben, dann hat man bei guten festplatten auch problem los 100mb/s + drinnen

Ansonsten hilft nur eines, mehr ram kaufen.
 
Wtfuq?
Die sicherheitsfrage eben war:
Im zentrum unseres Univerums befindet sich die...
Und die richtige Antwort war "Sonne" 😵
 
@TO
aber immer wieder riesen arrays durchlaufen nur weil sich dann 2 oder 3 zahlen ändern ist auch nicht gerade der sauberste ansatz ...

und mag sein das du vielleicht denkst das die platte viel zu langsam wäre ... aber schon mal was von DMA gehört ?
mit guten platten erreicht man locker um die 550MB/s ... was schon fast oberes limit von S-ATA III ist ... und dank DMA gehts von da aus dierekt in den RAM ohne den umweg über die CPU ... wenn dein RAM dann die 550MB/s mitmacht ... sehe ich keine probleme das auf die platte zu schreiben ...

vor allem wenn du eh sequenziell durchgehst wo platten im vergleich zum RAM mithalten können *nur random access fällt auf platten deutlich langsamer aus*

und bei den datenmengen sowieso ... ich weis zwar nicht ob das programm nur für dich gedacht ist ... aber stell dir doch mal vor du willst es verteilen ...
und es gibt selbst heute noch user die so wenig RAM im rechner und so viel kram im hintergrund laufen lassen das diese niemals 1,3GB zusammhängenden speicher frei hätten ... ergo : würde ein solches programm bei vielen usern schlicht in unzähligen OOME enden und niemand würde sich für interessieren weil es so schlechte kritiken dadurch hat ...


um dir mal ein beispiel zu geben : selbst Minecraft begnügt sich mit nicht mal ganz 1GB ... und da wird sicher ein haufen mehr gerechnet als bei deinen paar arrays ... und warum schafft MC das : weil eben nur die daten im RAM liegen mit denen auch gerechnet wird ... der rest wird durch den GC entweder komplett aufgeräumt oder es landen daten auf der platte *z.b. die welt ist ja auch nicht permanent komplett geladen sondern immer nur das stück wo du bist*

ich würde mir also gedanken machen ob du wirklich so viele daten gleichzeitig im RAM brauchst wenn du eh sequenziell durchgehst und daher immer nur einen kleinen teil auch wirklich gerade brauchst ... das macht doch keinen sinn und dein programm nur unnötig "fett" ...
 
Beschreib doch mal für was du die Arrays eigentlich brauchst, also welche Daten du da speicherst. Eine Datenstruktur die immer in ein [45][45][101][101][3] Array passt kommt mir seltsam vor.
Ein Beispiel: Das wäre z.B 45 Galaxien mit je 45 Sonnensystemen mit je 101 Planeten mit je 101 Ländern mit je 3 Städten. Füllst du diese Werte tatsächlich immer aus - Kanns nicht auch ein Sonnesystem mit nur 100 Planeten geben?
 
ich duchlaufe die arrays und komme zu einem ergebnis, dann durchlaufe ich abermals die arrays und habe ein anderes ergebnis (was ich mit dem alten vergleiche) und so weiter. da sind ladevorgänge mittels festplatte meiner meinung nach viel zu langsam.

Probiere es doch einfach aus. Speichere die Ergebnisse in einer Datenbank und ermittle
die Zugriffszeiten vs. der Zugriffzeiten auf das Array.


Eventuell: Wenn der Durchlauf über die Daten vorhersehbar ist und nicht zu jederzeit
der Zugriff auf dem gesamten Datenbestand nötig ist:

-Datenblock laden
-Berechnungen auf Datenblock durchführen - währenddessen nebenläufig nächstenDatenblock laden
-berechneten Datenblock nebenläufig speichern
usw.
(mit geeigneten Synchronisierungsmechanismen)
 
Zuletzt bearbeitet:

Zurück
Oben