Re: [whatwg] onclose events for MessagePort

2013-10-21 Thread Andrew Wilson
On Sat, Oct 19, 2013 at 2:26 AM, Jonas Sicking jo...@sicking.cc wrote:


 What I think might work is to say that as long as a channeldropped
 event listener is registered with a port, that is equivalent to
 holding a strong reference to the port. I.e. that prevents the channel
 from being GCed. Even if no references are held to either port.

 In other words, we'd give up 3, but only when 2 is actively used.


Agreed - this was my proposal here:
http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2013-October/041068.html in
response to your earlier email.



 We would also need to define that the channeldropped event is never
 fired on a port if that port's *owning* window has been navigated away
 from. Otherwise we could *never* GC a channel between two windows that
 has channeldropped registered on either side.


Makes sense, although I'm a bit fuzzy about the rules around MessagePorts
and window navigation (for example, if I navigate a window, is all content
in that window now shutdown/discarded, even though I could in theory get
back to the window by immediately clicking back)?


 So the expectation is that a caller should only register a
 channeldropped event if it's actively waiting for a response from
 that thread. It's not something that you should register when creating
 the port and then never unregister. Having a channeldropped event
 listener registered can cause a whole worker thread to be kept alive
 longer than it otherwise would.


How does this work - imagine that I have a reference to a MessagePort, but
I'm not actively waiting for any response on the port so I don't have a
channeldropped event listener.

Now, the remote side of the port crashes. I send a message on the port and
add a channeldropped event handler - are you saying that adding a
channeldropped event handler should trigger a channeldropped event if the
other side has already crashed? If not, then how do I find out that the
channel has been dropped if I don't keep the event handler registered all
the time?


Re: [whatwg] Canvas in workers

2013-10-21 Thread Glenn Maynard
On Sun, Oct 20, 2013 at 11:53 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 Glenn, taking a step back for a bit, is there anything in
 https://wiki.mozilla.org/User:Roc/WorkerCanvasProposal that you would
 actually object to? IOW, is there anything there that you would think is
 completely superfluous to the platform if all your proposals were to be
 adopted as well?


I have no objection to the overall change from CanvasProxy to WorkerCanvas,
eg. the stuff in Kyle's original mail to the thread.  (Being able to settle
on that is one of the reasons I've tried to detach discussion for the other
use cases.)

I'd only recommend leaving out transferToImageBitmap, srcObject and
ImageBitmap.close() parts.  I do think that would be redundant with with
present proposal.  They can always be added later, and leaving them out
keeps the WorkerCanvas proposal itself focused.

-- 
Glenn Maynard


Re: [whatwg] Synchronizing Canvas updates in a worker to DOM changes in the UI thread

2013-10-21 Thread Glenn Maynard
On Sun, Oct 20, 2013 at 11:16 PM, Robert O'Callahan
rob...@ocallahan.orgwrote:

 With all these proposals I think it's OK to allow the main thread to do
 (e.g.) a toDataURL and read what the current contents of the canvas is,


We can defer this discussion, since it's not something new to this proposal
(or any other proposal we're discussing).


On Sun, Oct 20, 2013 at 11:33 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 To me, passing the image data explicitly in an ImageBuffer along with the
 present message seems like a better fit to the workers message-passing
 model than this proposal, where the data is stored as hidden state in the
 canvas element with (effectively) a setter in the worker and a getter in
 the main thread, and that setting and getting has to be coordinated with
 postMessage for synchronization. The relationship between a commit and
 its present has to be deduced by reasoning about the timing of messages,
 rather than by just reasoning about JS data flow through postMessage.


Using ImageBitmap for this has a lot of issues.  It requires synchronizing
with scripts in the UI thread.  It requires manualling resize your canvas
repeatedly to fit different destinations.  It also may potentially create
lots of backbuffers. Here's an example of code using ImageBitmap
incorrectly, leading to excess memory allocation:

function render()
{
var canvas = myWorkerCanvas;
renderTo(canvas);
var buffer = canvas.transferToImageBitmap();
postMessage(buffer);
}
setTimeout(render, 1);

We start with one backbuffer available, render to it (renderTo), peel it
off the canvas to be displayed somewhere, and toss it off to the main
thread.  (For the sake of the example, the main thread is busy and doesn't
process it immediately.)  The worker enters render() again, and when it
gets to renderTo, a new backbuffer has to be allocated, since the one
buffer we have is still used by the ImageBuffer and can't be changed.  This
happens repeatedly, creating new backbuffers each time, since none of them
can be reused.

This is an extreme example, but if this ever happens even once, it means
potentially allocating an extra backbuffer.


 This proposal also requires that whenever a worker is going to return
 image data to the main thread, the main thread must start things off by
 creating a canvas element. It's also not possible for a worker to spawn off
 sub-workers to do drawing (at least, not without some really ugly
 coordination with the main thread.)


Sure it is.  If you want an offscreen buffer, you just new
WorkerCanvas().  This is unrelated to offscreen drawing.

-- 
Glenn Maynard


Re: [whatwg] Synchronizing Canvas updates in a worker to DOM changes in the UI thread

2013-10-21 Thread Kenneth Russell
On Mon, Oct 21, 2013 at 3:39 PM, Glenn Maynard gl...@zewt.org wrote:
 On Sun, Oct 20, 2013 at 11:16 PM, Robert O'Callahan rob...@ocallahan.org
 wrote:

 With all these proposals I think it's OK to allow the main thread to do
 (e.g.) a toDataURL and read what the current contents of the canvas is,


 We can defer this discussion, since it's not something new to this proposal
 (or any other proposal we're discussing).


 On Sun, Oct 20, 2013 at 11:33 PM, Robert O'Callahan rob...@ocallahan.org
 wrote:

 To me, passing the image data explicitly in an ImageBuffer along with the
 present message seems like a better fit to the workers message-passing
 model than this proposal, where the data is stored as hidden state in the
 canvas element with (effectively) a setter in the worker and a getter in the
 main thread, and that setting and getting has to be coordinated with
 postMessage for synchronization. The relationship between a commit and its
 present has to be deduced by reasoning about the timing of messages,
 rather than by just reasoning about JS data flow through postMessage.


 Using ImageBitmap for this has a lot of issues.  It requires synchronizing
 with scripts in the UI thread.

This isn't difficult, and amounts to a few additional lines of code in
the main thread's onmessage handler.

The ImageBitmap style proposal has another significant advantage in
that it allows a single canvas context to present results in multiple
output regions on the page.


  It requires manualling resize your canvas
 repeatedly to fit different destinations.  It also may potentially create
 lots of backbuffers. Here's an example of code using ImageBitmap
 incorrectly, leading to excess memory allocation:

 function render()
 {
 var canvas = myWorkerCanvas;
 renderTo(canvas);
 var buffer = canvas.transferToImageBitmap();
 postMessage(buffer);
 }
 setTimeout(render, 1);

 We start with one backbuffer available, render to it (renderTo), peel it off
 the canvas to be displayed somewhere, and toss it off to the main thread.
 (For the sake of the example, the main thread is busy and doesn't process it
 immediately.)  The worker enters render() again, and when it gets to
 renderTo, a new backbuffer has to be allocated, since the one buffer we have
 is still used by the ImageBuffer and can't be changed.  This happens
 repeatedly, creating new backbuffers each time, since none of them can be
 reused.

 This is an extreme example, but if this ever happens even once, it means
 potentially allocating an extra backbuffer.

This sort of resource exhaustion is certainly possible, but I view
this downside as smaller than the upside of addressing both of the
above use cases.

-Ken



 This proposal also requires that whenever a worker is going to return
 image data to the main thread, the main thread must start things off by
 creating a canvas element. It's also not possible for a worker to spawn off
 sub-workers to do drawing (at least, not without some really ugly
 coordination with the main thread.)


 Sure it is.  If you want an offscreen buffer, you just new WorkerCanvas().
 This is unrelated to offscreen drawing.

 --
 Glenn Maynard



Re: [whatwg] Synchronizing Canvas updates in a worker to DOM changes in the UI thread

2013-10-21 Thread Glenn Maynard
On Mon, Oct 21, 2013 at 6:08 PM, Kenneth Russell k...@google.com wrote:

  Using ImageBitmap for this has a lot of issues.  It requires
 synchronizing
  with scripts in the UI thread.

 This isn't difficult, and amounts to a few additional lines of code in
 the main thread's onmessage handler.


Synchronization with the UI thread isn't bad because it's difficult.
Avoiding synchronization with the main thread has been raised as a
desirable goal:
http://lists.w3.org/Archives/Public/public-whatwg-archive/2013Oct/0152.htmlincluding
that it isn't possible to render from a worker without
synchronizing with the main thread.

(My previous comments on this are here:
http://www.mail-archive.com/whatwg@lists.whatwg.org/msg35959.html)


 The ImageBitmap style proposal has another significant advantage in
 that it allows a single canvas context to present results in multiple
 output regions on the page.


You can do that.  You just create a WorkerCanvas for each canvas you want
to present to, hand them to the worker, then attachToCanvas in the worker
to switch from canvas to canvas.  (That's orthogonal to explicitpresent.)


 This sort of resource exhaustion is certainly possible, but I view
 this downside as smaller than the upside of addressing both of the
 above use cases.


I can only find one thing above that you might be referring to as a use
case (the one I replied to immediately above).  What was the other?

-- 
Glenn Maynard


Re: [whatwg] onclose events for MessagePort

2013-10-21 Thread Ehsan Akhgari
On Fri, Oct 18, 2013 at 8:26 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Thu, Oct 17, 2013 at 2:08 PM, Ehsan Akhgari eh...@mozilla.com wrote:
  It occurs to me that all of the proposals here does expose some amount
  of GC behavior. Even a channeldropped message which is sent only
  when the other side crashes exposes GC behavior. If GC happens to run
  before the crash and then collect the MessageChannel ports, then no
  channel exists at the time of crash, and thus no event is sent.
  However if the GC runs later, or if it doesn't successfully collect
  the MessageChannel ports, then the channeldropped event does fire.
 
  I'm not sure if I understand this.  If the MessagePort exists on the side
  that is interested to handle the event, then it can't be GCed on the
 other
  side either, right?

 I thought the proposal was to not fire channeldropped when the
 channel is GCed. Thus allowing channels with both message and
 channeldropped event listeners on either side to still be GCed. Is
 that correct?


Yes, that's correct.


 If so, that exposes GC behavior. If at some point both pages that hold
 on to an endpoint of a message channel drop their references the
 channel can get GCed. If it is GCed no events fire.

 However if the page holding on to either port crashes before the GC
 happens, then the channeldropped event is fired on the other port.

 Hence the timing of the GC affects whether channeldropped is fired.
 Hence GC behavior is exposed.


Yeah, I see the problem now.


   That's not to say that this solution wouldn't work. Exposing some
  amount of GC behavior might be ok. But it does mean that we should
  have a realistic bar as we discuss expanding the event to more
  situations than just process crashes.
 
  One solution which I think would never expose GC behavior is to simply
  have a property on the MessagePort which indicates if the owner of the
  other side has been killed or navigated away from. No event would fire
  as that property changes value.
 
  Since it's a property, it can only be read if a reference to the
  MessagePort is being held. As long as such a reference exists neither
  side of the MessageChannel can be GCed.
 
  Exposing this state as a property will make people who have use cases
 such
  as Update the UI if this other tab/page/app/etc is killed poll the
  attribute, which seems non-ideal to me.

 I don't see a way to simultaneously fulfill all of the following
 constraints:

 1. Don't expose GC.
 2. Provide a callback when the other side crashes or lives in a thread
 that dies.
 3. Enable GC of channels where neither side referenced.

 What I think might work is to say that as long as a channeldropped
 event listener is registered with a port, that is equivalent to
 holding a strong reference to the port. I.e. that prevents the channel
 from being GCed. Even if no references are held to either port.

 In other words, we'd give up 3, but only when 2 is actively used.

 And then define that channeldropped is fired on a port whenever the
 other side is killed due to either living in a process that crashes,
 or living in a thread that is closed or terminated.

 We would also need to define that the channeldropped event is never
 fired on a port if that port's *owning* window has been navigated away
 from. Otherwise we could *never* GC a channel between two windows that
 has channeldropped registered on either side.


This sounds good to me.


 So the expectation is that a caller should only register a
 channeldropped event if it's actively waiting for a response from
 that thread. It's not something that you should register when creating
 the port and then never unregister. Having a channeldropped event
 listener registered can cause a whole worker thread to be kept alive
 longer than it otherwise would.


Right.


 We could further define that channeldropped is fired when the owner
 of the *other side* is navigated away from. This would mean that
 events can be received even after a channeldropped event has been
 fired since other windows could still hold a reference to the port and
 send messages through it. However it would allow us to release the
 strong reference that the channeldropped event listener implicitly
 creates as soon as either side is navigated away from.


But what if the page is navigated back to?  I think this implies that
having fired a channeldropped event because of this reason means that the
UA needs to make it impossible to navigate back to the same window, which
means disabling optimizations such as Gecko's back-forward cache, which
sucks.


  Also, having a setTimeout(0) loop which polls the attribute would open
 us to
  the exact same risks as the event would, I think.

 How do you mean? Which risks in particular are you referring to?


I was talking about GC observabiity, but I think I was wrong since the
attribute that you were proposing could not be queried if you lost the
reference to it from js...

Cheers,
--
Ehsan

Re: [whatwg] onclose events for MessagePort

2013-10-21 Thread Ehsan Akhgari
On Mon, Oct 21, 2013 at 3:19 AM, Andrew Wilson atwil...@google.com wrote:




 On Sat, Oct 19, 2013 at 2:26 AM, Jonas Sicking jo...@sicking.cc wrote:


 What I think might work is to say that as long as a channeldropped
 event listener is registered with a port, that is equivalent to
 holding a strong reference to the port. I.e. that prevents the channel
 from being GCed. Even if no references are held to either port.

 In other words, we'd give up 3, but only when 2 is actively used.


 Agreed - this was my proposal here:
 http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2013-October/041068.html 
 in
 response to your earlier email.


Yeah, you're right, sorry for overlooking this the first time around!


  So the expectation is that a caller should only register a
 channeldropped event if it's actively waiting for a response from
 that thread. It's not something that you should register when creating
 the port and then never unregister. Having a channeldropped event
 listener registered can cause a whole worker thread to be kept alive
 longer than it otherwise would.


 How does this work - imagine that I have a reference to a MessagePort, but
 I'm not actively waiting for any response on the port so I don't have a
 channeldropped event listener.

 Now, the remote side of the port crashes. I send a message on the port and
 add a channeldropped event handler - are you saying that adding a
 channeldropped event handler should trigger a channeldropped event if the
 other side has already crashed? If not, then how do I find out that the
 channel has been dropped if I don't keep the event handler registered all
 the time?


I think we may need to mandate that a channeldropped eventis fired when
you register a handler on a port with the other side having already crashed.

Cheers,
--
Ehsan
http://ehsanakhgari.org/


Re: [whatwg] Synchronizing Canvas updates in a worker to DOM changes in the UI thread

2013-10-21 Thread Kenneth Russell
On Mon, Oct 21, 2013 at 4:34 PM, Glenn Maynard gl...@zewt.org wrote:
 On Mon, Oct 21, 2013 at 6:08 PM, Kenneth Russell k...@google.com wrote:

  Using ImageBitmap for this has a lot of issues.  It requires
  synchronizing
  with scripts in the UI thread.

 This isn't difficult, and amounts to a few additional lines of code in
 the main thread's onmessage handler.


 Synchronization with the UI thread isn't bad because it's difficult.
 Avoiding synchronization with the main thread has been raised as a desirable
 goal:
 http://lists.w3.org/Archives/Public/public-whatwg-archive/2013Oct/0152.html
 including that it isn't possible to render from a worker without
 synchronizing with the main thread.

 (My previous comments on this are here:
 http://www.mail-archive.com/whatwg@lists.whatwg.org/msg35959.html)


 The ImageBitmap style proposal has another significant advantage in
 that it allows a single canvas context to present results in multiple
 output regions on the page.


 You can do that.  You just create a WorkerCanvas for each canvas you want to
 present to, hand them to the worker, then attachToCanvas in the worker to
 switch from canvas to canvas.  (That's orthogonal to explicitpresent.)

OK, I misunderstood that part of your attachToCanvas proposal.

There are some unexpected consequences of the attachToCanvas API
style. For example, what if two contexts use attachToCanvas to target
the same canvas? What if one of those contexts is 2D and the other is
WebGL? Currently it's illegal to try to fetch two different context
types for a single Canvas. The current CanvasProxy spec contains
several complex rules for these cases, and they're not easy to
understand.

Will it be guaranteed that if you have a WebGL context, attachToCanvas
to canvas1, do some rendering, and then attachToCanvas to canvas2,
that the only remaining buffer in canvas1 is its color buffer? No
depth buffers, multisample buffers, etc. will have to remain for some
reason?

How would WebGL's preserveDrawingBuffer attribute, which is a property
of the context, interact with directing its output to multiple
canvases?

Fundamentally I think the behavior is easier to spec, and the
implementation is easier to make correct, if the ultimate destination
is an image rather than a canvas, and the color buffer is transferred
out of the WorkerCanvas in an explicit step.

-Ken



 This sort of resource exhaustion is certainly possible, but I view
 this downside as smaller than the upside of addressing both of the
 above use cases.


 I can only find one thing above that you might be referring to as a use case
 (the one I replied to immediately above).  What was the other?

 --
 Glenn Maynard