2016-08-10 3 views
0

Ich entwickle ein Spiel in Java, die im Grunde jede 1/60 Sekunde aktualisiert wird. Während eines solchen Updates werden viele Daten erzeugt, herumgereicht und dann nicht referenziert, nennen wir diese Daten-DTOs. Nach meinem Verständnis speichern die JVM und das Betriebssystem diese Daten auf dem Heap des Programms. Der Heap wird so aufgebaut, bis der JAVA GC ausgeführt wird, wodurch alle nicht referenzierten Daten als frei markiert und wiederverwendet werden können.erstellen und verwenden Sie einen temporären Heap

Jetzt, wie ich es sehe, ist dies unnötig und anfällig für gelegentliche Verzögerungen. Die Art und Weise, wie ich das Problem lösen möchte, besteht darin, einen zugewiesenen Teil des Speichers als temporären Heap zu verwenden. Dieser Heap wird verwendet, um alle temporären Daten zu speichern, die ich während des Aktualisierungsintervalls erstellt und weitergegeben habe. Und sobald ich das Ende meines Updates erreicht habe, ist keine Analyse mehr erforderlich, aber ich kann einfach sagen, dass der gesamte Chunk frei ist und auf diese Weise das gleiche Heap-Space-Update nach dem Update wieder verwendet. Ein bisschen wie tail-rekursive Stack-Frames. Eine andere Lösung wäre, nur änderbare DTO-Objekte zu verwenden und eine Menge davon zuzuordnen und sie einfach wiederzuverwenden, aber ich nutze den Vorteil, Dinge so unveränderbar wie möglich zu machen.

Dies ist ein Versuch, zu zeigen, was ich mit dem Code bedeuten:

void start(){ 
    Data data = System.allocateDatainMb(500); //allocate 500Mb of virtual memory 
    MagicHeap() mh = System.createAMagicHeap(data); //make a heap of it 
    mh.use(); //set all constructors to allocate on this heap 

    while(true){ 
     update(); 
     mh.clear(); 
    } 
} 

void update(){ 
    TmpData dto = Gamesystem.createALargePieceOfTemporaryData(); 
    someClass.doUpdateStuff(dto); 
} 

ich mit nicht allzu vertraut bin, wie Java verwaltet Speicher, aber ich hoffe, dass Sie meine Bedeutung bekommen.

Ist es in gewissem Maße möglich?

+0

Nein. Java ist nicht die geeignete Sprache für diese Tricks. Wechseln Sie zu C++, oder verwenden Sie Ihre Objekte erneut. – RealSkeptic

+0

Ich frage mich, warum Sie das für ein Problem halten? Ist Ihnen tatsächlich aufgefallen, dass GC Ihr Programm verlangsamt? Wenn nicht, sind Sie möglicherweise ohne Grund besorgt. – puhlen

+0

Ich bin nicht besonders besorgt, noch habe ich ein echtes Problem. Der GC ist jedoch bemerkenswert, aber ich habe hauptsächlich aus Neugier gefragt. – Jake

Antwort

0

Ich könnte etwas vermissen, aber ich bin mir ziemlich sicher, dass Sie das in Java nicht tun können, da es die eigene Speicherverwaltung von Java stören würde. Schließlich soll Java den Benutzer vor Low-Level-Speicherverwaltungsroutinen schützen.

Also würde ich vorschlagen, für den DTO-Pool-Ansatz, den Sie erwähnten. Eine Möglichkeit, dies zu verbessern, könnte darin bestehen, die Mutatoren (z. B. Setzer und andere Mutationsverfahren) zu verbergen und nur Factory-Methoden usw. zu erlauben, auf sie zuzugreifen (z. B. unter Verwendung der privaten Sichtbarkeit des Pakets). Dann haben Sie Fabriken, die scheinbar unveränderliche Instanzen erstellen und wiederverwenden und die Pools verwalten. Sie könnten sogar einen vorübergehenden "Überlauf" verarbeiten, d. H. Wenn Sie mehr Instanzen eines DTO benötigen, als der Pool tatsächlich bereitstellt.

Wenn Sie jedoch genau überlegen, werden Sie wahrscheinlich eine Menge Objekte finden, die Sie für kurzlebig halten, um tatsächlich längere Lebenszyklen zu haben, wenn sie richtig verwendet werden. Es sind wahrscheinlich nur Zwischenergebnisse einiger Berechnungen (wie Vektor-/Matrixmathematik), die Sie im nächsten Frame nicht brauchen, aber diese können oft direkt nach dem Erstellen verworfen werden und könnten auch in einigen Fällen vermieden werden (zB wenn Sie Primitive manuell verwenden) oder haben mulable Zwischenobjekte).

0

Was Sie versuchen, ist die JVM zu überlisten. Das ist nicht das, was du machen willst. Wenn Sie wirklich direkt mit der Speicherzuweisung spielen müssen, ist Java keine geeignete Sprache.

Java's GC ist optimiert für viele kurzlebige Objekte, es wird erwartet, dass die meisten Dinge aus dem Speicher freigegeben werden können, kurz nachdem sie hinzugefügt wurden. Die Möglichkeit, ein Caching-System einzurichten, kann die Leistung beeinträchtigen, da diese Objekte nicht mehr aus dem Speicher entfernt werden können, was bedeutet, dass der Heap weniger Platz hat und (FULL) GC-Pausen häufiger auftreten. Dies ist zusätzlich zu jedem Overhead, den das Caching-System selbst erzeugt.

Dies bedeutet nicht, dass Sie Speicherprobleme mit Java ignorieren sollten. Sie sollten vermeiden, Objekte unnötigerweise zu erstellen, und, was noch wichtiger ist, sollten Sie vermeiden, länger als nötig an einer Objektverweisliste zu bleiben, damit Sie dem GC erlauben, ihn zu bereinigen. Es wäre wahrscheinlich auch vorteilhaft, den GC auf die Bedürfnisse Ihres Programms abzustimmen und sicherzustellen, dass Sie den modernen G1 GC verwenden.

Wie bei jeder Leistungsoptimierung ist es wichtig, die Leistungsunterschiede Ihrer Änderungen zu messen. Eine Ahnung von dem zu entwickeln, was Sie für schneller halten, kann dazu führen, dass Sie sich Mühe geben und Komplexität für wenig bis keinen Gewinn oder noch schlimmer für einen Leistungsabfall hinzufügen. Stellen Sie sicher, dass Sie über reelle Zahlen verfügen, um Performance-Probleme zu beheben.

Verwandte Themen