The device that matters
Develop on a fast machine and everything is fine. The device that determines whether your game is good is a mid-range phone a few years old, which is several times slower, has less memory, throttles under heat and is running a browser with less headroom.
The practical implication is that performance work should be targeted at that device rather than at a profiler on a desktop. A game that runs at sixty frames on a laptop and thirty on a phone has a phone problem, and the phone is where most of your players are.
Ranked by impact
| Optimisation | Typical impact | Effort |
|---|---|---|
| Cap device pixel ratio at 2 | Very large | Two lines |
| Pool objects instead of allocating | Large - removes stutter | Small |
| Cap particle counts globally | Large under load | Small |
| Cull off-screen entities | Moderate to large in scrolling games | Small |
| Avoid allocation in the draw loop | Moderate - removes stutter | Discipline |
| Draw rather than load images | Moderate - removes decode and memory | Design decision |
| Pause when the tab is hidden | Battery, not frame rate | Three lines |
| Micro-optimising maths | Negligible | Wasted |
The top four account for nearly all of the difference in our experience. The last row is there because it is where a lot of optimisation effort goes and it almost never matters in a canvas game.
Advertising keeps Candy Arcade free. Ads never cover gameplay or controls.
Device pixel ratio is the big one
A 3x display renders nine times the pixels of a 1x display. On a phone screen held at arm's length, the difference between 2x and 3x is barely visible and the cost is enormous.
Capping at 2 is the single largest performance lever available in a canvas game, and it is two lines: take the minimum of devicePixelRatio and 2, and apply that as both the buffer multiplier and the context transform scale.
Stutter is not slowness
These feel similar and have different causes. Consistently low frame rate means you are drawing too much. Periodic hitching in an otherwise smooth game almost always means garbage collection.
Garbage comes from allocation: creating objects, arrays, strings or closures during play. A collection game that allocates one object per collectible spawn generates hundreds per minute, and on a phone the collector runs often enough to be felt.
The fix is pooling. Keep discarded objects in a free list and reuse them. Our pool holds up to 256 spares and the active list is compacted once per frame rather than spliced during iteration.
Splicing an array during iteration is both a correctness hazard and a source of allocation. Mark dead, sweep once, reuse.
Cap what can combine
Particles are the classic case. A single burst is cheap; twenty simultaneous bursts are not, and pickups do cluster.
Cap globally rather than per emitter, so simultaneous bursts cannot combine into a frame drop, and drop excess rather than queueing it. A burst slightly smaller than intended is imperceptible; a dropped frame is not.
Our cap is 220 particles with lifetimes under a second, which means the system clears itself rather than accumulating across a long run.
Procedural art as a performance strategy
Drawing everything from code rather than loading images removes several mobile-specific costs at once: image decode time on a slower CPU, texture memory on a device with less of it, and the need to ship multiple resolution variants.
It also removes the loading state entirely, which matters for a different reason: a browser game competes with everything else on the device for attention, and a game that starts playing in under a second keeps people who would otherwise leave.
The trade is CPU per frame. At the visual complexity an arcade game needs, that is comfortably affordable.
Measure at the worst moment
The most common profiling error is measuring the calm opening of a game. Frame rate matters during the densest section, when particle bursts are combining and entity counts are highest.
Practical method: play to the point where the game is busiest, and watch the frame time there. If it holds under sixteen milliseconds on a mid-range phone during the worst moment, it will hold everywhere.
Common mistakes
- Profiling on a desktop onlyThe device that determines whether your game is good is a mid-range phone, which is several times slower.
- Leaving device pixel ratio uncappedA 3x display costs nine times the pixels of 1x for barely visible benefit.
- Allocating during playGarbage collection stutter is the most common mobile performance problem and it is invisible on desktop.
- Capping particles per emitterBursts combine. The cap has to be global.
- Measuring the calm openingFrame rate matters during the densest section, not the first ten seconds.
Practical tips
- If a browser game hitches periodically rather than running slowly, it is allocating during play.
- Reduced motion lowers particle counts, which also helps on older devices.
- Games here pause automatically when you switch tabs, so nothing is lost.
- Instant starts are a consequence of having no assets to download.
- Judge a game's performance during its busiest moment rather than its opening.
Key takeaways
- Target a mid-range phone, not a development machine.
- Capping device pixel ratio at 2 is the largest single lever.
- Stutter means allocation; low frame rate means draw cost. They have different fixes.
- Cap combinable effects globally and drop excess rather than queueing.
- Procedural art removes decode time, texture memory and resolution variants.
- Measure during the densest moment of the game.
Frequently Asked Questions
Why do some browser games stutter on phones but not on desktop?
Almost always garbage collection from allocating objects during play. Desktops have enough headroom to hide it; phones do not.
What is the single biggest performance win in a canvas game?
Capping device pixel ratio at 2. A 3x display renders nine times the pixels of 1x for barely visible benefit.
Why do Candy Arcade games start instantly?
Because there are no assets to download or decode. All artwork is drawn from code and all audio is synthesised.
Do the games keep running if I switch tabs?
No. They pause automatically and tell you so, because running in the background drains battery and browsers throttle background timers unpredictably.
How should I judge a browser game's performance?
During its densest moment rather than its opening, on a mid-range phone rather than a fast computer.
Read next
- how canvas handles collectibles — rendering detail
- how to design mobile-friendly candy games — the wider mobile article
- how responsive canvas scaling works — pixel ratio in detail
- how HTML5 candy games work — the whole stack
- Endless Candy Collector — the densest entity counts here
References
- Optimizing canvas - MDN Web Docs — Canvas-specific performance guidance.
Every external source listed here has been read. We do not cite sources we have not checked, and we do not invent references. See our fact-checking policy.