Course contentsShow
← C#
Lesson 226 of 1,9082. Object-Oriented Design in C#Free lesson

Object Pooling for Performance

You will reuse expensive objects instead of destroying and recreating them to reduce GC spikes.

In this lesson, you will learn how to boost your application's performance by reusing expensive objects instead of constantly creating and destroying them.

The Problem: Garbage Collector Pressure

In C#, every time you use the new keyword, you allocate memory on the heap. When you are finished with that object, the Garbage Collector (GC) must eventually wake up to clean it up. If you do this thousands of times per second—like spawning bullets in a game or processing rapid network packets—the GC will constantly trigger "stop-the-world" pauses. These spikes lead to stuttering and poor performance.

The Solution: The Object Pool

Instead of throwing an object away, imagine placing it into a "waiting room" (the pool). When your application needs a new object, it first checks the pool. If an object is sitting there, you "check it out" and reset its data. Only if the pool is empty do you pay the cost of new to create a fresh one.

Here is a simplified look at how this works:

public class BulletPool {
    private readonly Stack<Bullet> _pool = new Stack<Bullet>();

    public Bullet GetBullet() {
        // Reuse an existing object, or create one if the pool is empty
        return _pool.Count > 0 ? _pool.Pop() : new Bullet();
    }

    public void ReturnBullet(Bullet bullet) {
        bullet.Reset(); // Clear old state
        _pool.Push(bullet); // Return to pool for later use
    }
}

Why This Matters

By reusing the Bullet objects, you stabilize your application's memory usage. Because you aren't constantly creating new instances, the Garbage Collector has much less work to do. This keeps your program running smoothly without sudden drops in frame rate or responsiveness.

It is important to remember that this pattern is best for "expensive" objects—those that take time to initialize or contain large amounts of data. Using it for simple, tiny objects is often unnecessary overhead. Always measure your performance to ensure that the complexity of the pool actually provides the benefit you expect.

Key Takeaway: Object pooling trades memory complexity for performance by recycling existing objects, effectively silencing the Garbage Collector and preventing performance-killing memory spikes.