Profiling CPU and GPU
The wave that stutters
When a big wave of pests reaches the garden, Shard Garden stutters on budget Android phones. Kai suspects the particles, Remy suspects the network. Neither has measured.
Profiling means recording what the game actually did, millisecond by millisecond, so a guess becomes a fact. Course 1 opened the Performance panel. This lesson reads it like a professional, and adds the GPU.
First, record an honest profile:
- A clean browserChrome's guide records in an Incognito window, so extensions don't add noise.
- Slow the CPUIn the Performance panel's capture settings, CPU throttling slows the laptop. The guide uses 4x, and suggests 20x for pages aimed at low-end phones. Calibrate can match a real device.
- Or the real phonePlug a budget phone in by USB and profile it from the laptop: remote debugging.
Reading the flame chart
The flame chart shows the main thread over the recording. Left to right is time. Top to bottom is the call stack: each bar called the bars below it.
Tasks over 50 ms are long tasks: they get a red triangle, with the part over 50 ms shaded red. In the Frames row, a dropped frame, one Chrome couldn't draw in time, is red with a dense line pattern.
Quick check
In the flame chart, time runs from the top of the chart to the bottom.
- True
- False
Show the answer
False
Time runs left to right. Top to bottom is the call stack: each bar was called by the bar above it, so the bottom bars are the functions doing the actual work.
Self time and total time
Every function has two times:
- Self time: time spent in the function's own code.
- Total time: self time plus everything it called.
The Bottom-up tab sorts activities by the time they directly took, so the real worker floats to the top. The Call tree tab starts from the root activities and shows which ones caused the most work.
Read the numbers
1Function Self Total2updateGarden 0.4 11.23findPath 8.9 9.14drawPests 1.2 1.6
Which function should Kai optimise first?
- findPath
- updateGarden
- drawPests
Show the answer
findPath
findPath does 8.9 ms of work itself. updateGarden has a big total only because it calls findPath; its own code takes 0.4 ms.
Label your own code
Browser tools see function names, not game ideas. The User Timing API lets us add our own labels:
performance.mark('ai-start')performance.mark('ai-end')performance.measure('pest-ai', 'ai-start', 'ai-end')
The measure records the time between two marks, and browser tools can show it in the recording. Now "pest AI took 6 ms" sits right in the profile, and the same numbers can go into our field data.
When the GPU is the problem
- Draw callsEach draw call has a cost. MDN advises batching 1,000 sprites into one call. PixiJS batches sprites using up to 16 textures (depending on hardware), so spritesheets keep batches whole.
- Filters and masksPixiJS warns both are expensive: hundreds of masks really slow things down.
- Waiting on the GPUWebGL calls like getError and readPixels make the CPU stop and wait for the GPU, sometimes 1 ms or more each.
- Android GPU InspectorRecords the GPU on Android phones, frame by frame. Google now recommends the newer Android Performance Analyzer for games.
Profile pick
Each frame takes 24 ms, but the CPU flame chart is only busy for 7 ms. Every pest has its own glow filter.
What should Kai try first?
- Replace the per-pest glow filters with a glow drawn into the sprite art
- Rewrite findPath
- Turn off CPU throttling
Show the answer
Replace the per-pest glow filters with a glow drawn into the sprite art
The CPU is idle most of the frame, so the time is going to the GPU. Filters are expensive, and one per pest multiplies the cost. Baking the glow into the art removes them.
Time is one budget, memory another
Profiles show time. A game can also be fast and still crash, because it runs out of memory.
Bolt says: Next: how the garbage collector works, and what a phone does when memory runs out.
Fact-checked 11 October 2026
- Chrome DevTools: Analyze runtime performance developer.chrome.com
- Chrome DevTools: Performance features reference developer.chrome.com
- MDN: Performance.measure() developer.mozilla.org
- MDN: WebGL best practices developer.mozilla.org
- PixiJS: Performance tips pixijs.com
- Android Developers: Android GPU Inspector developer.android.com