Verwenden von MapMaker zum Erstellen eines Caches

8

Ich möchte mit MapMaker eine Map erstellen, die große Objekte zwischenspeichert, welches aus dem Cache entfernt werden sollte, wenn nicht genügend Speicher vorhanden ist. Dieses kleine Demo-Programm scheint gut zu funktionieren:

%Vor%

Wenn ich jedoch dasselbe in meiner realen Anwendung mache, sind Einträge grundsätzlich aus dem Cache entfernt, sobald sie hinzugefügt werden. In meinem echten Anwendung verwende ich auch Ganzzahlen als Schlüssel, und die zwischengespeicherten Werte sind archiviert Blöcke von der Festplatte, die einige Daten enthält. soweit ich Verstehen, Schwachstellen werden so schnell wie sie sind Müll gesammelt nicht mehr verwendet, so scheint dies sinnvoll, weil die Schlüssel schwach sind Verweise. Wenn ich die Karte so erstelle:

%Vor%

Die Einträge werden nie auf Müllbasis gesammelt und ich bekomme nicht genügend Speicher Fehler in meinem Testprogramm. Die Finalize-Methode für die TestValue-Einträge wird nie genannt. Wenn ich die Testmethode wie folgt ändere:

%Vor%

-Einträge werden aus dem Cache und dem Finalizer des TestValue entfernt Objekte wird aufgerufen, aber nach einer Weile bekomme ich auch einen nicht ausreichenden Speicher Fehler.

Also meine Frage ist: Was ist der richtige Weg, um mit MapMaker ein Karte, die als Cache verwendet werden kann? Warum wird mein Testprogramm nicht entfernt? die Einträge so schnell wie möglich, wenn ich weakKeys verwende? Ist es möglich, zu Hinzufügen einer Referenzwarteschlange zur Cachemap?

    
Michael 09.07.2010, 07:25
quelle

3 Antworten

8

Es gibt viele Dinge, die passieren können, aber in Bezug auf Ihr Testprogramm, das weiche Werte verwendet: Sie können OutOfMemoryError auch dann aufrufen, wenn Sie SoftReferences haben, die noch nicht als Garbage Collected gesammelt wurden. Das wiederholt sich: Sie können einen OutOfMemoryError erhalten, auch wenn Sie SoftReferences haben, die noch nicht gelöscht wurden.

SoftReferences sind etwas seltsam, siehe Ссылка für eine Beschreibung der aktuellen Mechanik. Wahrscheinlich in Ihrem Testfall hatte der GC gerade keine Zeit, zwei vollständige GCs zu machen.

Wenn Sie weakKeys verwendeten, löschte der CG diese sofort und musste nicht auf eine vollständige GC-Pause warten. (b / c WeakReferences werden aggressiv gesammelt.)

Wenn Sie einen speichersensitiven Cache mit Integer-Schlüsseln wünschen, wäre meiner Meinung nach Folgendes angebracht:

%Vor%

Sie können leicht ein Testprogramm erstellen, das OutOfMemoryError auslöst, aber wenn Ihre reale Anwendung sich einigermaßen gut benimmt und nicht unter zu viel Druck gerät, könnten Sie in Ordnung sein. SoftReferences sind ziemlich schwer zu bekommen.

Wenn Sie System.gc () nicht zu wenig Arbeitsspeicher benötigen, würde ich Ihnen stattdessen empfehlen, zu einer LRU-Map mit einer festen Maximalgröße zu wechseln (siehe das Javadoc von java.util.LinkedHashMap für ein Beispiel). Es ist nicht gleichzeitig, aber ich erwarte, dass es am Ende zu einem besseren Durchsatz führt, als wenn das System eine ganze Pause für die Garbage-Collection ein paar zusätzliche Male verlangt.

Oh, und eine letzte Anmerkung zu Integer-Keys und weakKeys (): MapMaker verwendet einen Identitätsvergleich für Keys, wenn schwache oder weiche Keys verwendet werden, und das ist ziemlich schwer richtig zu machen. Zeuge das Folgende:

%Vor%

Viel Glück.

    
Darren Gilroy 10.07.2010 05:43
quelle
3

Schwache Schlüssel scheinen ein Fehler zu sein. Verwenden Sie starke Schlüssel, da sie Ganzzahlen sind.

    
Craig P. Motlin 09.07.2010 12:23
quelle
0

Ich möchte Ihre Aufmerksamkeit auf Suppliers.memoizeWithExpirationm, Instant-Cache lenken.

Ссылка , long, java.util.concurrent.TimeUnit)

    
BjornS 09.08.2010 12:39
quelle

Tags und Links