ist tiefes Kopieren sinnvoll?

oetzi

Bekanntes Mitglied
Hallo zusammen,

ich benutze im Moment tiefe Kopien von Objekten mittels ByteArrayOutputStream -> InputStream.
Als ich da mit Kollegen drüber gesprochen habe, waren sie der Meinung, dass man tiefe Kopien eigentlich nie verwenden sollte und das dann wohl eher ein Designfehler vorliegen würde.

Da wir aber auf keine andere Lösung gekommen sind, möchte ich das Problem hier nochmal schildern. Vielleicht könnt ihr mir ja sagen, ob hier das tiefe kopieren die beste Lösung ist, oder ob man es anders machen sollte.

Hintergrundinfos:
- web basiertes Rollenspiel
- es gibt unique-monster, d. h. Monster A gibt es in verschiedenen Ausführungen, die zufällig, basieren auf Standardwerten, generiert werden
- beim Starten des Servers werden u.a. die Basiswerte (id, name, attribute, etc.) von Monstern ausgelesen und in jeweilige Objekte gepackt. Diese Objekte speichere ich in ArrayList<Monster> monsterList
-> Damit möchte ich die Performance verbessern, da nicht jedesmal auf die DB zugegriffen werden muss, wenn die Basiswerte benötigt werden

Problemsituation:
- Brauche ich jetzt ein unique-Monster, rufe ich die Methode "public Monster getUniqueMonster(Integer)" (s.u.) auf und übergebe die Id von dem Viech, wovon ich eine zufällige Variante generiert haben möchte.
- Die Methode sucht innerhalb der monsterList nach diesem Monster und berechnet die zufälligen finalen Werte
-> hier kommt aktuell das tiefe Kopieren zum Einsatz. Würde ich einfach per monsterList.get(i) das Monster holen und bearbeiten, würde ich beim 2. Aufruf der Methode die Werte des 1. zurückgegebenen Monsters verändern, da ich ja auf dem selben Speicherbereich arbeite.

Die Methode sieht aktuell so aus:
Java:
	public Monster getUniqueMonsterById(Integer id){
		Monster tmpMonster = null;
		for (int i = 0; i < allMonster.size(); i++) {
			if (allMonster.get(i).getPk_Monster().equals(id)){
				tmpMonster = (Monster) Monster.clone(allMonster.get(i));
				break;
			}
		}
		if (tmpMonster == null){
			System.out.println("ERROR | Es gibt kein Monster mit der ID: "+ id);
		}
		tmpMonster.calculateStandardLevel();
        tmpMonster.createUniqueAttributes();
        tmpMonster.calculateFinalLevel();
        tmpMonster.refreshAllValues();
	return tmpMonster;
	}
(Monster.clone() ist die selbstgeschriebene Methode zum tiefen kopieren)

Ich hoffe, dass das jetzt halbwegs verständlich war :)

Für mich stellen sich im Moment 2 Fragen:
1. Spricht irgendwas grundsätzlich gegen das Erstellen von tiefen Kopien mittels der ByteArrayOutputStream-Methode? Performance, Ressourcen,...?
2. Gäbe es überhaupt eine andere Mögichkeit das hier zu lösen?

Schönen Gruß
oetzi
 
G

Gast2

Gast
Ich würde da eher ein Factory Pattern einsetzen.

Ob du durch kopieren eines bestehenden Objectes wirklich Performance gewinnst mag ich bezweifeln.
 

oetzi

Bekanntes Mitglied
Hallo fassy,

ich kenne mich zwar nicht besonders gut mit Factory Pattern aus, aber geht das was ich da mache nicht sogar in die Richtung?
Schließlich rufe ich eine Methode auf, die mir ein neues Objekt zurück liefert.

Und abgesehen davon: Wie soll ich mit dem Factory Pattern das tiefe kopieren umgehen?
 

Empire Phoenix

Top Contributor
also ich sehe da jetzt nicht wo das Problem ist, wenn die eigene Versionen der Daten brauchen müssen die die auch haben, da hilft nichts.(was mir bekannt wäre)
 

oetzi

Bekanntes Mitglied
naja, eine Alternative die naheliegt wäre jedesmal auf die Datenbank zuzugreifen, alle benötigten Daten zu laden und daraus die neuen Objekte zu erzeugen.
Allerdings war es ja genau diesen Vorgang den ich vermeiden wollte, in der Annahme, dass dies wohl der am meisten Ressourcen fressende Ablauf wäre.

Allerdings war das halt nur eine Annahme. Ich lasse mich ja auch gerne vom Gegenteil überzeugen :)
 

Landei

Top Contributor
Erste Frage: Habt ihr schon alles immutable gemacht, was sich immutable machen lässt (und das mehr, als man gemeinhin annimmt)? Was sich nicht ändert, braucht man natürlich nicht zu kopieren...
 

oetzi

Bekanntes Mitglied
Hallo Landei,

ich verstehe ehrlich gesagt nicht, was das genau mit meinem Problem zu tun hat.
Ich will doch eine Kopie von meinem Objekt haben.
Aber vielleicht habe ich den Sinn von immutable auch einfach nicht richtig verstanden :)

Gruß
oetzi
 

FArt

Top Contributor
Anmerkungen:
- Im Prinzip ist das eine Factory. Das Factorypattern an sich wäre schöner, aber sei es drum. Du kannst auch mit Copy-Konstruktor arbeiten usw.
- Clonen ist ok
- vollständiger deep-clone serialisierbarer Objekte über Marshalling/Unmarshalling ist u.U. uncool, weil tatsächlich von allen Objekten Kopien angefertigt werde. Bei Clones nach diesem Muster werden auch Objekte kopiert, die nicht kopiert werden müssen weil sie immutable sind. Außerdem übernimmt die VM eine Optimierung mit Strings (die auch immutable sind) und die du damit aushebelst.
- Wenn deine Kollegen Behauptungen aufstellen, sollten sie die auch begründen können, also nachhaken.
 
Zuletzt bearbeitet:

oetzi

Bekanntes Mitglied
- Clonen ist ok
- vollständiger deep-clone serialisierbarer Objekte über Marshalling/Unmarshalling ist u.U. uncool, weil tatsächlich von allen Objekten Kopien angefertigt werde. Bei Clones nach diesem Muster werden auch Objekte kopiert, die nicht kopiert werden müssen weil sie immutable sind. Außerdem übernimmt die VM eine Optimierung mit Strings (die auch immutable sind) und die du damit aushebelst.

Naja, das Problem ist einfach, dass diese Klasse "Monster" natürlich Attribute wie name, beschreibung, etc. hat, die für alle Instanzen gleich sind, allerdings auch viele (die Mehrheit) die wirklich einzigartig sind.
Daher weiß ich nicht, ob ich mir nicht selber nen Strick drehe, wenn ich jetzt anfange nur die benötigten Attribute/Objekte der Klasse "Monster" tief zu kopieren und den Rest halt flach. Da sehe ich einfach das Risiko, dass ich vor lauter Unterscheidungen irgendwann nur noch irgendwelche Kopierfehler suche :)
Wenn es also kein "Killerargument" gegen die tiefe Kopie gibt, ist das sicherlich die einfachste und sicherste Variante, soweit ich das jedenfalls sehe.

- Wenn deine Kollegen Behauptungen aufstellen, sollten sie die auch begründen können, also nachhaken.
Ich habe ohne Ende nachgehakt ;-)
Halt mit dem Ergebnis, dass sie mir auch nicht sagen konnten, wie ich das Problem anders lösen kann.
Die Hauptbegründung war halt der Ressourcenverbrauch und Performanceverlust.

Und genau um rauszufinden wie hoch dieser Verbrauch/Verlust ist, frage ich hier die Experten :)

Gruß
oetzi
 

FArt

Top Contributor
Und genau um rauszufinden wie hoch dieser Verbrauch/Verlust ist, frage ich hier die Experten :)

Gruß
oetzi

Das kannst nur du beantworten, der du die Objekte kennst. Wie viele Objekte werden unnötig kopiert weil immutable? Das ist der unnötige Ressourcenverbrauch.
Fällt das ins Gewicht? Kommt darauf an wie oft du davon Gebrauch machst und wie viel Platz gesamt zur Verfügung steht.
In der Regel sollte man nur optimieren, wenn man ein Problem hat und durch die Änderunge eine spürbare (messbare) Verbesserung erzielt.
 

oetzi

Bekanntes Mitglied
Ja genau um die Frage geht es ja, wenn ich die so einfach beantworten könnte, würde ich nicht fragen ;-)
Was den Speicherverbrauch angeht, müsste man wohl einfach sämtliche Speicherverbrauchswerte der Attribute addieren um den Gesamtspeicherverbrauch pro Objekt zu erhalten.
Aber wie sieht es denn mit der Performance aus, wenn ich immer wieder dieses wegschreiben und einlesen über ein ByteArray mache.

Sagen wir einfach mal, dass ich anfänglich ca. 100-200 solcher Objekte mal im Speicher vorhalten würde. (Später vielleicht das 2-3 fache)
 

FArt

Top Contributor
Wenn die Antwort so allgemein gültig wäre würdest du eine bekommen. Wir kennen deine Randbedingungen und die Objekte nicht.
Wenn dich das glücklicher macht: 300 Monster sind kein Problem.
Ich könnte auch sagen: 300 Monster. Nie im Leben, da geht dir der Speicher aus. Mache keinen Deep-Clone auf diese Art!
Such's dir aus.

Ok, stürzen wir uns mal auf den Designfehler: poor man's caching.

Damit möchte ich die Performance verbessern, da nicht jedesmal auf die DB zugegriffen werden muss, wenn die Basiswerte benötigt werden

Warum lässt du das nicht die DB bzw. die Persistenzschicht (Cache) optimieren? Die können das viel besser und du musst keine Klimmzüge machen.
... und mein Motto ist... optimiere bei Bedarf, nachdem Messungen vorliegen und du eine signifikante Verbesserung durch Eingriffe erwarten kannst.
 

Landei

Top Contributor
Hallo Landei,

ich verstehe ehrlich gesagt nicht, was das genau mit meinem Problem zu tun hat.
Ich will doch eine Kopie von meinem Objekt haben.
Aber vielleicht habe ich den Sinn von immutable auch einfach nicht richtig verstanden :)

Gruß
oetzi

Von einem String brauchst du keine "tiefe" Kopie zu machen: Wenn zwei Klassen auf denselben String verweisen, ist das kein Problem, da er sich selbst nie ändert. Nun ist die Frage, ob das bei deinem Monster u.s.w. eventuell auch möglich wäre. Dazu müsste man überall da, wo früher der Monster-Zustand geändert wurde, stattdessen ein geändertes Monster zurückliefern (etwa wie String.replace, was ja auch den String nicht ändert, sondern eine geänderte Kopie zurückliefert), das Problem dabei ist, dass alle "interessierten Stellen" die Änderung auch mitbekommen müssen. Theoretisch ist das immer möglich, in manchen Fällen aber nicht besonders praktisch, nicht performant genug, und manchmal ist einfach der Aufwand zu groß, eine bestehende Struktur von veränderlich auf unveränderlich umzumodeln.
 
Zuletzt bearbeitet:

oetzi

Bekanntes Mitglied
... und mein Motto ist... optimiere bei Bedarf, nachdem Messungen vorliegen und du eine signifikante Verbesserung durch Eingriffe erwarten kannst.

das Vorgehen ist sicherlich nicht verkehrt.
Aber hättet ihr mir jetzt gesagt, dass tiefe Kopien sehr stark die Performance und oder den Speicher beeinflussen, hätte ich ja erst gar nicht auf das Pferd setzen müssen und mir das Re-Engineering gespart :)

@Landei: Danke für die nähere Erklärung. Aber das ganze hört sich ja schon alles andere als simpel an... Ich glaube ich werde es erstmal so lassen wie es ist (es hat ja keiner KO-Kriterien dagegen gebracht s.o. ;-) ). Und dann werde ich mal gucken was draus wird.
Vielleicht hole ich den Thread irgendwas mal wieder raus und werde von den schlechten Erfahrungen berichten ;-)

Gruß
oetzi
 

FArt

Top Contributor
Aber hättet ihr mir jetzt gesagt, dass tiefe Kopien sehr stark die Performance und oder den Speicher beeinflussen, hätte ich ja erst gar nicht auf das Pferd setzen müssen und mir das Re-Engineering gespart
Na ja, auf das Pferd hättest du ja auch gar nicht erst setzen müssen. Die Frage war ja auch: sind denn die DB Zugriffe wirklich so teuer und kommen so häufig vor, dass sich dieses "Caching" lohnt? Wäre da eine reine Optimierung auf Persistenzbasis nicht von Haus aus besser gewesen?

Deswegen meinte ich erst den sauberen Weg gehen (ganz ohne "Caching") und dann an den richtigen Stellen optimieren. In sofern haben deine Kollegen bzgl. des Designfehlers schon Recht.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I arraycopy und tiefes Klonen Allgemeine Java-Themen 3
M Ordner kopieren Allgemeine Java-Themen 5
S Referenzdatentyp kopieren Allgemeine Java-Themen 5
I Wie Vektor-Grafik in die Zwischenablage kopieren? Allgemeine Java-Themen 2
J Gebautes Jar per Maven in einen Docker Container kopieren Allgemeine Java-Themen 0
L File beim Kopieren in einen anderen Ordner umbenennen Allgemeine Java-Themen 6
M Dateien schneller kopieren Allgemeine Java-Themen 1
M Dateien nach kopieren vergleichen Allgemeine Java-Themen 9
B In zwischenablage kopieren Allgemeine Java-Themen 2
F Datentypen Kopieren von Datentypen Allgemeine Java-Themen 10
K JAR Datei Corrupt nach Kopieren Allgemeine Java-Themen 4
D Kopieren von Dateien aus einem Ordner in einen anderen Allgemeine Java-Themen 6
A Bestimmte Inhalte aus ArrayList 1 in ArrayList 2 kopieren Allgemeine Java-Themen 6
N String ins Clipboard kopieren ohne makieren. Allgemeine Java-Themen 12
J Umwandeln von URL zu File und danach kopieren geht nicht Allgemeine Java-Themen 1
F Java moved Files statt sie zu kopieren Allgemeine Java-Themen 12
X Dateien von der Jar zum Ordner kopieren. Allgemeine Java-Themen 4
J PDF-Datei aus JAR-Archiv in Dateisystem kopieren Allgemeine Java-Themen 1
S Einen übergebenen String kopieren Allgemeine Java-Themen 3
S in Zip kopieren -- Backup-Programm Allgemeine Java-Themen 9
P Vectorelemente in einen anderen Vector kopieren Allgemeine Java-Themen 12
J Bilder halb in falscher Farbe nach kopieren aus Web Allgemeine Java-Themen 3
D Mit Hilfe von Java aus Excel-Sheet Zellen in neues Excel Dokument kopieren Allgemeine Java-Themen 3
K NetBeans Ordner bei 'Clean&Build' automatisch in dist Verzeichnis kopieren Allgemeine Java-Themen 0
T Ordner samt Dateien kopieren Allgemeine Java-Themen 11
Todesbote Zeilen aus Excel in andere Excel Tabelle kopieren Allgemeine Java-Themen 0
T Mit Apache Poi Daten aus einer Excel Tabelle kopieren und in Word einfügen Allgemeine Java-Themen 1
A Collections Array-Elemente in ArrayList kopieren ohne Schleife Allgemeine Java-Themen 7
P jar aus der jar kopieren XD Allgemeine Java-Themen 4
M Pakete in Ordner Kopieren Allgemeine Java-Themen 7
D File mit Inhalt kopieren und dieses File dann neu erstellen ? Allgemeine Java-Themen 4
kodela Problem mit Kopieren über FileChannel Allgemeine Java-Themen 4
H Kopieren sehr langsam Allgemeine Java-Themen 5
I Java Ordner kopieren [Error] Allgemeine Java-Themen 6
E Files Kopieren Allgemeine Java-Themen 8
P Daten kopieren mit nio - Zugriff verweigert Allgemeine Java-Themen 8
Z Ausschneiden, Kopieren, Einfügen, Löschen in JTextArea Allgemeine Java-Themen 5
S exe Kopieren Allgemeine Java-Themen 11
E Ordner rekursiv kopieren Allgemeine Java-Themen 8
J Standard-I´/O kopieren Allgemeine Java-Themen 5
R kopieren von Dateien und Verzeichnissen - UNICODE? Allgemeine Java-Themen 4
S Kopieren von Datei führt zu Beschädigung Allgemeine Java-Themen 7
D markierten Text kopieren Allgemeine Java-Themen 2
B Zertifikat des Users speichern (serialisieren oder kopieren) Allgemeine Java-Themen 2
S Dateiinhalt kopieren Allgemeine Java-Themen 4
G Object mit clone kopieren Allgemeine Java-Themen 21
F Kopieren eines Objekts Allgemeine Java-Themen 3
D Kopieren und Einfügen Allgemeine Java-Themen 8
C Kopieren von Dateien die von einem anderen Programm verwendet werden? Allgemeine Java-Themen 7
E Blob Element kopieren Allgemeine Java-Themen 12
0din Websites kopieren Allgemeine Java-Themen 25
D mit java kopieren und umbenennen Allgemeine Java-Themen 6
X Objektsammlung clonen bzw. kopieren Allgemeine Java-Themen 5
A Beim Kopieren werden Bilder verfälscht Allgemeine Java-Themen 3
V Dateien kopieren Allgemeine Java-Themen 6
N Daten auf Server kopieren Allgemeine Java-Themen 6
Q Iterator kopieren Allgemeine Java-Themen 6
M Wie in Eclipse Quellcode incl. Zeilennummern kopieren? Allgemeine Java-Themen 6
G Daten von Excel kopieren - sinnvolle Datenstruktur? Allgemeine Java-Themen 3
P Eigene Klasse kopieren die auf sich selbst refferenziert Allgemeine Java-Themen 8
J Externes Programm - Konsolenausgabe kopieren/sichtbar machen Allgemeine Java-Themen 22
C File in Jar kopieren? Allgemeine Java-Themen 9
G ANT und Verzeichnisstruktur kopieren Allgemeine Java-Themen 2
G Datei löschen nach kopieren geht nicht Allgemeine Java-Themen 5
R Dateien lokal kopieren Allgemeine Java-Themen 6
P Objekt kopieren Allgemeine Java-Themen 8
hdi ArrayList kopieren? Allgemeine Java-Themen 8
G Datei kopieren Allgemeine Java-Themen 27
O Vektor kopieren (Inhalt, nicht Referenzen) Allgemeine Java-Themen 3
I Teile von ArrayList in eine andere kopieren? Allgemeine Java-Themen 2
V Datei kopieren und Datum erhalten Allgemeine Java-Themen 2
V Sich selbst kopieren (Jar- Datei) Allgemeine Java-Themen 3
G Code mit Zeilennummern kopieren? Allgemeine Java-Themen 3
S Stream ohne Referenz kopieren ? Allgemeine Java-Themen 4
M variable übergeben NICHT KOPIEREN Allgemeine Java-Themen 12
P String in Array kopieren Allgemeine Java-Themen 3
S Dateien auf Diskette kopieren Allgemeine Java-Themen 3
M Datei kopieren? Allgemeine Java-Themen 2
MQue Array in ein anderes Array kopieren Allgemeine Java-Themen 5
D aufruf beim kopieren Allgemeine Java-Themen 11
G Objekt dynamisch erstellen und Inhalte kopieren Allgemeine Java-Themen 6
K Datei kopieren Allgemeine Java-Themen 2
M 2-dimensionalen array schnell kopieren Allgemeine Java-Themen 6
T Text aus Java-Applet kopieren. Allgemeine Java-Themen 14
TheJavaKid Textformatierung bei Kopieren übernehmen Allgemeine Java-Themen 8
P Mehrzeiligen Text aus JTA lesen und in andere JTA kopieren Allgemeine Java-Themen 7
S Objekte kopieren Allgemeine Java-Themen 6
W Dateien über Clipboard kopieren Allgemeine Java-Themen 2
G InputStream kopieren? Allgemeine Java-Themen 6
G In Windows Datei kopieren Allgemeine Java-Themen 2
G Text aus Chatfenster kopieren Allgemeine Java-Themen 7
M Cache & Datein kopieren Allgemeine Java-Themen 3
R Problem bei Kopieren eines Ordners Allgemeine Java-Themen 13
J Nicht-static variable in static variable kopieren - wie? Allgemeine Java-Themen 14
m@nu Kopieren beschleunigen Allgemeine Java-Themen 3
T Musikdateien von CD Kopieren Allgemeine Java-Themen 4
M Bild in Zwischenablage kopieren? Allgemeine Java-Themen 7
bernd Problem beim kopieren! Allgemeine Java-Themen 2
G Dateien werden beim Kopieren zerstört Allgemeine Java-Themen 4
N Schnellste Art Dateien zu kopieren Allgemeine Java-Themen 16

Ähnliche Java Themen


Oben