Wann und warum wird eine Pool-Klasse benötigt, um Objekte aufzunehmen?

12

Ich habe Opengles studiert und ein Beispiel dafür war die Verwendung einer "Pool" -Klasse, um Tastatureingaben und Tastaturereignisse zu verfolgen.

Könnte jemand bitte erklären, wie und warum eine Poolklasse benötigt wird. Was ich gelesen habe, hat etwas mit Garbage Collection und der Begrenzung der Anzahl der Eingabeklassen zu tun, die erstellt werden.

Dies alles scheint mir ein wenig abstrakt zu sein. Wenn also jemand erklären könnte, was vor sich geht, würde ich es begrüßen, wenn ich hier Code einfügen würde:

    public Pool(PoolObjectFactory <> factory, int maxSize) {            
        this.factory = factory;         
        this.maxSize = maxSize;         
        this.freeObjects = new ArrayList < T > (maxSize);     
    }  
         
    public T newObject() {        
        T object = null ;        
        if (freeObjects.isEmpty())            
            object = factory.createObject();        
        else             
            object = freeObjects.remove(freeObjects.size() - 1);        
            return object;     
    } 

    public void free(T object) {         
        if (freeObjects.size() < maxSize)             
            freeObjects.add(object);     
    }

    PoolObjectFactory <TouchEvent> factory = new PoolObjectFactory <TouchEvent> () {
     
    @Override     
    public TouchEvent createObject() {         
         return new TouchEvent();     
    } 

    Pool <TouchEvent> touchEventPool = new Pool <TouchEvent> (factory, 50); 
    TouchEvent touchEvent = touchEventPool.newObject(); 
    . . . do something here . . . 
    touchEventPool.free(touchEvent);

Vielen Dank!

Mathacka
quelle

Antworten:

17

Pools werden verwendet, wenn die Anzahl der Objekte stark schwankt, und werden verwendet, um die Speicherzuweisung und die Speicherbereinigung zu verringern.

Unter Verwendung eines Pools wird das standardmäßige neue Objekt (), das neuen Speicher zuweist, ersetzt, indem ein bereits zugewiesenes Objekt aus dem Pool gezogen wird. Dies ist viel schneller, selbst wenn Sie alle Variablen im alten Objekt auf einen Standardwert zurücksetzen.

Wenn Sie jedes Mal ein neues Objekt erstellen, muss jedem Objekt ein hoher Overhead als Speicher zugewiesen werden. Auch weil Sie so viele Objekte erstellen, müssen Sie diese häufig bereinigen, was dazu führt, dass der Garbage Collector sehr oft ausgeführt wird, was die Leistung weiter beeinträchtigt.

Ein häufiges Beispiel sind Aufzählungszeichen.

Für einen FPS können 0 Kugeln auf dem Bildschirm sein, dann 1000 in der nächsten Sekunde und dann wieder 0 in der Sekunde danach. Wenn Sie für jeden einzelnen Schuss eine neue Kugel erstellen, ist die konstante Speicherzuweisung äußerst leistungsintensiv. Außerdem muss der Garbage Collector alle diese Instanzen nachverfolgen und die Daten regelmäßig bereinigen, was noch mehr Zeit in Anspruch nimmt.

Wenn Sie über einen Pool von 5.000 Kugeln verfügen und nur die nicht in der freeObjects-Liste aufgeführten aktualisieren und mit ihnen interagieren, haben Sie nur 5.000 Gesamtzuweisungen, unabhängig davon, wie lange der Feuergefecht dauert, anstatt 1 Zuweisung pro Kugel. Auch der Garbage Collector muss erst laufen, wenn die Möglichkeit eines Feuergefechts beendet ist. Die Interaktion mit dem Speicher ist sehr langsam, was sich enorm auf die Leistung auswirkt und sicherstellt, dass die Arbeitslast gleichmäßig verteilt wird, sodass es nicht zu Bildstörungen kommt.

ClassicThunder
quelle
Ich denke also, eine Poolklasse für Partikeleffekte wäre extrem wichtig, oder?
Mathacka
Ja, genau für diese Art von Situation wurden Pools entwickelt.
ClassicThunder
Ist es besser, einen Klassenpool mit eigenen Objekten zu haben oder eine Fabrik zu benutzen? Dh Object.getObject () vs ObjectFactory.getObject ()