Guide

Lag that builds up over a long game

If a map runs fine at minute 5 and crawls at minute 50, it is almost always leaking: objects created every few seconds that nothing removes.

What you see

  • Frame rate and responsiveness drop over 30 to 60 minutes.
  • Lag spikes grow into short freezes, especially when big waves spawn or die.
  • The game's memory use keeps climbing, and very long games may crash near the end.

Why it happens

Many GUI actions create an object you never see. Center of (Playable map area) creates a point, Units in (Playable map area) creates a unit group (even inside a condition), All enemies of Player 1 creates a player group, and Create Special Effect creates an effect. Nothing removes them, so a trigger that runs every second leaks every second.

In JASS, a local variable that still points to a unit, group, timer or effect when the function ends holds a reference, and the handle's id is never recycled.

Lua's garbage collector frees Lua data only. Game objects such as locations and groups leak in Lua maps the same way.

Floods hurt too: one dummy unit per missile, floating texts with no lifespan, tens of thousands of doodads.

How to fix it

  1. Store the object in a variable, use it, then destroy it with RemoveLocation, DestroyGroup, DestroyForce or DestroyEffect. In GUI, use custom script lines for the destroy calls, or the GUI actions 3.0 added for them.
  2. Before a GUI group action, set bj_wantDestroyGroup = true makes the next group clean itself up.
  3. Never destroy All players: it is a constant.
  4. JASS: destroy first, then set the local to null, before every return.
  5. Give floating texts a lifespan, reuse dummy units for missiles, and cap how many units a wave keeps alive.

How WC3 Map Doctor detects it

Rules that look for this
  • Warnings
    A location is stored and never removed, so every call leaks one.
    PERF-L01 · auto-fix: local-location-remove
  • Warnings
    A group made by a BJ function is neither destroyed nor flagged with bj_wantDestroyGroup, so it leaks.
    PERF-L02
  • Warnings
    A force made by a BJ function is never destroyed, so it leaks.
    PERF-L03
  • Severe
    A special effect is created and its handle thrown away, so it can never be destroyed.
    PERF-L04
  • Info
    A handle local is not set to null before the function returns.
    PERF-L05
  • Warnings
    A floating text is created with no lifespan, so it stays until the cap (100 before 3.0) is reached.
    PERF-X01
  • Severe
    A periodic timer with a 0 s period runs every frame.
    PERF-T01

Operations that fix it on a copy

  • leak.hot Stop handle leaks in code that runs all game
  • optimize.effects Destroy fire-and-forget effects

The scan also projects how many handles leak per minute and when the map would hit a game limit. That projection feeds the Stability grade.

Sources

Written in our own words from our lab notes; these are the pages behind them.