Quando e perché è necessaria una classe Pool per contenere oggetti?


12

Ho studiato le opzioni e un esempio che ho visto è stato l'utilizzo di una classe "Pool" per tenere traccia degli eventi tattili e della tastiera.

Qualcuno potrebbe spiegare come e perché è necessaria una classe di pool. Da quello che stavo leggendo aveva qualcosa a che fare con la garbage collection e la limitazione del numero di classi di input che sono state create.

Tutto questo mi sembra un po 'astratto, quindi se qualcuno potesse spiegare cosa sta succedendo, lo apprezzerei, incollerei un po' di codice qui:

    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);

Grazie!

Risposte:


17

I pool vengono utilizzati quando il numero di oggetti fluttuerà drasticamente e vengono utilizzati per ridurre la quantità di allocazione di memoria e garbage collection.

Utilizzando un pool, il nuovo Object () standard che alloca la nuova memoria viene sostituito con l'estrazione di un oggetto già allocato dal pool. Questo è molto più veloce anche se vai e ripristini tutte le variabili nel vecchio oggetto su un valore predefinito.

Se crei un nuovo elemento ogni volta che hai un enorme overhead poiché la memoria deve essere allocata per ogni oggetto. Inoltre, poiché stai creando così tanti oggetti, devi pulirli spesso, il che fa sì che il Garbage Collector venga eseguito molto spesso, danneggiando ulteriormente le prestazioni.

Un esempio comune sono i proiettili.

Per un FPS ci possono essere 0 proiettili sullo schermo, quindi 1000 il secondo successivo e poi 0 di nuovo il secondo successivo. Se si dovesse creare un nuovo proiettile per ogni singolo sparato, l'allocazione costante della memoria richiederebbe prestazioni estremamente elevate. Inoltre, il garbage collector deve tenere traccia di tutte queste istanze e ripulire periodicamente, il che richiede ancora più tempo.

Se hai un pool di 5000 proiettili e aggiorni e interagisci solo con quelli non presenti nell'elenco FreeObjects hai solo 5000 allocazioni totali, indipendentemente dalla durata dello scontro a fuoco invece di 1 allocazione per proiettile. Inoltre, il garbage collector deve funzionare solo una volta terminata qualsiasi possibilità di uno scontro a fuoco. L'interazione con la memoria è molto lenta, quindi questo ha un impatto enorme sulle prestazioni e assicura che il carico di lavoro sia distribuito uniformemente evitando gli scatti della frequenza dei fotogrammi.


Quindi sto pensando che una classe di pool per effetti particellari sarebbe estremamente essenziale, vero?
Mathacka,

Sì, esattamente per il tipo di pool di situazioni per cui sono stati progettati.
ClassicThunder

È meglio avere un pool di classi i propri oggetti o usare una factory? Vale a dire Object.getObject () vs ObjectFactory.getObject ()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.