Quando e por que uma classe Pool é necessária para armazenar objetos?

12

Venho estudando opengl es e um exemplo que vi foi o uso de uma classe "Pool" para acompanhar os eventos de toque e teclado.

Alguém poderia explicar como e por que uma classe de piscina é necessária. Pelo que eu estava lendo, isso tinha algo a ver com a coleta de lixo e limitar o número de classes de entrada que são feitas.

Tudo isso me parece um pouco abstrato, então, se alguém puder explicar o que está acontecendo, eu apreciaria, colarei algum código aqui:

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

Obrigado!

mathacka
fonte

Respostas:

17

Os conjuntos são usados ​​quando o número de objetos flutua dramaticamente e são usados ​​para reduzir a quantidade de alocação de memória e coleta de lixo.

Usando um pool, o novo Object () padrão que aloca nova memória é substituído por puxar um objeto já alocado do pool. Isso é muito mais rápido, mesmo se você redefinir todas as variáveis ​​no objeto antigo para o padrão.

Se você criar um novo item cada vez que houver uma sobrecarga enorme, a memória deverá ser alocada para cada objeto. Também porque você está criando tantos objetos, é necessário limpá-los com frequência, o que faz com que o coletor de lixo seja executado com muita frequência prejudicando ainda mais o desempenho.

Um exemplo comum são marcadores.

Para um FPS, pode haver 0 marcadores na tela, depois 1000 no segundo seguinte e 0 novamente no segundo depois disso. Se você criar um novo marcador para cada um deles disparado, a alocação de memória constante seria extremamente intensiva em desempenho. Além disso, o coletor de lixo precisa rastrear todas essas instâncias e limpar periodicamente, o que leva ainda mais tempo.

Se você tiver um pool de 5000 marcadores e atualizar e interagir apenas com os que não estão na lista freeObjects, terá apenas 5000 alocações totais, independentemente do tempo de duração do tiroteio, em vez de 1 alocação por marcador. Além disso, o coletor de lixo só precisa ser executado quando a possibilidade de um tiroteio terminar. A interação com a memória é muito lenta, portanto, isso causa um enorme impacto no desempenho e garante que a carga de trabalho seja distribuída uniformemente, evitando interrupções na taxa de quadros.

ClassicThunder
fonte
Então, eu estou pensando que uma aula de pool para efeitos de partículas seria extremamente essencial, certo?
Mathacka
Sim, para o qual exatamente foram criados os pools de situações.
ClassicThunder
É uma prática recomendada ter um pool de classes com seus próprios objetos ou usar uma fábrica? Ou seja Object.getObject () vs ObjectFactory.getObject ()