Когда и зачем нужен класс Pool для хранения объектов?

12

Я изучал OpenGLES, и один из примеров, который я видел, это использование класса «Pool» для отслеживания событий касания и клавиатуры.

Может кто-нибудь объяснить, как и почему нужен класс пула. Из того, что я читал, это было как-то связано со сборкой мусора и ограничением количества вводимых классов.

Все это кажется мне немного абстрактным, поэтому, если кто-то может объяснить, что происходит, я был бы признателен, я вставил сюда некоторый код:

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

Благодарность!

mathacka
источник

Ответы:

17

Пулы используются, когда количество объектов будет сильно колебаться, и используются для уменьшения объема выделяемой памяти и сбора мусора.

При использовании пула стандартный новый Object (), который выделяет новую память, заменяется извлечением уже выделенного объекта из пула. Это намного быстрее, даже если вы идете и сбрасываете каждую переменную в старом объекте на значение по умолчанию.

Если вы создаете новый элемент каждый раз, когда у вас огромные накладные расходы, память должна быть выделена для каждого объекта. Кроме того, поскольку вы создаете так много объектов, вы должны часто их очищать, что приводит к очень частому запуску сборщика мусора, что снижает производительность.

Типичным примером являются пули.

Для FPS на экране может быть 0 пуль, затем 1000 в следующую секунду, а затем 0 снова через секунду после этого. Если бы вы создавали новую пулю для каждого запускаемого файла, постоянное выделение памяти было бы чрезвычайно требовательным к производительности. Кроме того, сборщик мусора должен отслеживать все эти случаи и периодически очищать, что занимает еще больше времени.

Если у вас есть пул из 5000 пуль, и вы обновляете и взаимодействуете только с теми, которых нет в списке freeObjects, у вас всего 5000 выделений, независимо от того, как долго длится перестрелка, вместо 1 выделения на пулю. Кроме того, сборщик мусора должен работать только после того, как любая возможность перестрелки закончилась. Взаимодействие с памятью происходит очень медленно, поэтому это оказывает огромное влияние на производительность и обеспечивает равномерное распределение рабочей нагрузки, предотвращая заикания кадров.

ClassicThunder
источник
Так что я думаю, что пул-класс для эффектов частиц был бы крайне необходим, я прав?
Mathacka
Да, именно для этого и были созданы пулы ситуаций.
ClassicThunder
Лучше ли иметь пул классов с собственными объектами или использовать фабрику? Т.е. Object.getObject () против ObjectFactory.getObject ()