Kann ich ein Objekt durch Kopieren seines Speichers klonen?

8

Ich muss Rückgängig + Redo-Stack für eine begrenzte Anzahl von Klassen unter meiner Kontrolle haben, die sehr, sehr sehr schnell sein muss und RTTI und XML oder Streams verwenden ist nicht machbar, da die Anzahl der Instanzen so hoch wie 2000+ sein kann in verschachtelten Objektlisten. Die Objekte müssen über ein Memento-Muster in und aus kopiert und sofort wieder geladen werden.

Gibt es eine Möglichkeit, Objekte zu kopieren, indem der Speicher kopiert und die Objekte aus diesem Speicher erneut instanziiert werden?

    
MX4399 17.10.2011, 18:37
quelle

5 Antworten

15

Kaum. Sie können den Speicher eines Objekts einfach kopieren, aber ein Teil dieses Speichers ist ein Zeiger. In diesem Fall kopieren Sie nur die Referenz. Diese Zeiger können auch Zeichenfolgen und andere Objekte enthalten.

Ich denke, der beste Weg besteht darin, diese Klassen von TPersistent (oder einem anderen Abkömmling) zu erben und die Assign-Methode für jeden von ihnen zu implementieren. Auf diese Weise können Sie eine zweite Instanz erstellen und das Objekt dieser neuen Instanz zuweisen. In der Implementierung zuweisen können Sie selbst entscheiden, welche Daten kopiert werden sollen und welche nicht.

    
GolezTrol 17.10.2011, 18:43
quelle
10

2000+ verschachtelte Objekte sind nicht so groß und werden auch bei RTTI nicht so langsam sein (Festplattenzugriffe oder Komprimierung werden viel langsamer sein). Mit einer direkten manuellen SaveToStream-Serialisierung ist es sehr schnell, wenn Sie FastMM4 (den Standardspeichermanager seit Delphi 2006) verwenden.

Vielleicht können Sie Ihren Algorithmus ändern und stattdessen dynamische Arrays verwenden (es gibt einen Open-Source-Serializer hier ). Aber Ihre Daten passen möglicherweise nicht in diese Art von Datensätzen.

Oder geben Sie niemals / selten Speicher frei und verwenden Sie nur Objekte oder Record-Referenzen. Sie können einen im Speicher befindlichen Pool von Objekten mit einer Art manuellem Garbage Collector haben und nur den Verweis auf Objekte (oder Datensätze) behandeln.

Wenn Sie string in den Objekten haben, können Sie sie nicht neu zuweisen und eine globale Liste der verwendeten Strings verwalten: Referenzzählung und Copy-on-Write machen es viel schneller als die Standardserialisierung und -zuordnung (sogar mit FastMM4) .

In jedem Fall lohnt es sich, Ihre Anwendung wirklich zu profilieren. Allgemeine menschliche Vermutungen über Leistungsengpässe sind meistens falsch. Vertrauen Sie nur einem Profiler und einer Wanduhr. Vielleicht ist Ihre derzeitige Implementierung nicht so langsam und der eigentliche Engpass ist nicht der Objektprozess, sondern woanders.

Optimiere nicht zu früh. "Mach es richtig, bevor du es schnell machst. Mach es klar, bevor du es schneller machst. Behalte es richtig, wenn du es schneller machst." - Kernighan und Plauger, Elemente des Programmierstils.

    
Arnaud Bouchez 17.10.2011 20:37
quelle
3

Eine einfache Möglichkeit, ein Objekt zu klonen, ist:

  • Leiten Sie Ihre klonbare Klasse von TPersistent ab
  • Implementieren Sie die Prozedur Zuweisen

Siehe Memento Entwurfsmusterbeispiel hier: Ссылка

    
TridenT 17.10.2011 19:16
quelle
1

Ein Ansatz, den ich in der Vergangenheit für diese Situation verwendet habe, besteht darin, einen Datensatz mit dem Teil des Objekts zu deklarieren, den ich behalten muss, und diesen Datensatz innerhalb einer Klasse zu verwenden. Siehe meine alte Antwort unter Optimizing Klassengröße in Delphi. Gibt es etwas wie "gepackte Klassen"? für ein Beispiel.

Da Datensätze bei der Zuweisung kopiert werden, ist es einfach, die Felder von einem Objekttyp in einen anderen zu kopieren.

z.B.

%Vor%

Natürlich können Sie, wenn Sie XE verwenden, verwenden Generics.Collections.TObjectStack statt.

    
Gerry Coll 17.10.2011 20:41
quelle
0

Rückgängig / Wiederherstellen kann mit TMemoryStream implementiert werden - speichern Sie einfach die Daten des Objekts, um sie zu streamen und zu laden, wenn Wiederholen / Rückgängig erscheint. Es verwendet die saveToStream / loadfromstream-Mechanik eines Objekts und ermöglicht es, Referenzen korrekt zu rekonstruieren.

Aktualisierung:

%Vor%

Dann:

Vor der Änderung:

%Vor%

Nach der Wiederherstellung

%Vor%

Ich verwende einen ähnlichen Ansatz für meine CAD-Software, es funktioniert ziemlich gut. Es kann auch verwendet werden, um mehrfache Objekte zu speichern, die in einer Operation geändert werden.

    
George 17.10.2011 19:55
quelle