mmofacts.com

Java und seine Objekte

gepostet vor 18 Jahre, 11 Monate von TheUndeadable

Naja ich hatte vor kurzem das Problem, dass ich Datenmenge, um die 1000 Datensätze, im Speicher ablegen wollte. Mit java artet das ja mehr oder weniger in einem Speicherchaos aus, weil das dort ja auch alles Objekte sind (weiß garnicht, ob Java überhaupt gescheites memory mapping beherrscht). Deswegen musste ich auf C und JNI ausweichen. Ok dadurch kann man halt das Meiste umsetzen, da man die nicht implementierten Teile in Java schnell mal nachimplementiert Mit C# hab ich leider noch keine Erfahrung gemacht


Sowas ist bei ordentlicher Programmierung unter Java in der aktuellen Version kein Problem. Mich würde es interessieren, welche Version du in Java gehabt hattest. Gerade überflüssiges In- und Outboxing macht unter Java extreme Probleme.
Es stimmt zwar, dass nahezu alles in Java-Objekte sind. Diese können jedoch wie in C auch auf dem Stack liegen oder zusammengefasst sein. Gerade bei komplexen Strukturen finde ich das Handling unter einer 'gemanagten' Sprache angenehmer.

C# ist im Prinzip wie Java, nur auf Grund seines Datums etwas moderner, ob es besser ist, werde ich hier auf Grund der Gefahr eines Flame-Wars nicht starten. Zur Zeit ist das Speicherverhalten von .Net 2.0 dem von Java leicht überlegen. .Net 1.1 war bei sehr großen Objekten nicht sehr optimal.
Die Gefahr einer Off-Topic-Diskussion ist auch der Grund, warum ich den Beitrag herausgezogen habe.
gepostet vor 18 Jahre, 11 Monate von KoMtuR
Also ich benutze die j2se 5.0, um meine javasachen zu schreiben. Bei mir war halt nur das Problem, dass ich mir rein instinktiv vorgestellt hab, dass es ja einen Overhead geben muss, wenn ich Objekte in den Speicher packe. Ok man könnte die Eigenschaften des Objektes vorher nochn in nen Bytestream packen und dies dann in ne Collection legen, aber ich weiß nicht ob es dann wirklich nur dewn Bytstream speichert oder eher doch nochn kleiner Overhead entsteht. Ich hab bis jetzt bei meiner Suche nach effektiven Speicherfunktionen (also Funktionen mit denen man Speicher manipulieren kann) keinen erfolg gehabt. Vielleicht bin ich da auch falsch ran gegangen.

Mein Ziel war halt Items für ein Spiel so zu speichern, dass ich sie möglichst schnell abrufen kann. mysql zb. produziert für mich da zuviel Overhead (meine Meinung

Wenn es jetzt natürlich irgendwelche Sachen gebe, wo du mir zeigen könntest, dass meine Theorie falsch ist und es doch einen effektiven Ansatz gäbe, dann immer her damit Ich lerne ja auch noch (wer macht das denn nicht).

Naja wie ich schonmal meinte kann ich zu C# leider nichts bedeutendes sagen. Da ich mich ja nun explizit mit Java auseinandersetze wirds auch nicht demnächst geschehen, dass ich mir die Sprache mal anschaue Ich würde mal auf deine Aussage "..., ob es besser ist, ..." darauf antworten, dass es halt keine Sprache gibt, die irgendwo perfekt ist. Deswegen kann man halt schlecht davon sprechen, was nun besser ist und was nicht
gepostet vor 18 Jahre, 11 Monate von TheUndeadable
Gewissermaßen hast du Recht:

Es gibt einen kleinen Overhead. In C# sind es 8 Byte pro komplexem Objekt, native Objekte wie Int, double und String besitzen diesen Header nicht. In den 8 Bytes stecken 4 Bytes für die Typinformation und 4 Bytes für diverse Synchronisationen. In Java wird es ähnlich sein.
Dieser Overhead ist für heutige Systeme vernachlässigbar.

> (also Funktionen mit denen man Speicher manipulieren kann)

Dies wird es nicht geben, da Java per se eine 'sichere' Umgebung ist und alle Objekte vor unbefugtem Zugriff geschätzt sind. Entweder klappt ein Zugriff oder es wird eine Exception geworfen, würdest du direkt in den Speicher schreiben, könnte die JRE diesen Zugriff nicht mehr protokollieren.

> Mein Ziel war halt Items für ein Spiel so zu speichern, dass ich sie möglichst schnell abrufen kann

Dafür sind .Net und Java meines Erachtens sogar besser geeignet.

Bei C++ hast du das Problem, dass der Speicher durch viele news und deletes fragmentiert. Objekt A liegt auf Position 0x08000000, Objekt B auf 0x10000000. Greifst du nun regelmäßig nach Objekt A auf Objekt B, so muss der Prozi andauernd Speicherseiten wechseln. .Net und Java registrieren diese Reihenfolge und strukturieren den Speicher so um, dass A und B auf einer Speicherseite liegen. Weiterhin ordnet der GC in Wartezeiten den kompletten Speicher neu, so dass du wieder einen defragmentierte Speicher hast. Viele Objekte, die im zeitlichnahen Abstand genutzt werden, befinden sich dadurch in näherer Umgebung und der Caching-Algorithmus des Prozessors kann besser greifen.
gepostet vor 18 Jahre, 11 Monate von KoMtuR
Also meinste ich sollte die Objekte lieber in ner Collection speichern und diese Collection statisch machen, so dass da jeder drauf lesen kann. Die Items sind ja weniger zum schreiben gedacht (ausser der Admin fügt mal ein Item hinzu oder editiert mal eins). Muss ich mal gucken, ob es eine Funktion gibt, welche die Größe eines Objekts ausgibt (hab ich irgendwo mal gelesen) und dann kann man ja kalkulieren. Also wenn dies natürlich nicht diese Ausmaße einnimt, die ich befürchtet habe, dann wäre es wirklich praktischer (ich hab es mir sicherlich nicht ausgesucht es in C zu machen
gepostet vor 18 Jahre, 11 Monate von TheUndeadable
Ich glaube, ich habe herausgelesen, was du meinst:

Du meinst Objekt-Serialisierung?

Pseudocode:

List aoItems = new List();
// Fülle aoItems

// Nun die Speicherung:

Serializer oSerializer = new Serializer();
StreamWriter oWriter = new StreamWriter ( "datei.dump" );
oSerializer.Serialize ( aoItems, oWriter );
oWriter.Dispose();

// Einladen

StreamReader oReader = new StreamReader ( "datei.dump" );
List aoItems = ( List ) oSerializer.Deserialize ( oReader );
oReader.Dispose();

Dies geht so garantiert auch in Java. Die JRE kümmert sich dann vollautomatisch auf die in aoItems enthaltenen Objekte und stellt den Typ wieder her.

http://www.galileocomputing.de/openbook/javainsel5/javainsel12_013.htm#Xxx999378
gepostet vor 18 Jahre, 11 Monate von KoMtuR
Ist denn dann auch gesichtert, dass , einmal geladen, die Objekte dann immer (also auch threadübergreifend) in einer statischen Variable verfügbar sind? Ich weiß nun nicht, inwieweit der GC statische Objekte behandelt. Mir gehts ja auch darum, dass ich dieses Teil dann nicht nachladen muss
gepostet vor 18 Jahre, 11 Monate von schokofreak
Speichern von Records in Objekte ist in Java ein RIESIGES Problem. Und wird es auch immer bleiben (As long as there were no events).

Respektive es braucht extremes Wissen um hier ein Speicherchaos zu vermeiden.

Beispiel gefällig?
Dem Otto- Normalcoder wird sicher irgendwann auffallen dass es ineffizient ist, ALLES IMMER im Speicher zu halten. Sprich er wird ab und zu mal die Objekte wieder löschen wollen.

Otto Normalcoder kennt sich auch ein bisschen mit Patterns aus, sprich er bindet ev. scho mal einen Observer auf ein Datenobjekt.

Otto Normalcoder benötigt Benutzerspezifische Iteratoren, Filter, Subsetzs dieser Objekte. Hierzu erstellt er ein Objekt welches Referenzen auf ein Subset der Objekte beinhaltet (Beispielsweise für Alle Objekte mit Fremdschlüssel = 1).

Otto Normalcoder macht einen Aufruf im Sinne von:
 

Liste meineListe = getObjekteMitFS(1);
for each in meineLIste
Next


Was passiert hier?
- Der Observer verhindert, das die Liste vom GC entfernt werden kann.
- Selbst wenn die Objekte vor den GC vorbereitet werden (Sprich aus dem Cache entfernt werden) kann der GC diese Objekte aufgrund der Listen-Leiche nicht entfernen

Fazit: Liste bleibt erhalten; Liste erzwingt ein Erhaltenlassen sämtlicher Objekte

Fazit2: Eine Cache Re-Allokation bedeutet dass ein Objekt sdchlussendlich mehrfach gespeichert wird.

Somit soll gesagt werden: Wer mit grossen Datenmengen in java arbeiten will soll:
- NIEMALS einfach so Coden sondern viel Überlegen
- Sich nicht auf den GC verlassen sondern alles genau so machen, wie er es in C++ auch tun müsste.

Das gleiche gilt übrigens auch für C# unter Einsatz eines Observers (Naja, wer setzt in C# schon einen Observer und ned Event/Delegate ein?)

Gruss
gepostet vor 18 Jahre, 11 Monate von schokofreak
Für dein Problem heist die Lösung höchst warscheinlich: HashMap respektive Vektor.

Vektor bei einer simplen Auflistung; HashMap bei einer Abfrage aufgrund einer ID (Fremdschlüssel).

Das ganze schön Synchronisieren und möglichst nie das ganze Cache gehen.

Code kann ich dir notfalls geben... weist du wie Synchronisation in Java funzt? Resp. brauchst du Synchronisation überhaupt?

Gruss
gepostet vor 18 Jahre, 11 Monate von KoMtuR
Jo Synchronisation weiß ich wie das in Java geht. Ich brauchs sicherlich, weil man ja erst mit multithreaded Servlets so richtig die Geschwindigkeit rausholt. Klar werd ich sicher diese Probleme kriegen, dass ich einfach mal ne Statische nicht richtig absicher und somit es zu fehlern kommt. Aber was man nicht weiß lernt man


Das ganze schön Synchronisieren und möglichst nie das ganze Cache gehen.

Meinst du damit, dass ich nicht alles in den Cache hauen soll? Ich hab nicht die ganz Wortwahl verstanden.
Ich will einfach nur wissen, ob ich irgendwas noch beachten beim programmieren (ich weiß das die Servlets im Speicher bleiben udn dann nur eben ein Abbild davon gemacht wird). Brauch ich diese Geschichte mit dem Observer, was du da geschrieben hattest?

Letzte Frage: Kann es passieren, dass eben der GC diese Liste, welche gewollterweise natürlich nur einmal im Speicher angelegt werden soll, einfach löscht und ich dann probleme kriegen könnte (Ok es würde einfach nur darauf hinauslaufen, dass das Programm die Liste neu initialisiert)?

Edit: Wenigstens in der Wahl der Collection lag ich schonmal richtig mit ner Hashmap *g*

edit2: Ah ich galube nun hab ich das mit den Observer einigermaßen verstanden. Zumindest was bei galileocomputing stand


edit die 3.: Dank dieser Seite wurde nun endlich meine komplette Befürchtung zu nicht gemacht *g* http://www.adtmag.com/java/articleold.asp?id=165
gepostet vor 18 Jahre, 11 Monate von schokofreak
Der GC entfernt Objekte erst, wenn es keine Referenzen mehr auf diese gibt.
Sprich: Solange du die Liste nutzen kannst, wird sie auch nicht entfernt.

AUSSER dein Servlet wird aus dem Speicher entfernt; was dann allerdings auch kein Problem darstellen sollte da sich dann dein Applikationsserver um das ganze kümmert.

Kritisch für dich wird es erst, wenn du dir Teile der Liste auf der Festplatte zwischenspeicherst (Sprich nur Teile im Speicher sind, bei Bedarf auf Platte eingelesen wird). Alles direkt im Speicher stellt für dich kein Problem dar - zumindest im Bezug auf den GC nicht.

Gruss

Auf diese Diskussion antworten