¿Cuándo y por qué se necesita una clase Pool para contener objetos?

12

He estado estudiando opengl es y un ejemplo que vi fue usar una clase "Pool" para hacer un seguimiento de los eventos táctiles y del teclado.

¿Podría alguien explicar cómo y por qué se necesita una clase de grupo? Por lo que estaba leyendo, tenía algo que ver con la recolección de basura y la limitación del número de clases de entrada que se realizan.

Todo esto me parece un poco abstracto, así que si alguien pudiera explicar lo que está sucediendo, lo agradecería, pegaré un código aquí:

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

¡Gracias!

mathacka
fuente

Respuestas:

17

Los grupos se usan cuando la cantidad de objetos fluctúa dramáticamente y se usan para reducir la cantidad de asignación de memoria y recolección de basura.

Al usar un grupo, el nuevo Objeto estándar () que asigna nueva memoria se reemplaza por extraer un objeto ya asignado del grupo. Esto es mucho más rápido incluso si va y restablece todas las variables en el objeto antiguo a un valor predeterminado.

Si crea un nuevo elemento cada vez que tiene una gran sobrecarga, ya que se debe asignar memoria para cada objeto. Además, debido a que está creando tantos objetos, debe limpiarlos con frecuencia, lo que hace que el recolector de basura se ejecute con mucha frecuencia, lo que perjudica aún más el rendimiento.

Un ejemplo común son las balas.

Para un FPS puede haber 0 viñetas en la pantalla, luego 1000 el siguiente segundo y luego 0 nuevamente el segundo después de eso. Si tuviera que crear una nueva viñeta para cada uno de los disparos, la asignación constante de memoria sería extremadamente intensiva en rendimiento. Además, el recolector de basura tiene que rastrear todas estas instancias y limpiar periódicamente, lo que lleva aún más tiempo.

Si tiene un grupo de 5000 viñetas y solo actualiza e interactúa con las que no están en la lista de FreeObjects, solo tiene 5000 asignaciones totales sin importar cuánto dure el tiroteo en lugar de 1 asignación por viñeta. Además, el recolector de basura solo necesita ejecutarse una vez que haya finalizado la posibilidad de un tiroteo. La interacción con la memoria es muy lenta, por lo que esto tiene un gran impacto en el rendimiento y asegura que la carga de trabajo se distribuya de manera uniforme, evitando tartamudeos de velocidad de fotogramas.

Trueno clásico
fuente
Así que estoy pensando que una clase de pool para efectos de partículas sería extremadamente esencial, ¿estoy en lo cierto?
mathacka
Sí, exactamente para qué tipo de situación se diseñaron los grupos.
ClassicThunder
¿Es mejor tener un grupo de clase con sus propios objetos o usar una fábrica? Es decir, Object.getObject () vs ObjectFactory.getObject ()