Ist es möglich, nicht-sammelbare Java-Objekte aus GC-Perspektive zu markieren, um die GC-Sweep-Zeit zu speichern?

8

Ist es möglich, nicht-sammelbare Java-Objekte aus GC-Perspektive zu markieren, um die GC-Sweep-Zeit zu speichern?

Etwas in der Art von Ссылка und speziell nicht-müllsammelbare Container dort (nicht müllsammelbar?).

Das Problem ist, dass ich viele gewöhnliche temporäre Objekte habe, aber ich habe noch größere (mehrere Gigs) Objekte, die für Cache-Zwecke gespeichert werden. Aus keinem Grund sollte der Java-GC alle Cache-Gigabytes durchqueren, die versuchen, etwas zu sammeln, weil sie zwischengespeicherte Daten enthalten, die ihre eigenen Timeouts haben.

Auf diese Weise konnte ich meine Daten auf eine benutzerdefinierte Weise in unendlich gelebte und normal gelebte Objekte partitionieren, und GC wäre hoffentlich ziemlich schnell, weil normale Objekte nicht so lange leben und kleinere Mengen ergeben.

Es gibt einige Problemumgehungen für dieses Problem, z. B. Apache DirectMemory und Commercial Terracotta BigMemory (http: // terracotta.org/products/bigmemory), aber eine Java-native Lösung wäre schöner (ich meine frei und wahrscheinlich zuverlässiger?). Außerdem möchte ich Serialisierungsoverhead vermeiden, was bedeutet, dass es innerhalb desselben jvm passieren sollte. Nach meinem Verständnis funktionieren DirectMemory und BigMemory hauptsächlich off heap , was bedeutet, dass die Objekte zu / von Speicher außerhalb von jvm serialisiert / deserialisiert werden müssen. Einfaches Markieren von Nicht-GC-Regionen innerhalb des JVM scheint eine bessere Lösung zu sein. Die Verwendung von Dateien für den Cache ist ebenfalls keine Option, es hat den gleichen unerschwinglichen Aufwand für die Serialisierung / Deserialisierung - Anwendungsfall ist ein HA-Server mit vielen Daten in zufälliger (menschlicher) Reihenfolge und geringer Latenz.

    
Martin 04.07.2012, 15:48
quelle

5 Antworten

1
  

Ist es möglich, nicht-sammelbare Java-Objekte aus GC-Perspektive zu markieren, um die GC-Sweep-Zeit zu speichern?

Nein, das ist nicht möglich.

Sie können verhindern, dass Objekte gesammelt werden, indem Sie sie erreichbar halten, aber der GC muss sie dennoch verfolgen, um die Erreichbarkeit jedes einzelnen Objekts zu überprüfen. GC (zumindest).

  

Ist einfach meine Annahme, dass, wenn der jvm hungert, er auch all diese unnötigen Objekte scannt.

Ja. Das ist richtig. Wenn jedoch nicht viele Objekte auf diese Weise behandelt werden sollen, ist der Overhead wahrscheinlich unbedeutend. (Und eine bessere Idee ist es, der JVM mehr Speicher zu geben ... wenn das möglich ist.)

    
Stephen C 04.07.2012, 16:52
quelle
2

Jeder Speicher, den die JVM verwaltet, wird auch von der JVM gesammelt. Und alle "Live" -Objekte, die für Java-Methoden ohne Deserialisierung direkt verfügbar sind, müssen im JVM-Speicher existieren. In meinem Verständnis kann man also keine lebenden Objekte haben, die immun gegen die Garbage Collection sind.

Auf der anderen Seite sollte die von Ihnen beschriebene Verwendung den Generationsansatz bei der Garbage Collection sehr effizient machen. Bleiben Ihre großen Objekte eine Weile stehen, werden sie seltener auf Rückgewinnung untersucht. Ich bezweifle daher, dass es viel zu gewinnen gibt, wenn man diese Kontrollen vermeidet.

    
MvG 04.07.2012 16:34
quelle
0

Ganz einfach, damit Sie dies tun können, müsste der Garbage-Collection-Algorithmus ein solches Flag kennen und bei seiner Arbeit berücksichtigen.

Ich bin mir keiner der Standard-GC-Algorithmen bewusst, die ein solches Flag haben. Um dies zu erreichen, müssten Sie Ihren eigenen GC-Algorithmus schreiben (nachdem Sie sich über eine mögliche Art und Weise entschieden haben, diese Informationen zu übermitteln) / p>

Im Prinzip haben Sie diesen Track bereits begonnen - Sie entscheiden, wie die Garbage-Collection durchgeführt werden soll, anstatt sie dem GC-Algo der JVM zu überlassen. Ist die Situation, die Sie beschreiben, ein messbares Problem für Sie? etwas, für das die vorhandene Müllsammlung nicht ausreicht, aber Ihr Plan würde funktionieren? Müllsammler sind extrem gut abgestimmt, daher wäre ich nicht überrascht, wenn die "ineffiziente" Standardstrategie tatsächlich schneller ist als Ihre naiv-optimale Strategie.

(Die manuelle Speicherverwaltung ist in den besten Zeiten knifflig und fehleranfällig; die Verwaltung von einigen Speichern selbst bei Verwendung eines Speicherbereinigers für den Rest scheint noch schlimmer zu sein. Ich nehme an, Sie würden es tun in viele Edge-Fälle laufen, wo der GC davon ausgeht, dass er "weiß", was mit dem ganzen Heap passiert, was nicht mehr wahr wäre. Bleiben Sie klar, wenn Sie können ...)

    
Andrzej Doyle 04.07.2012 16:58
quelle
0

Die empfohlenen Ansätze bestehen darin, entweder eine kommerzielle RTSJ-Implementierung zu verwenden, um GC zu vermeiden, oder Off-Heap-Speicher zu verwenden. Man könnte auch nach weichen Referenzen für Caches suchen (sie werden gesammelt).

Dies wird nicht empfohlen: Wenn Sie aus irgendeinem Grund nicht glauben, dass diese Optionen ausreichen, können Sie in den direkten Speicherzugriff schauen, der UNSAFE (Teil von sun.misc.Unsafe) ist. Sie können das Feld 'theUnsafe' verwenden, um die 'Unsafe'-Instanz zu erhalten. Unsafe ermöglicht die Zuweisung / Freigabe von Speicher über 'allocateMemory' und 'freeMemory'. Dies unterliegt weder der GC-Steuerung noch der JVM-Heap-Größe. Die Auswirkung auf die GC / Anwendung, sobald Sie diese Route durchlaufen haben, ist nicht garantiert - weshalb die Verwendung von Byte-Puffern der richtige Weg ist (wenn Sie keine RTSJ-ähnliche Implementierung verwenden).

Hoffe, das hilft.

    
ali haider 04.07.2012 17:23
quelle
0

Lebende Java-Objekte werden immer Teil des GC-Lebenszyklus sein. Oder anders gesagt, das Markieren eines Objekts, das nicht-gc ist, ist die gleiche Reihenfolge des Overheads, als wenn das Objekt durch eine Stammreferenz referenziert wird (z. B. eine statische endgültige Map).

Aber ein wenig weiter darüber nachgedacht, sind Daten, die in einen Cache gestellt werden, höchstwahrscheinlich nur vorübergehend und würden schließlich geräumt werden. An diesem Punkt wirst du wieder anfangen, die JVM und den GC zu mögen. Wenn Sie 100 GB an permanenten Daten haben, sollten Sie die Architektur Ihrer Anwendung überdenken und versuchen, Ihre Daten zu teilen und zu verteilen (horizontale Skalierbarkeit).

Zu guter Letzt wurde eine Menge Arbeit für die Serialisierung geleistet, und der Overhead der Serialisierung (ich spreche nicht über den schlechten Ruf von ObjectInputStream und ObjectOutputStream) ist nicht so groß. Wenn Ihre Daten hauptsächlich aus primitiven Typen (einschließlich Byte-Array) bestehen, gibt es einen effizienten Weg, readInt () oder readBytes () von off heap Puffern (zum Beispiel netty.io's ChannelBuffer ). Dies könnte ein Weg sein.

    
Killerwhile 04.07.2012 19:30
quelle

Tags und Links