PixiJS Performance — Optimizing 2D Rendering
In this tutorial, you will learn about PixiJS Performance. We cover key concepts, practical examples, and best practices to help you master this topic.
PixiJS performance optimization focuses on reducing draw calls, efficient texture management, memory pooling, and profiling to maintain 60fps.
What You'll Learn
By the end of this guide, you will reduce draw calls with sprite batching, use texture atlases to minimize texture swaps, cache complex graphics with render textures, use object pooling for particles, and profile with PixiJS debug tools.
Batch Sprites
// Use the same texture for all sprites to maximize batching
var texture = PIXI.Texture.from('tile.png');
for (var i = 0; i < 1000; i++) {
var sprite = new PIXI.Sprite(texture);
app.stage.addChild(sprite);
}
// All 1000 sprites render in 1-2 draw calls
Texture Atlas
PIXI.Assets.load('atlas.json').then(function() {
var frame1 = PIXI.Texture.from('icon1.png');
var frame2 = PIXI.Texture.from('icon2.png');
// Using frames from a single atlas reduces texture swaps
});
Object Pooling
var bulletPool = [];
function getBullet() {
return bulletPool.pop() || new Bullet();
}
function returnBullet(bullet) {
bullet.visible = false;
bulletPool.push(bullet);
}
Performance Profiling
// Display FPS
var fpsText = new PIXI.Text('FPS: 0', { fill: '#ffffff' });
app.stage.addChild(fpsText);
app.ticker.add(function() {
fpsText.text = 'FPS: ' + Math.round(app.ticker.FPS) +
' | Draw Calls: ' + app.renderer.geometry.drawCalls;
});
Common Mistakes
1. Using Many Different Textures
Each texture change breaks the batch. Use texture atlases to minimize switches.
2. Creating Graphics Each Frame
Creating new Graphics objects every frame causes Garbage Collection spikes. Pre-create and reuse.
3. Not Using Pooling
Creating and destroying objects frequently causes GC pauses. Use object pools.
4. Large Canvas Render Area
A 1920x1080 canvas with many sprites drops to 30fps on mobile. Use a smaller canvas or scale.
5. Ignoring Draw Calls
Target under 50 draw calls for smooth 60fps. Monitor with renderer debug stats.
Practice Questions
Q1: How do draw calls affect performance? A: Each draw call is a CPU-to-GPU round trip. Fewer calls = faster rendering.
Q2: What breaks sprite batching? A: Changing texture, blend mode, or shader between sprites.
Q3: How does a texture atlas help? A: All sprites share one texture, keeping them in the same batch.
Q4: What is object pooling? A: Reusing objects instead of creating/destroying them to avoid GC.
Q5: How do you measure FPS in PixiJS? A: Use app.ticker.FPS or monitor app.renderer.plugins.sprites.
Challenge: Build a particle system with 2000 particles using object pooling. Display draw call count and FPS. Compare performance with and without pooling.
FAQ
Try It Yourself
Monitor draw calls and FPS.
<!DOCTYPE html>
<html>
<head>
<title>PixiJS Performance</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/7.3/pixi.min.js"></script>
</head>
<body style="font-family:sans-serif;padding:20px;">
<h2>Performance Monitor</h2>
<button onclick="addSprites(100)">Add 100</button>
<button onclick="clearSprites()">Clear</button>
<script>
var app = new PIXI.Application({ width: 500, height: 350, background: 0x1a1a2e });
document.body.appendChild(app.view);
var fpsText = new PIXI.Text('FPS: 0 | Draws: 0 | Sprites: 0', {
fill: '#ffffff',
fontSize: 14
});
fpsText.x = 10;
fpsText.y = 10;
app.stage.addChild(fpsText);
var spriteContainer = new PIXI.Container();
app.stage.addChild(spriteContainer);
// Create a reusable texture
var g = new PIXI.Graphics();
g.beginFill(0x4ecdc4);
g.drawCircle(0, 0, 8);
g.endFill();
var tex = app.renderer.generateTexture(g);
function addSprites(count) {
for (var i = 0; i < count; i++) {
var s = new PIXI.Sprite(tex);
s.x = Math.random() * 480 + 10;
s.y = Math.random() * 300 + 40;
s.scale.set(0.5 + Math.random());
s.tint = Math.random() * 0xffffff;
spriteContainer.addChild(s);
}
}
function clearSprites() {
spriteContainer.removeChildren();
}
app.ticker.add(function() {
var draws = app.renderer.drawCalls || app.renderer.geometry.drawCalls || 0;
fpsText.text = 'FPS: ' + Math.round(app.ticker.FPS) +
' | Draws: ' + draws +
' | Sprites: ' + spriteContainer.children.length;
});
</script>
</body>
</html>
What's Next
Build a complete PixiJS project.
Project — Complete PixiJS project.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro