Efficient memory usage with Memory Pool

This article, SE Nguyen Ngoc Tu of NAL, will provide you with a reference for memory management using Memory Pool.

he balance between speed and memory usage is continually a headache for programmers. When facing this problem, programmers must consider whether to prioritize speed or memory. Memory is always one of the top concerns in applications that run for long periods. During the application lifecycle, objects are continually being created and destroyed, thus defragging the memory. If memory management is not good, it will waste resources, leading to the system quickly running out of memory. In case programming for resource-limited devices, both are important. Finding the right balance between performance and memory usage is not always easy.

This article, SE Nguyen Ngoc Tu of NAL, will provide you with a reference for memory management using Memory Pool.
Memory Pool is a technique that helps to exploit memory effectively by initializing a fixed memory area and then managing the allocation and recycling of objects in that memory.

To understand how Pool works, let us put the following hypothetical scenario
A film director receives a script where there are more than 100 characters, but he only has ten actors in his hand. How to complete the film with more than 100 characters in hand with only ten actors? The answer, in this case, is simple: for each actor to play different roles.
Try a different situation: How to destroy 1000 enemy airplanes with only ten bullets in your hand? : D. You will wonder how practical it is to do so, but if you have ever played a shooting game like SkyForce, this is entirely possible from the point of a programmer. Of course, players just shoot and shoot without knowing that they only have ten bullets!!! This situation, compared to the above case, is no different from the perspective of Pool.
Now we examine the source code of this game (although written in Java, thoughtfully it can apply to other languages and platforms):

A game with a machine gun with 1000 bullets, shooting continuously at a target in 10m. The game will end when the machine gun runs out of shots.
Now we examine the source code of this game (although written in Java, thoughtfully it can apply to other languages and platforms):
Describe the class of bullets, with one basic property, is its position over time (in m):

public class Bullet {
    private int position;

    public int getPosition() {
         return position;
    }

    public void setPosition(int position) {
         this.position = position;
    }

    public Bullet() {
    }

    public void move() {
         position++;
    }
}

The メモリープール class (the source code of メモリープール from box2d.org) allows to create a pool for a specific group of objects:

import java.util.LinkedList;

public abstract class MemoryPool<T> {
    private LinkedList<T>; free_items = new LinkedList<T>();
    public void freeItem(T item) {
        free_items.add(item);
    }
    protected abstract T allocate();
    public T newItem() {
        T out = null;
        if ( free_items.size() == 0 ) {
             out = allocate();
        } else {
             out = free_items.getFirst();
             free_items.removeFirst();
        }
        return out;
    }
}

We see that メモリープール uses a FreeList data structure where free_items is a linked list that stores objects released at the end of their role, and they will be reused in the newItem() method. メモリープール has a method allocate() that is used to create new actual objects, instead of creating and reusing like the newItem().
The BulletPool class is a メモリープール, which is implemented as follows:

public class BulletPool extends MemoryPool<Bullet> {
    @Override
    protected Bullet allocate() {
        return new Bullet();
    }
}

The Gun class, which describes a machine gun with the ability to shoot economically (use Pool) or unsparingly (not use Pool).

public class Gun {
    private int bulletCount=1000;
    public void fireInPool() {
         BulletPool pool=new BulletPool();
         List<Bullet>; plist=new ArrayList<>();
         for(int i=0;i<bulletCount;i++) {
             Bullet p=pool.newItem();
             p.setPosition(0);
             plist.add(p);
             for(int j=0;j<plist.size();j++) {
                 Bullet pp=plist.get(j);
                 pp.move();
                 System.out.print("-"+pp.getPosition());
                 if(pp.getPosition()==10) {
                      pool.freeItem(pp);
                      plist.remove(pp);
                 }
             }
             System.out.println();
         }
    }

    public void fire() {
         List<Bullet> plist=new ArrayList<>();
         for(int i=0;i<bulletCount;i++) {
              Bullet p=new Bullet();
              p.setPosition(0);
              plist.add(p);
              for(int j=0;j<plist.size();j++) {
                  Bullet pp=plist.get(j);
                  pp.move();
                  System.out.print("-"+pp.getPosition());
                  if(pp.getPosition()==10) {
                      plist.remove(pp);
                  }
              }
              System.out.println();
        }
    }
}

Finally, the gameplay:

public class DemoMemoryPool {
    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) {
        Gun gun=new Gun();
        System.out.println("Start");
        gun.fireInPool();
        gun.fire();
        System.out.println("Game over");
    }
}

Now we use Profiler to measure the memory usage of the object Bullet. We see the results very clearly. When you don't use Pool to fire 1000 bullets, you need to initialize 1000 Bullet objects, while with the Pool you only need to initialize 11 objects:
Interestingly, These 11 objects do not depend on the number of iterations but on the condition of releasing the objects. (in this example, at position = 10)
Thus, we can see that cleverly using the Pool will thoroughly solve memory limitations in the application, especially games or real-time interactive applications. Of course, the actual implementation of Pool also depends on platforms and specific problems. Hopefully, through this article, programmers will have one more solution and idea for everyday issues.

Original article: https://media.nal.vn/efficient-memory-usage-with-memory-pool

Comments are closed.