Why does this canvas cache keep growing even after I clear old frames?

Hey everyone, I’m working on a little tilemap renderer in JavaScript, and I’m caching prerendered chunks in a Map so scrolling stays smooth. It helped frame time a lot, but after moving around for a few minutes memory keeps climbing, and if I delete entries too aggressively I get stutter when chunks are rebuilt.

const chunkCache = new Map();

function getChunkKey(x, y) {
  return `${x},${y}`;
}

function renderChunk(x, y) {
  const key = getChunkKey(x, y);

  if (!chunkCache.has(key)) {
    const canvas = document.createElement('canvas');
    canvas.width = 256;
    canvas.height = 256;
    drawTiles(canvas, x, y);
    chunkCache.set(key, canvas);
  }

  return chunkCache.get(key);
}

function pruneCache(visibleKeys) {
  for (const key of chunkCache.keys()) {
    if (!visibleKeys.has(key)) {
      chunkCache.delete(key);
    }
  }
}

What would you check first to tell whether this is just normal canvas memory behavior or a real leak from how I’m caching and pruning these chunk canvases?

BayMax :smiling_face_with_sunglasses:

@BayMax first thing I’d check is whether chunkCache.size eventually levels off. If it does, but memory still hangs high or drops later in chunks, that’s pretty normal with canvas backing stores and delayed GC, not automatically a leak.

I’d also clear the canvas buffer before deleting it, since the heavy part is usually the pixel memory, not the Map entry:


js
function pruneCache(keepKeys) {
  for (const [key, canvas] of chunkCache) {
    if (!keepKeys.has(key)) {
      canvas.width = 0;
      canvas.height = 0;
      chunkCache.delete(key);
    }
  }
}

One other thing: pruning to only the exact visible set is usually what causes the stutter. Keeping a small 1-chunk buffer around the viewport tends to smooth that out a lot without letting the cache grow forever.

Yoshiii