Bug 18611 - Blob should support Transferable
Summary: Blob should support Transferable
Status: RESOLVED WONTFIX
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: File API (show other bugs)
Version: unspecified
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: Arun
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-08-17 22:24 UTC by Glenn Maynard
Modified: 2012-08-28 03:20 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Glenn Maynard 2012-08-17 22:24:50 UTC
#17757 was in error.

It makes perfect sense for Blob to be transferable, for the same reasons that Blob#close is useful: so the UA deterministically knows that the underlying storage of a Blob can be freed immediately if no other Blobs refer to it.

It would be equivalent to saying:

    worker.postMessage({data: blob});
    blob.close();

but with the consistency of working like everything else that supports neutering, and giving the same semantics of postMessage.  It's inconsistent to have to do this differently for Blob and ArrayBuffer, eg. isntead of

    worker.postMessage({data: blob, buffer: arrayBuffer}, [blob, arrayBuffer]);

you have to say

    worker.postMessage({data: blob, buffer: arrayBuffer}, [arrayBuffer]);
    blob.close();

even though as far as script-visible behavior is concerned, transfer and neutering are the same thing.  To scripts, the transfer argument is simply a list of large objects that the script no longer needs, indicating that the browser can optimize for that; whether that optimization actually involves transfering objects (ArrayBuffer) or just freeing storage (Blob) doesn't matter.

This also means that you get the same semantics of postMessage: either all of the items in the transfer list are neutered or none are, instead of the above which may neuter arrayBuffer but not blob if an exception is thrown by structured clone.
Comment 1 Jonas Sicking 2012-08-17 23:35:24 UTC
Transferability has been added twice before: Ports and "ArrayBuffer-stuff".

In the first occasion it was added because Ports doesn't make sense if they aren't transferred.

In the second occasion it was added to enable better performance.

Neither of those reasons apply here. We would get no additional performance benefits from transferring blobs, and we can implement posting Blobs just fine without transferring them.


It sounds like you are proposing the ability to transfer blobs purely as a syntax sugar to handle the case of wanting to transfer the blob and then make sure to not hold it alive any longer than needed?

However, it doesn't seem hugely beneficial from a syntax point of view:

worker.postMessage({data: blob}, [blob]);

vs.

worker.postMessage({data: blob});
blob.close();


Second, I don't think it has been proven that this pattern is common enough that adding syntax sugar for it is warranted at this time.

Please don't file new bugs on this. If you want to keep discussing this, either keep commenting in existing bugs (you can even reopen them), or start a thread on the list.
Comment 2 Glenn Maynard 2012-08-18 00:21:58 UTC
(In reply to comment #1)
> Second, I don't think it has been proven that this pattern is common enough
> that adding syntax sugar for it is warranted at this time.

It's not syntax sugar, it's an API simplification: as far as scripts are concerned, neuterable, closable, transferable objects are are all the same thing, yet the APIs are needlessly diverging, giving an inconsistent, piecemeal API.  (Similarly, ArrayBuffer is missing .close.)

> Please don't file new bugs on this. If you want to keep discussing this, either
> keep commenting in existing bugs (you can even reopen them), or start a thread
> on the list.

I filed a new bug because reopening the one I saw (#17757) didn't make sense (since it was just about a note).
Comment 3 Charles Pritchard 2012-08-18 06:37:04 UTC
(In reply to comment #1)
> Transferability has been added twice before: Ports and "ArrayBuffer-stuff".
> 
> In the first occasion it was added because Ports doesn't make sense if they
> aren't transferred.
> 
> In the second occasion it was added to enable better performance.
> 
> Neither of those reasons apply here. We would get no additional performance
> benefits from transferring blobs, and we can implement posting Blobs just fine
> without transferring them.


We've got discussion about Blob with autorelease as well as transferring Blobs across origins (because we can't just sent a simple filesystem URI) and the consequences among all existing implementations in keeping Blob references in memory and on many occasions, Blobs in RAM.
Comment 4 Glenn Maynard 2012-08-18 15:12:15 UTC
(In reply to comment #3)
> We've got discussion about Blob with autorelease as well as transferring Blobs
> across origins (because we can't just sent a simple filesystem URI) and the
> consequences among all existing implementations in keeping Blob references in
> memory and on many occasions, Blobs in RAM.

That's a separate issue (making sure blob URLs aren't leaked, causing Blobs to become unreleasable).  Neither this nor Blob.close are ever intended to be used as a workaround for things like this.
Comment 5 Jonas Sicking 2012-08-20 15:14:25 UTC
I disagree that we need to make "closable" and "transferable" the same thing.

For one, it simply doesn't hold true for Blobs. You can get the same performance as transfering those without closing them.

Second, you are not proposing an API simplification. You are proposing additional syntax for to make sending and closing certain objects simpler. That is absolutely syntax sugar.
Comment 6 Glenn Maynard 2012-08-20 16:18:43 UTC
From the perspective of scripts, "transferable" has nothing to do with objects being transferred.  (The mechanics of that are invisible.)  All it means is that the object is able to be neutered when told to, either via postMessage or close().  The underlying optimizations this permits are different for different objects--Blobs to quickly free resources, ArrayBuffers both to free resources and avoid copies--but that's an implementation detail.  The visible side-effects are identical.

It seems like a clear simplification to have a uniform API for things that look identical to scripts.
Comment 7 Jonas Sicking 2012-08-21 00:16:48 UTC
I disagree. The concept of transferrable is highly visible in the case of ArrayBuffer since performance is different from when copying+closing the ArrayBuffer.

The concept of transferrable is also very different in the case of MessagePorts because the port isn't actually closed, it's, well, transferred.
Comment 8 Glenn Maynard 2012-08-24 23:02:32 UTC
(In reply to comment #7)
> I disagree. The concept of transferrable is highly visible in the case of
> ArrayBuffer since performance is different from when copying+closing the
> ArrayBuffer.

The testable, deterministic, specified behavior on scripts is identical.  Performance is an implementation detail, and probably won't even apply in every case (eg. a process-model browser might optimize cross-thread messaging in this way but not cross-process).  It seems a bit odd to not give a consistent API for things that act the same just because the underlying optimizations differ.

> The concept of transferrable is also very different in the case of MessagePorts
> because the port isn't actually closed, it's, well, transferred.

MessagePorts are a different beast entirely.  (They're Transferable for other reasons--API backwards-compatibility, and maintaining the invariant that structured clone doesn't mutate its input of objects not in the transfer list.)
Comment 9 Jonas Sicking 2012-08-25 03:38:00 UTC
I wouldn't call the performance of transferable ArrayBuffers an implementation detail. Authors will highly care about it. If thats not the case we should remove the feature entirely.

The fact that MessagePorts are entirely different is exactly my point.
Comment 10 Glenn Maynard 2012-08-28 00:37:57 UTC
(In reply to comment #9)
> I wouldn't call the performance of transferable ArrayBuffers an implementation
> detail. Authors will highly care about it. If thats not the case we should
> remove the feature entirely.

It's the very definition of an implementation detail.  Transferable makes certain optimizations possible, but nothing in the spec requires they be used, and I would be fairly surprised if browsers don't often fall back on copying when posting across processes.  (Otherwise ArrayBuffers would have to be allocated in shared memory in advance, which would be expensive, depending on the size.)  The only thing the spec requires of the API is that neutering happen.

> The fact that MessagePorts are entirely different is exactly my point.

In that case, I don't know what your point is.  MessagePorts simply aren't relevant (which is why I didn't bring them up).
Comment 11 Jonas Sicking 2012-08-28 03:20:57 UTC
My point is that "transfer" isn't semantically equivalent to "copy and neuter". So saying that all "neuterable" objects should be "transferable" and vise versa doesn't make sense to me.