mapbox / mapbox/mapbox-gl-js

setData Trashes Memory -- Dynamic Lines are Unusable

Open
#12,948 6 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

performance :zap:
Dominant language
TypeScript
Stars
12.4k
Forks
2.4k
PR merge metrics
No merged PRs in 30d

Description

I am trying to dynamically update a simple line (using a geojson source) on each frame, and am seeing constant CPU usage of 200-300%, and animation that starts stuttering after around 20 seconds. It gets increasingly worse, with frames frequently taking several hundred ms after a few minutes runtime.

This happens in both Chrome and Firefox, on both Linux and Mac, with both Mapbox GL JS v2.14 and v3, and with all map styles I've tried.

I see multiple similar issues about this in the past; #12400, #5252, #4618, #2607, and also on Stackoverflow, so this might not be a new problem.

The profiler shows that the frame is blocked due to **Major GC**, and memory seems to be allocated by **reloadTile** and its callees in "class G extends e.VectorTileWorkerSource".

![image](https://github.com/mapbox/mapbox-gl-js/assets/1812661/af2f6a9c-c83c-4ba6-8693-ad85959a3b14)

Perhaps this is by design, but in that case, is there any other way to dynamically modify a line? I'm trying to render a trivial route line from a moving vehicle on a map, which seems like a core functionality that should work efficiently? Having the UI stutter and freeze for several hundred ms at a time is not acceptable for our use case. The only workaround I've found is to use a custom layer with e.g. Three.js to render lines.

Minimum reproducible example below. It calls `setData` each frame with an empty line, and logs any frame taking > 30 ms. After some time (~30 seconds for me), this happens frequently, and if you leave it running for a few minutes there are much longer pauses. Some runs appear to be faster, then refreshing the page could make it slower again. (**Note:** In this code, I call `setData` 100 times per frame which seems to make the issue appear faster, but this is not needed, the same thing happens when called once per frame.)

https://jsbin.com/yegudivudi/edit?html,output

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked JSBin reproduction, which calls setData on a GeoJSON line each frame, and profile the resulting Major GC pauses. Trace allocations from reloadTile and its callees in VectorTileWorkerSource. Done means repeated updates no longer cause growing memory pressure, frequent long frame pauses, or severe animation stutter.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.