Re: [IndexedDB] setVersion blocked on uncollected garbage IDBDatabases

On Wed, Feb 9, 2011 at 5:05 PM, Drew Wilson <atwilson@google.com> wrote:

> In some cases we leak them, yes (they live for the life of the parent
> context) if the developer does not close them. Typically this is only when
> you've cloned a MessagePort and sent the other end to a different process.
> Trying to figure out if a port is reachable when the entangled port lives in
> a different process (and whose reachability may itself depend on the
> reachability of a third port in yet another process ad infinitum) is a
> fairly intractable problem.


OK.  At least the heap snapshotting in Chrome is good enough to make
debugging this reasonably easy, if it results in nontrivial leaks.


>  This does not happen with the implicit ports associated with dedicated
> workers, because in WebKit those aren't actually MessagePorts (mainly
> because the webkit implementation of dedicated workers predates message
> ports). Chromium SharedWorkers use real MessagePorts though, so if you do
> this:
>
> var w = new SharedWorker("foo.html");
> w.port.onmessage = function() {...};
>
> that port will not be GC'd in chromium, even if the SharedWorker drops its
> end of the port on the floor, until either the SharedWorker calls close() on
> the port, the worker exits or your parent document is collected.
>

That's natural, of course--the event handler holds a reference to the
object.

On a related note, please see this statement from section 5.5 of the
> MessagePort spec:
>
> Authors are strongly encouraged to explicitly close MessagePort<http://dev.w3.org/html5/postmsg/#messageport> objects
> to disentangle them, so that their resources can be recollected. Creating
> many MessagePort <http://dev.w3.org/html5/postmsg/#messageport> objects
> and discarding them without closing them can lead to high memory usage.
>

For explicitly-created MessagePorts this is natural enough.  It's slightly
less obvious for MessagePorts created implicitly by Worker/SharedWorker
objects, though; I'd predict that becoming a common cause of leaks on pages
that create and destroy a lot of threads.


Back on IDB: If one page has an opened database (whether from not being
closed, a GC issue, or a simpler site issue), and a new tab is failing to
setVersion as a result, figuring out the cause may be painful.  Hopefully
browsers will at least be able to tell which other tab is holding the
database open, and retrieve a stack trace of where it was opened, even if
it's in a closed tab.  If that information is available, it would be useful
to include it in the "blocked" event, as an optional, informative message
that scripts can send to their server-side error logging if it blocks for
too long.

Another related issue: what happens if a long-running number-cruncher worker
keeps a database open while it works, to read data or output results?
There's no API for sending versionchange events for IDBDatabaseSync, and it
doesn't fit in any obvious way since it's inherently asynchronous.  I
suppose the developer-side workaround would be to open the same database
asynchronously in the UI thread just to listen for versionchange, and to
terminate the thread when it's received.  Is that generally what's intended?

-- 
Glenn Maynard

Received on Thursday, 10 February 2011 01:29:29 UTC