Updates:
Status: Available
Cc:
tobia...@chromium.org
Labels: -Needs-Feedback Cr-Internals-Skia Cr-Blink-Image
Comment #12 on issue 525938 by
to...@chromium.org: android webview chromium
Not 100% confident about all of this, but based on dissecting the stack
data and looking at the code with tobiasjs@:
This crash looks like a 3750x2722 pixel image that's being drawn scaled
down, such that the entire image fits on the screen, either because the web
page is zoomed out, or because the site is showing it at smaller than
native size, and the 40MB memory allocation that's failing is the buffer it
intends to decode the image into, so that it can then resample it down to a
smaller size to draw on the screen.
The hardware draw logic checks whether the decoded image is too large for
the GPU and checks various other things to work out whether it should
decode the image all in one go, or in tiles, and because the large image is
still smaller than the maximum texture size and the entire image is needed,
it decides not to tile it, but allocating a shared memory buffer that large
is failing.
It's not that likely that allocating 40MB of memory is actually failing due
to a lack of memory, but what's possibly happening is that the virtual
address space of the webview application has become fragmented too badly
and there might not be a single 40MB chunk of address space left. This
crash seems to mostly happen in apps like reddit readers, pinterest, gmail,
etc - all of which are apps that might be used for a fairly extended period
of time, going through lots of different content with potentailly lots of
of large images embedded. The longer the app gets used for without being
restarted the worse its address space will be fragmented and the lower the
chance that a huge bitmap allocation will succeed.
This is probably much more likely to affect WebView than Chrome itself.
Chrome is multiprocess and so different sites don't always run in the same
renderer, plus renderers get recycled fairly often when navigating between
sites, letting one die and be replaced by a new one, so the odds of a
single renderer's address space being fragmented really badly are pretty
low. Also, on Android, Chrome renderers can be killed by the system to
reclaim memory when they aren't being used to render the foreground tab,
which further keeps their lifetimes relatively short. WebView is
single-process and so the only time the virtual address fragmentation will
get "reset" is when the entire application exits, which will typically only
happen after it's been in the background for a while and the system kills
it to reclaim memory for other apps - if the user's actively interacting
with the app it's not going to be killed and so never gets a chance to
start from a "clean" memory state.
----
So, question for skia/image decoding/etc people:
* Does the above sound plausible? Any ideas how we can test it? (we haven't
reproduced this crash)
* Is this a known issue that just hasn't been addressed because it's rarely
relevant for non-webview use cases?
* Isn't there a way to rescale images while decoding them, such that it's
never necessary to allocate the full size bitmap? Does this only get used
in some cases?
* Should we maybe consider forcing SkGpuDevice::shouldTileBitmap to tile
very large images even if the current checks think tiling isn't necessary?
(maybe just for singleprocess?) Tiled allocations would be smaller
individually and less likely to run into fragmentation issues, even if the
total memory usage is the same.