New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 705718 link

Starred by 3 users

Issue metadata

Status: WontFix
Owner:
Closed: May 2017
Cc:
Components:
EstimatedDays: 1
NextAction: ----
OS: Linux
Pri: 2
Type: Bug



Sign in to add a comment

Creating sequence of ImageBitmaps in worker exhausts memory

Reported by martin.v...@gmail.com, Mar 27 2017

Issue description

UserAgent: Mozilla/5.0 (X11; Linux x86_64; rv:51.0) Gecko/20100101 Firefox/51.0

Steps to reproduce the problem:
1. Have a worker thread crate a sequence of images using createImageBitmap, posting each to the main thread once it is ready.

2. Have the main thread keep the latest such image and use it for rendering.

Run the HTML file from the attached ZIP to see this.

What is the expected behavior?
Only one image kept in main thread, so GC should collect the others and memory consumption should be constant.

What went wrong?
Memory consumption keeps rising. Tab gets killed at about 1.5G of memory on my system. System crashes reported by others.

Did this work before? N/A 

Chrome version: 57.0.2987.54 (Developer Build) (64-bit)  Channel: n/a
OS Version: 4.9.9
Flash Version: Shockwave Flash 24.0 r0

I THINK this used to work better in previous versions, around Chromium version 54 or so, but I'm not sure.

https://github.com/CindyJS/CindyJS/pull/517#issuecomment-289402683 is the context where we encountered this.

Firefox had a similar problem, see https://bugzilla.mozilla.org/show_bug.cgi?id=1312148 for discussion. There the memory consumption was not tracked so the memory pressure was not detected and the garbage collector not executed.
 
Stickler2.zip
4.4 KB Download

Comment 1 by tkent@chromium.org, Mar 27 2017

Components: -Blink Blink>MemoryAllocator Blink>Image
Components: -Blink>Image Blink>Canvas
The given example file gives a DOM exception. I'm not sure how to fix that, maybe turn off security checks locally. But in any case, the worker is using canvas.

Uncaught DOMException: Failed to construct 'Worker': Script at 'file:///Users/schenney/Downloads/Stickler2/ifs.js' cannot be accessed from origin 'null'.
    at file:///Users/schenney/Downloads/Stickler2/Stickler2.html:5:20
> The given example file gives a DOM exception. I'm not sure how to fix that,
> maybe turn off security checks locally.

OK, I used a local web server, so the files could get loaded via http: not file:. Disabling some security checks should work as well. The st package for node can be used for this, see https://www.npmjs.com/package/st for details.

> But in any case, the worker is using canvas.

The worker is no accessing the canvas directly. It is creating ImageBitmaps, which get drawn to the canvas on the main thread.
Components: -Blink>Canvas Blink>Image Blink>DOM
Labels: BugSource-User PaintTeamTriaged-20170228
Status: Available (was: Unconfirmed)

Comment 5 by noel@chromium.org, Apr 3 2017

Cc: xlai@chromium.org junov@chromium.org

Comment 6 by junov@chromium.org, Apr 3 2017

Components: Blink>Canvas
EstimatedDays: 1
Owner: xidac...@chromium.org
Status: Assigned (was: Available)
As far as I can tell the JS code is doing everything right.

I see that the code is taking advantage of the transferability of ImageBitmap in the calls to postMeassage. That's good.

I also see that the onmessage handler on the other side is correctly disposing of old ImageBitmaps by calling .close().  

Those two measures combined should be sufficient to keep memory usage under control for ImageBitmaps even without garbage collection kicking in.

This could be an internal bug in the ImageBitmap implementation.
I haven't looked at details here so bear that in mind..but are (Static)ImageBitmaps registering their external allocations with v8 (AdjustAmountOfExternalAllocatedMemory())? If so, then transferring the bitmap objects to the worker would not transfer the cost from the worker's v8 context to the transferred context (and make that receiving context more eager to perform v8 GCs.)

See  issue 700353  for the ArrayBuffer case of this; SerializedScriptValue could easily accommodate ImageBitmaps for such alloc-cost transfers also.
I have attached a minimal repro case: keep creating an ImageBitmap on a worker thread and transfer to the main thread and let main thread call close() method on the ImageBitmap.

The above test case will eat about 1.5GB of ram in 3-5 seconds. However, if we un-comment the self.gc() line, then there is no memory leak at all. This indicate that the memory is garbage-collectable, it is just the case that GC is not actively triggered.

I have a WIP CL: https://codereview.chromium.org/2796103002/, which should solve the problem in theory, but it doesn't. Another finding I have is that when running the attached test case, the constructor of the UnacceleratedStaticBitmapImage gets heavily called, but the destructor never gets called, even though the ImageBitmap's destructor is actively being called, and I am not sure why is that.
leak.html
419 bytes View Download
leak.js
412 bytes View Download
Cc: -junov@chromium.org xidac...@chromium.org
Owner: junov@chromium.org
Cc: -xidac...@chromium.org junov@chromium.org
Owner: xidac...@chromium.org
Status: WontFix (was: Assigned)
The memory leak has gone with ToT code. I think our GC has done a much better job now:).

Sign in to add a comment