-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory keeps increasing with each zoom interaction on iPhone / Macbook Safari browser #8771
Comments
@alankaanil26 Thank you for the details in this ticket. Adding some notes from the tickets you posted:
We are investigating this and will post back here when we find the root cause. |
It also happens on both Chrome and Safari in iOS when interacting with the map instance from the mapboxgl, e.g. when map extent changes, Tested the mapboxgl-js 1.3.1 on iOS 12.4.1 and Chrome 77. |
hi @asheemmamoowala any update on the issue? |
@iamanvesh We are still investigating the issue, and will post updates here when we have some concrete leads. |
Same issue! |
Same issue for chrome on osx |
setting |
I've done some more profiling on macOS with #8814 applied and did memory profiles of controlled zooming in/out with Chrome 77Firefox 70Safari 13It looks like this problem is isolated to Safari. What's weird is that the memory seems to increase in a terraced way. Possibly this is some internal vector that uses an allocation strategy that doubles the memory. |
I ran another test with a debug build of Chromium 75 and a testing script that executes a flyTo to a random location every couple of seconds. After 1h30m, the master branch was at ~2GB and growing. With #8814 applied, it remained stable between 400 and 500MB, with a peak of 659.7MB after ~1h40m. |
This is looking like a browser bug, after instrumenting with Xcode instruments and a debug build of WebKIt @ahk and I discovered that calls to We've come up with a simple example that reproduces the issue, and filed a bug with webkit. The example:
|
A partial fix for a Safari bug related to I also discovered another Safari memory leak related to transferring buffers through message channels and ticketed it in https://bugs.webkit.org/show_bug.cgi?id=203990. I believe the remaining memory growth that the above PR doesn't fix can be attributed to the same or a similar problem, but so far we haven't been able to identify a suitable fix for Safari. |
I'm using this demo page to trigger rapid memory growth: <!DOCTYPE html>
<html>
<head>
<title>Mapbox GL JS debug page</title>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel='stylesheet' href='../dist/mapbox-gl.css' />
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body>
<div id='map'></div>
<script src='../dist/mapbox-gl-dev.js'></script>
<script src='access_token_generated.js'></script>
<script>
let zoom = 15;
const center = [-77.01866, 38.888];
const duration = 60000;
let map = window.map = new mapboxgl.Map({
container: 'map',
zoom,
center,
style: 'mapbox://styles/mapbox/streets-v10',
interactive: false,
maxTileCacheSize: 0
});
const interval = setInterval(() => {
map.style.sourceCaches.composite.clearTiles();
map.jumpTo({});
}, 1000);
</script>
</body>
</html> The advantage over zooming/panning is that the tiles loaded are known, so there's less variation and it's easier to spot memory growth. |
I've been debugging this further and will post a little bit about the progress, process and tools used. Capturing memory use isn't straightforward; there are a few different metrics. I've settled for using "Real Memory Size" since it most closely reflects the actual memory use. Activity Tracker also shows it in the Info window for a given process. The number in the table overview seems to be a rolling average, so take it with a grain of salt. To create profiles like those posted above, I'm using the Python module To visualize the memory trace that is currently in progress, I stripped down the My workflow is to open the debugging site posted above in a new window/tab, then use Activity Monitor (or a CLI tool) to find the correct process. In Activity Monitor, the process helpfully is titled with You can also use The WebKit wiki contains an info page on Leaks and Bloats which links to a patch that adds many more zones to the malloc tracker. I applied the patch to a June revision of WebKit, compiled a release build and ran it with version 87 of the Safari Technology Preview.app (Safari 13 will fail to launch with older WebKit builds). Note that you'll have to make sure that the DYLD_FRAMEWORK_PATH includes both the build directory and the app's Framework directory separated by colons, otherwise it will default to using the wrong libraries. With that patch applied, |
I've tested memory growth with the tooling I described above with all GL JS versions back to 0.43 from late 2017, with the patch in #8956 applied where applicable, but got the same memory growth, which looks similar to this (~30 minute trace): It typically grows pretty quickly, up until 3-5 GB, then hovers around that area for a long time, sometimes reducing memory usage after a while. The initial memory use is often terraced, with big allocations happening in a very short time, then remaining completely stable for a few minutes. I found that this erratic memory growth is connected to WebWorkers. I produced a build of GL JS that doesn't use them and instead processes all tiles on the main thread. It loads the same amount of tiles so the numbers are comparable. This is the memory graph I got in a ~50 minute trace: To me, this indicates that Safari is capable of running GL JS without excessive memory growth, but that there's some bug or adverse behavior in conjunction with webworkers. |
To simplify debugging with webworkers and making it easier to set breakpoints, I created this rollup script based on our CSP build: import {plugins} from './build/rollup_plugins';
const config = (input, file, format) => ({
input,
output: {
name: 'mapboxgl',
file,
format,
sourcemap: 'inline',
indent: false
},
treeshake: false,
plugins: plugins(false, false)
});
export default [
config('src/index.js', 'dist/mapbox-gl-main.dev.js', 'umd'),
config('src/source/worker.js', 'dist/mapbox-gl-worker.dev.js', 'iife')
]; Running it with <script src='../dist/mapbox-gl-main.dev.js'></script>
<script>
mapboxgl.workerCount = 1;
mapboxgl.workerUrl = '/dist/mapbox-gl-worker.dev.js';
</script> in your debug HTML page. Safari will now allow you to set a breakpoint in the worker bundle and correctly read the source maps. It has the added benefit that builds are faster, in particular if they only affect either the worker or the main bundle. |
I've followed a number of different approaches, gradually disabling parts of the tile parsing on the worker side along the way. However, short of disabling creation of Here's the graph when disabling passing data back to the main thread (but still parsing everything): It's particularly noticeable that the memory stays flat for long time, then suddenly jumps very excessively. I've been monitoring the "Private Memory Size" in Activity Monitor and it seems that this is varying quite a bit, depending on when Safari runs the garbage collection. However, once Safari bumps against the memory ceiling, it looks like it won't reuse any of the already available space and allocates new space. This is the graph with It's still jumping quite a bit. When disabling tile parsing altogether (but still keeping WorkerTile creation), something interesting happens: The steep cliffs become less steep. I'm explaining this with the fact that we don't create as many objects during one tile reload anymore on the worker. |
We know that memory somehow keeps leaking in the web workers, since a build that runs on just the foreground thread doesn't exhibit memory growth. I produced an experimental build of GL JS that uses workers 10 times, and then explicitly terminates them after the last tile that was using the worker gets removed from the map. With the demo above, this is happening regularly and I checked that all workers are getting terminated after a few seconds. Yet, this is the memory graph I'm observing: |
Another experiment I've done is to use MessageChannel, send the port to the webworker, and communicate via the channel instead of via the webworker's |
We've observed that this only happens when using web workers. We use web workers to load and process tiled map data for use with WebGL, then send it to the main thread. A typical tile can have up to a few hundred ArrayBuffers. We are using Furthermore, we've observed that disabling transferable objects mostly fixes the memory growth issue and the process stays at ~500-600 MB. I've dug in to find out why this happens:
A few other observations:
I ticketed this over in https://bugs.webkit.org/show_bug.cgi?id=204515 along with a reproduction example. |
@alankaanil @zhenyanghua @ezraripps A fix for this is available in the 1.5.1-beta release. |
@arindam1993 (or whoever did) hey thanks man, https://www.bountysource.com/issues/80631646-memory-keeps-increasing-with-each-zoom-interaction-on-iphone-macbook-safari-browser idk how but go claim this |
It looks like this was not released with v1.6.0, or is it just missing from the changelog? Any ETA in that case? Edit: Oops, sorry. Thought 1.5.1 was just a beta release. The PRs are in master and live with 1.6.0 |
1.5.1 is also a final release which includes this fix. It's also available in 1.6.0. |
It looks like this bug was fixed by Apple on June 4, 2020. Should this issue be re-opened? It would be nice to turn back on transferrables in Safari. |
mapbox-gl-js version: v1.3.1
browser: Safari for iPhone / Macbook
I am using a single HTML page with example provided in Mapbox-gl-js page.
Steps to Trigger Behavior
Link to Demonstration
https://codepen.io/anilalanka/pen/pozxPGx
Please add your access token for testing.
Actual Behavior
The following are the Memory profile details captured on Macbook Safari Web inspector, based on style URL used.
When memory consumed is large enough,
This webpage is using significant memory. Closing it may improve the responsiveness of your Mac.
.1. Using Mapbox default style URL:
Memory increases upto 1.06 GB in 80 seconds, as shown below
2. Using our Product's custom style URL:
A faster rate of memory increase is observed - 1.76 GB in 40 seconds
On further investigation, I found the below tickets already present on Safari:
The last notable comment from Safari noted that "I checked further. It seems crash I am seeing does not have to do this with specific bug which indeed seems fixed. It seems Safari has some general limit of overall memory use and we are running into that due to memory bloat."
The text was updated successfully, but these errors were encountered: