mapbox / mapbox/mapbox-gl-js

Reduce slowness when loading many raster tiles at once

Open
#7,405 2 comments 3 reactions 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

We're bottlenecked on too many texture uploads occurring at the same time, and Webkit's timeline recorder confirms this:

image

It seems that uploading a single texture takes ~7.5ms per raster tile. On smaller screens, this is typically split up across multiple frames, but if you have a fast network and a big screen, many of the load events can happen within the same frame.

We should:
* [ ] Investigate why the calls to `texImage2D` and `generateMipmap` raster tile take a combined ~7.5ms. The tiles in the screenshot above `@2x` tiles (512×512), but even then ~7.5ms seems excessive.
* [ ] Distribute raster tile loads across multiple frames and upload at most 1-2 tiles per frame.
* [ ] Don't generate the mipmaps immediately after loading, but wait a frame to spread the load.

Further avenues for investigation:
* [ ] Check whether using `texSubImage2D` to upload the bitmap in batches, and spread the upload of large bitmaps across multiple frames improves the performance.
* [x] A [comment on the chromium mailing list](https://groups.google.com/a/chromium.org/d/msg/chromium-dev/0j74Nd7i7IA/NmYiPkClKAAJ) claims:
> Image decompression happens after the onload handler fires. [...] The ImageBitmap API will fix this problem.

The [ImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap) API is supported in Chrome and Firefox at the time of this writing, but not Safari/Webkit, IE and Edge. It looks like we could use this to make image decoding asynchrous: The `createImageBitmap` constructor method returns a promise that will be resolve to a `ImageBitmap` object, so the call to `texImage2D` doesn't need to decode the image first. (See example in https://gist.github.com/ahem/d19ee198565e20c6f5e1bcd8f87b3408). Note that [at least Chrome](https://bugs.chromium.org/p/chromium/issues/detail?id=580202) still decodes on the current, thread, so we need to do this in a webworker.

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 Webkit timeline recorder and investigate the raster-tile calls to texImage2D and generateMipmap. Compare the current upload timing with spreading uploads across frames, deferring mipmap generation, and the possible texSubImage2D or ImageBitmap approaches. Done means raster tiles no longer upload more than 1–2 at once and mipmap work is spread across frames.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.