Pixi.js Memory Management and Garbage Collection
Web applications utilizing Pixi.js require diligent memory management to maintain high frame rates and prevent browser crashes caused by memory leaks. This article explores how Pixi.js handles resource allocation and garbage collection, detailing the manual destruction of sprites, the lifecycle of textures on the GPU, and how Pixi’s built-in automatic garbage collector assists in freeing system resources.
Sprite Destruction and CPU Memory
When you remove a sprite from the render stage using
stage.removeChild(sprite), the sprite is only unlinked from
the scene graph. It remains in system memory (CPU) because JavaScript’s
native garbage collector cannot reclaim it if references to it still
exist in your code.
To properly dispose of a sprite, you must call its
destroy() method. By default, calling
sprite.destroy() frees up the sprite’s internal references,
making it eligible for JavaScript garbage collection. However, you can
pass options to this method to control how associated resources are
handled:
sprite.destroy({
children: true, // Recursively destroys all children of this container
texture: true, // Destroys the sprite's texture reference
baseTexture: true // Destroys the underlying image source and unloads it from the GPU
});Using these options ensures that not only the sprite container is freed, but also the heavy graphical assets linked to it.
Texture vs. BaseTexture on the GPU
In Pixi.js, memory is split between system RAM (CPU) and video RAM
(GPU). Understanding the distinction between Texture and
BaseTexture is critical for memory management:
- BaseTexture: This holds the actual image source (such as an HTMLImageElement or HTMLCanvasElement) and represents the actual WebGL texture uploaded to the GPU’s memory.
- Texture: This is a lightweight wrapper that
references a
BaseTextureand defines a specific frame (UV coordinates). Multiple sprites can share a singleBaseTexturevia differentTextureinstances (e.g., in a spritesheet).
If you destroy a Texture without destroying its
BaseTexture, the image data remains resident in the GPU
memory. To completely purge an image from the GPU, you must call
baseTexture.dispose() or
texture.destroy(true).
The Automatic Texture Garbage Collector
Pixi.js features an automated system called the
TextureGarbageCollector (managed by the renderer) to
prevent GPU memory bloat from inactive textures.
Instead of keeping all loaded textures in WebGL memory indefinitely, the garbage collector periodically scans active textures. If a texture has not been used in a render pass for a specified number of frames, the collector automatically unbinds and unloads the texture from the GPU.
You can configure the behavior of the texture garbage collector via the renderer settings:
// Example configuration for Pixi.js WebGL renderer
renderer.textureGC.mode = PIXI.GC_MODES.AUTO; // Enables automatic GC
renderer.textureGC.maxIdle = 3600; // Number of frames a texture can be idle before removal
renderer.textureGC.checkCountMax = 600; // How often (in frames) the GC runs its checkWhen the automatic garbage collector unloads a texture, the data is removed from the GPU but remains in the CPU’s system memory. If the application requests that texture again, Pixi.js automatically re-uploads the image to the GPU on the next render frame.
Asset Management with Assets (Pixi.js v7+)
In modern versions of Pixi.js, the Assets class is the
preferred tool for loading and managing resources. It automates much of
the manual memory management:
- Assets.load(): Loads and caches textures.
- Assets.unload(): Properly disposes of both the
Textureand the underlyingBaseTexturefrom CPU and GPU memory simultaneously, ensuring no orphan memory blocks remain.
By utilizing Assets.unload() and explicitly passing
destruction flags to your sprites, you can maintain precise control over
your application’s memory footprint and ensure consistent performance
across all devices.