Re: Weak callbacks?

2013-11-07 Thread Terrence Cole
On 11/06/2013 07:37 PM, K. Gadd wrote:
 Generally speaking, all the discussions on this list about WRs so far have
 not suggested that there is any way to introduce WeakRefs without making GC
 behavior observable in some fashion. WeakRefs functionally make GC
 observable because when you try to get at the target of the weakref, you
 either get it or you don't. Once you introduce the ability to get back
 'null' when asking for the target of a WR (or any similar failure case),
 you can use that to determine things about GC behavior.
 
 If you somehow eliminate this weakness, WRs no longer solve the problems
 they are intended to solve. Or at the least, they solve only a small
 reduced subset of the problems solved in real software via the use of weak
 references. Being able to access the target of the WR (and have this
 operation fail) is core to their value (even if finalization notifications
 are also used quite often).
 
 I've already argued in the past about why weak references are important,
 and why not having solutions for those problems will kneecap the
 development of web applications by either preventing certain types of
 software from running in the browser, or forcing implementers to write
 their own GCs (or entire runtime environments) inside the browser, as is
 done with environments like emscripten and native client. Once that becomes
 the solution, the ES spec is irrelevant for those applications because they
 have had to abandon the language. While the risk of something like this
 happening is still relatively low, the risk increases over time as more
 people begin seriously considering solutions like emscripten and nacl -
 we're starting to see companies ship real products using them already. If
 this spreads to popular reusable libraries (physics libraries, rendering
 libraries, etc), there's a risk that those libraries will pull new
 applications out of the ES realm because it's not possible to use those
 libraries without abandoning ES in favor of a custom GC/runtime environment.
 
 Based on the conversations thus far, a choice just has to be made between
 the two downsides: exposing some amount of GC internals, or making it
 impossible to write some subset of applications in ES. It's possible that
 exposing GC semantics has such catastrophic security consequences that
 ruling those applications out is merited. It's also possible that
 workarounds can be applied to reduce the harm of GC visibility (I think in
 the past someone - maybe Mark? - suggested that disabling cross-realm WRs
 would mitigate the damage considerably?)

This is a false dichotomy. At the extreme, we could simply ship a new
builtin resource manager which has it's own GC behaviour that we can
expose at will. Given that the sorts of resources that people want to
use the memory GC to manage generally have very different cost and
volume tradeoffs than memory [1], this is actually much more reasonable
than it sounds.

The real problem with weak things is that they do have a performance
impact on the GC, even when not used. Missing weak-maps can at least be
worked around; a slow environment cannot.

-Terrence

1 -
http://www.mail-archive.com/dev-tech-js-engine-internals@lists.mozilla.org/msg00572.html

 On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt oli...@apple.com wrote:
 
 On Nov 6, 2013, at 3:14 PM, Rick Waldron waldron.r...@gmail.com wrote:




 On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola 
 dome...@domenicdenicola.com wrote:

 Thanks Mark for the education, especially on the pre- vs. post-morterm
 finalization distinction. I don't think I was specifically advocating for
 pre-mortem in my OP, since I didn't really understand the difference :P.
 Post-mortem finalization sounds quite reasonable. What do people think of
 introducing it into ECMAScript?


 This may be a naïve question, but how would the handler know which
 object/weakref had been gc'ed?

 You wouldn’t :)

 I’m kind of anti-finalisers in JS for all of the reasons people have
 raised - they are extremely hazardous, expose non-deterministic behaviour,
 etc

 Given our general desire to avoid exposing internal GC semantics, and the
 difficulty in defining observable GC behaviour (I suspect this would be a
 non-starter in any case), I can’t see any specification that would allow
 useful finalisers or WeakRefs.

 If MarkM has an idea for WeakRefs that don’t leak observable GC behaviour
 i’d love to hear, but in general i’m opposed to both them and finalisers :-/

 —Oliver

 Rick

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


 
 
 
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
 


Re: Weak callbacks?

2013-11-07 Thread K. Gadd
When I talk about the importance of weak references I am *not* talking
about the importance of finalization for managing native/remote resources;
that's an important consideration but it's a separate one. When I talk
about why weak references are important, I mean for the purposes of
building large applications without creating uncollectable cycles in object
graphs. Doing this without weak references is *very* difficult in some
scenarios, and in other scenarios requires manual management of all object
lifetimes (addref/release style, or having a single lifetime owner that
'deletes' an object on demand).

That's the sort of obstacle that factors into a developer's choice of
language and toolset. I've seen this particular concern with ES crop up in
the past on real projects, and I've seen firsthand how difficult it is to
avoid uncollectable cycles in a language environment without any sort of
weak reference mechanism. Leaking large uncollectable cycles can have
catastrophic consequences in multimedia applications and games, where those
cycles might be retaining images or sounds or other huge game assets.

On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote:

 On 11/06/2013 07:37 PM, K. Gadd wrote:
  Generally speaking, all the discussions on this list about WRs so far
 have
  not suggested that there is any way to introduce WeakRefs without making
 GC
  behavior observable in some fashion. WeakRefs functionally make GC
  observable because when you try to get at the target of the weakref, you
  either get it or you don't. Once you introduce the ability to get back
  'null' when asking for the target of a WR (or any similar failure case),
  you can use that to determine things about GC behavior.
 
  If you somehow eliminate this weakness, WRs no longer solve the problems
  they are intended to solve. Or at the least, they solve only a small
  reduced subset of the problems solved in real software via the use of
 weak
  references. Being able to access the target of the WR (and have this
  operation fail) is core to their value (even if finalization
 notifications
  are also used quite often).
 
  I've already argued in the past about why weak references are important,
  and why not having solutions for those problems will kneecap the
  development of web applications by either preventing certain types of
  software from running in the browser, or forcing implementers to write
  their own GCs (or entire runtime environments) inside the browser, as is
  done with environments like emscripten and native client. Once that
 becomes
  the solution, the ES spec is irrelevant for those applications because
 they
  have had to abandon the language. While the risk of something like this
  happening is still relatively low, the risk increases over time as more
  people begin seriously considering solutions like emscripten and nacl -
  we're starting to see companies ship real products using them already. If
  this spreads to popular reusable libraries (physics libraries, rendering
  libraries, etc), there's a risk that those libraries will pull new
  applications out of the ES realm because it's not possible to use those
  libraries without abandoning ES in favor of a custom GC/runtime
 environment.
 
  Based on the conversations thus far, a choice just has to be made between
  the two downsides: exposing some amount of GC internals, or making it
  impossible to write some subset of applications in ES. It's possible that
  exposing GC semantics has such catastrophic security consequences that
  ruling those applications out is merited. It's also possible that
  workarounds can be applied to reduce the harm of GC visibility (I think
 in
  the past someone - maybe Mark? - suggested that disabling cross-realm WRs
  would mitigate the damage considerably?)

 This is a false dichotomy. At the extreme, we could simply ship a new
 builtin resource manager which has it's own GC behaviour that we can
 expose at will. Given that the sorts of resources that people want to
 use the memory GC to manage generally have very different cost and
 volume tradeoffs than memory [1], this is actually much more reasonable
 than it sounds.

 The real problem with weak things is that they do have a performance
 impact on the GC, even when not used. Missing weak-maps can at least be
 worked around; a slow environment cannot.

 -Terrence

 1 -

 http://www.mail-archive.com/dev-tech-js-engine-internals@lists.mozilla.org/msg00572.html

  On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt oli...@apple.com wrote:
 
  On Nov 6, 2013, at 3:14 PM, Rick Waldron waldron.r...@gmail.com
 wrote:
 
 
 
 
  On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola 
  dome...@domenicdenicola.com wrote:
 
  Thanks Mark for the education, especially on the pre- vs. post-morterm
  finalization distinction. I don't think I was specifically advocating
 for
  pre-mortem in my OP, since I didn't really understand the difference
 :P.
  Post-mortem finalization 

Re: Weak callbacks?

2013-11-07 Thread Mark S. Miller
Could you give an example, hopefully simple, of such a problem you can
solve better with GC + weakmaps + weakrefs but without finalization, vs
just GC + weakmaps ? Thanks.


On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote:

 When I talk about the importance of weak references I am *not* talking
 about the importance of finalization for managing native/remote resources;
 that's an important consideration but it's a separate one. When I talk
 about why weak references are important, I mean for the purposes of
 building large applications without creating uncollectable cycles in object
 graphs. Doing this without weak references is *very* difficult in some
 scenarios, and in other scenarios requires manual management of all object
 lifetimes (addref/release style, or having a single lifetime owner that
 'deletes' an object on demand).

 That's the sort of obstacle that factors into a developer's choice of
 language and toolset. I've seen this particular concern with ES crop up in
 the past on real projects, and I've seen firsthand how difficult it is to
 avoid uncollectable cycles in a language environment without any sort of
 weak reference mechanism. Leaking large uncollectable cycles can have
 catastrophic consequences in multimedia applications and games, where those
 cycles might be retaining images or sounds or other huge game assets.


 On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote:

 On 11/06/2013 07:37 PM, K. Gadd wrote:
  Generally speaking, all the discussions on this list about WRs so far
 have
  not suggested that there is any way to introduce WeakRefs without
 making GC
  behavior observable in some fashion. WeakRefs functionally make GC
  observable because when you try to get at the target of the weakref, you
  either get it or you don't. Once you introduce the ability to get back
  'null' when asking for the target of a WR (or any similar failure case),
  you can use that to determine things about GC behavior.
 
  If you somehow eliminate this weakness, WRs no longer solve the problems
  they are intended to solve. Or at the least, they solve only a small
  reduced subset of the problems solved in real software via the use of
 weak
  references. Being able to access the target of the WR (and have this
  operation fail) is core to their value (even if finalization
 notifications
  are also used quite often).
 
  I've already argued in the past about why weak references are important,
  and why not having solutions for those problems will kneecap the
  development of web applications by either preventing certain types of
  software from running in the browser, or forcing implementers to write
  their own GCs (or entire runtime environments) inside the browser, as is
  done with environments like emscripten and native client. Once that
 becomes
  the solution, the ES spec is irrelevant for those applications because
 they
  have had to abandon the language. While the risk of something like this
  happening is still relatively low, the risk increases over time as more
  people begin seriously considering solutions like emscripten and nacl -
  we're starting to see companies ship real products using them already.
 If
  this spreads to popular reusable libraries (physics libraries, rendering
  libraries, etc), there's a risk that those libraries will pull new
  applications out of the ES realm because it's not possible to use those
  libraries without abandoning ES in favor of a custom GC/runtime
 environment.
 
  Based on the conversations thus far, a choice just has to be made
 between
  the two downsides: exposing some amount of GC internals, or making it
  impossible to write some subset of applications in ES. It's possible
 that
  exposing GC semantics has such catastrophic security consequences that
  ruling those applications out is merited. It's also possible that
  workarounds can be applied to reduce the harm of GC visibility (I think
 in
  the past someone - maybe Mark? - suggested that disabling cross-realm
 WRs
  would mitigate the damage considerably?)

 This is a false dichotomy. At the extreme, we could simply ship a new
 builtin resource manager which has it's own GC behaviour that we can
 expose at will. Given that the sorts of resources that people want to
 use the memory GC to manage generally have very different cost and
 volume tradeoffs than memory [1], this is actually much more reasonable
 than it sounds.

 The real problem with weak things is that they do have a performance
 impact on the GC, even when not used. Missing weak-maps can at least be
 worked around; a slow environment cannot.

 -Terrence

 1 -

 http://www.mail-archive.com/dev-tech-js-engine-internals@lists.mozilla.org/msg00572.html

  On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt oli...@apple.com wrote:
 
  On Nov 6, 2013, at 3:14 PM, Rick Waldron waldron.r...@gmail.com
 wrote:
 
 
 
 
  On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola 
  dome...@domenicdenicola.com 

Re: Weak callbacks?

2013-11-07 Thread K. Gadd
I'll try and restate an example I used before.

Let's say you're building a somewhat simple tab-based application, where
each tab represents a different 'mode'. In this case, you need a higher
level coordinating object that manages the tab bar, and it needs to own
references to all of the active modes in order to manage the tabs.
Similarly, each mode may need to have a reference to the coordinator in
order to interact with it - like by setting the title of the tab, or
opening a new tab containing another mode - and it may need to have
references to other modes in order to communicate (like if one tab opens a
tab containing related information).

In a model like that, you can trivially end up with object cycles. All the
references (going in every direction) are strong, so to successfully
collect a mode you need to ensure that every reference to it from live
objects is released. This is problematic because it means that, for example:

If Mode A opens a new tab containing Mode B, and Mode A wants to respond to
things happening in Mode B, Mode A now has to register some sort of event
listener on Mode B. This means that Mode A and Mode B have now formed a
strong cycle: Mode B's event listener list contains a strong reference to
Mode A (to fire the event notification), and Mode A has a strong reference
to Mode B in order to be able to respond to those events.

Now, if you close Mode B, the coordinator gets rid of the tab and drops its
strong references to Mode B - the tab is 'gone' - but there's no trivial
way to ensure that everyone else holding a reference to it is dead. If
multiple tabs interact in this way it's possible for a huge graph of
objects to be hanging off one live tab. Eventually, if you close enough
tabs you might 'free' the graph, but if you aren't careful the coordinator
itself can end up keeping dead tabs alive, with things like event listener
lists.

In the real apps I've worked on like this, the solution was some form of
weak references - making event listeners own weak self-references instead
of strong self-references, so that in normal circumstances event
subscriptions expire along with the subscriber, along with using weak
references directly in cases like 'tab a spawns tab b' in order to ensure
that you aren't keeping an object alive just to monitor it.

IIRC, cycles like this are already common in some DOM scenarios, where
event subscription and such result in big graphs of objects hanging off a
single live object? I've certainly run into it in a few cases, where an
event listener hanging off an audio element caused a huge graph of
objects to leak, and I had to manually remove the event listeners at an
appropriate time (and finding an appropriate time can be difficult!)


On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.com wrote:

 Could you give an example, hopefully simple, of such a problem you can
 solve better with GC + weakmaps + weakrefs but without finalization, vs
 just GC + weakmaps ? Thanks.


 On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote:

 When I talk about the importance of weak references I am *not* talking
 about the importance of finalization for managing native/remote resources;
 that's an important consideration but it's a separate one. When I talk
 about why weak references are important, I mean for the purposes of
 building large applications without creating uncollectable cycles in object
 graphs. Doing this without weak references is *very* difficult in some
 scenarios, and in other scenarios requires manual management of all object
 lifetimes (addref/release style, or having a single lifetime owner that
 'deletes' an object on demand).

 That's the sort of obstacle that factors into a developer's choice of
 language and toolset. I've seen this particular concern with ES crop up in
 the past on real projects, and I've seen firsthand how difficult it is to
 avoid uncollectable cycles in a language environment without any sort of
 weak reference mechanism. Leaking large uncollectable cycles can have
 catastrophic consequences in multimedia applications and games, where those
 cycles might be retaining images or sounds or other huge game assets.


 On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote:

 On 11/06/2013 07:37 PM, K. Gadd wrote:
  Generally speaking, all the discussions on this list about WRs so far
 have
  not suggested that there is any way to introduce WeakRefs without
 making GC
  behavior observable in some fashion. WeakRefs functionally make GC
  observable because when you try to get at the target of the weakref,
 you
  either get it or you don't. Once you introduce the ability to get back
  'null' when asking for the target of a WR (or any similar failure
 case),
  you can use that to determine things about GC behavior.
 
  If you somehow eliminate this weakness, WRs no longer solve the
 problems
  they are intended to solve. Or at the least, they solve only a small
  reduced subset of the 

Re: Weak callbacks?

2013-11-07 Thread felix lee
That example looks to me like it could be implemented with WeakMap instead
of WeakRef. Am I missing something?

On Thu Nov 07 2013 at 2:43:45 PM, K. Gadd k...@luminance.org wrote:

 I'll try and restate an example I used before.

 Let's say you're building a somewhat simple tab-based application, where
 each tab represents a different 'mode'. In this case, you need a higher
 level coordinating object that manages the tab bar, and it needs to own
 references to all of the active modes in order to manage the tabs.
 Similarly, each mode may need to have a reference to the coordinator in
 order to interact with it - like by setting the title of the tab, or
 opening a new tab containing another mode - and it may need to have
 references to other modes in order to communicate (like if one tab opens a
 tab containing related information).

 In a model like that, you can trivially end up with object cycles. All the
 references (going in every direction) are strong, so to successfully
 collect a mode you need to ensure that every reference to it from live
 objects is released. This is problematic because it means that, for example:

 If Mode A opens a new tab containing Mode B, and Mode A wants to respond
 to things happening in Mode B, Mode A now has to register some sort of
 event listener on Mode B. This means that Mode A and Mode B have now formed
 a strong cycle: Mode B's event listener list contains a strong reference to
 Mode A (to fire the event notification), and Mode A has a strong reference
 to Mode B in order to be able to respond to those events.

 Now, if you close Mode B, the coordinator gets rid of the tab and drops
 its strong references to Mode B - the tab is 'gone' - but there's no
 trivial way to ensure that everyone else holding a reference to it is dead.
 If multiple tabs interact in this way it's possible for a huge graph of
 objects to be hanging off one live tab. Eventually, if you close enough
 tabs you might 'free' the graph, but if you aren't careful the coordinator
 itself can end up keeping dead tabs alive, with things like event listener
 lists.

 In the real apps I've worked on like this, the solution was some form of
 weak references - making event listeners own weak self-references instead
 of strong self-references, so that in normal circumstances event
 subscriptions expire along with the subscriber, along with using weak
 references directly in cases like 'tab a spawns tab b' in order to ensure
 that you aren't keeping an object alive just to monitor it.

 IIRC, cycles like this are already common in some DOM scenarios, where
 event subscription and such result in big graphs of objects hanging off a
 single live object? I've certainly run into it in a few cases, where an
 event listener hanging off an audio element caused a huge graph of
 objects to leak, and I had to manually remove the event listeners at an
 appropriate time (and finding an appropriate time can be difficult!)


 On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.com wrote:

 Could you give an example, hopefully simple, of such a problem you can
 solve better with GC + weakmaps + weakrefs but without finalization, vs
 just GC + weakmaps ? Thanks.


 On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote:

 When I talk about the importance of weak references I am *not* talking
 about the importance of finalization for managing native/remote resources;
 that's an important consideration but it's a separate one. When I talk
 about why weak references are important, I mean for the purposes of
 building large applications without creating uncollectable cycles in object
 graphs. Doing this without weak references is *very* difficult in some
 scenarios, and in other scenarios requires manual management of all object
 lifetimes (addref/release style, or having a single lifetime owner that
 'deletes' an object on demand).

 That's the sort of obstacle that factors into a developer's choice of
 language and toolset. I've seen this particular concern with ES crop up in
 the past on real projects, and I've seen firsthand how difficult it is to
 avoid uncollectable cycles in a language environment without any sort of
 weak reference mechanism. Leaking large uncollectable cycles can have
 catastrophic consequences in multimedia applications and games, where those
 cycles might be retaining images or sounds or other huge game assets.


 On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote:

 On 11/06/2013 07:37 PM, K. Gadd wrote:
  Generally speaking, all the discussions on this list about WRs so far
 have
  not suggested that there is any way to introduce WeakRefs without making
 GC
  behavior observable in some fashion. WeakRefs functionally make GC
  observable because when you try to get at the target of the weakref, you
  either get it or you don't. Once you introduce the ability to get back
  'null' when asking for the target of a WR (or any similar failure case),
  you can use 

Re: Weak callbacks?

2013-11-07 Thread K. Gadd
I am not aware of any way to implement my described scenario using WeakMaps
without having the same cycle collection issues. I haven't seen any
examples of WeakMap used for this in the wild either.

On Thu, Nov 7, 2013 at 2:48 PM, felix lee feli...@gmail.com wrote:

 That example looks to me like it could be implemented with WeakMap instead
 of WeakRef. Am I missing something?


 On Thu Nov 07 2013 at 2:43:45 PM, K. Gadd k...@luminance.org wrote:

 I'll try and restate an example I used before.

 Let's say you're building a somewhat simple tab-based application, where
 each tab represents a different 'mode'. In this case, you need a higher
 level coordinating object that manages the tab bar, and it needs to own
 references to all of the active modes in order to manage the tabs.
 Similarly, each mode may need to have a reference to the coordinator in
 order to interact with it - like by setting the title of the tab, or
 opening a new tab containing another mode - and it may need to have
 references to other modes in order to communicate (like if one tab opens a
 tab containing related information).

 In a model like that, you can trivially end up with object cycles. All
 the references (going in every direction) are strong, so to successfully
 collect a mode you need to ensure that every reference to it from live
 objects is released. This is problematic because it means that, for example:

 If Mode A opens a new tab containing Mode B, and Mode A wants to respond
 to things happening in Mode B, Mode A now has to register some sort of
 event listener on Mode B. This means that Mode A and Mode B have now formed
 a strong cycle: Mode B's event listener list contains a strong reference to
 Mode A (to fire the event notification), and Mode A has a strong reference
 to Mode B in order to be able to respond to those events.

 Now, if you close Mode B, the coordinator gets rid of the tab and drops
 its strong references to Mode B - the tab is 'gone' - but there's no
 trivial way to ensure that everyone else holding a reference to it is dead.
 If multiple tabs interact in this way it's possible for a huge graph of
 objects to be hanging off one live tab. Eventually, if you close enough
 tabs you might 'free' the graph, but if you aren't careful the coordinator
 itself can end up keeping dead tabs alive, with things like event listener
 lists.

 In the real apps I've worked on like this, the solution was some form of
 weak references - making event listeners own weak self-references instead
 of strong self-references, so that in normal circumstances event
 subscriptions expire along with the subscriber, along with using weak
 references directly in cases like 'tab a spawns tab b' in order to ensure
 that you aren't keeping an object alive just to monitor it.

 IIRC, cycles like this are already common in some DOM scenarios, where
 event subscription and such result in big graphs of objects hanging off a
 single live object? I've certainly run into it in a few cases, where an
 event listener hanging off an audio element caused a huge graph of
 objects to leak, and I had to manually remove the event listeners at an
 appropriate time (and finding an appropriate time can be difficult!)


 On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.comwrote:

 Could you give an example, hopefully simple, of such a problem you can
 solve better with GC + weakmaps + weakrefs but without finalization, vs
 just GC + weakmaps ? Thanks.


 On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote:

 When I talk about the importance of weak references I am *not* talking
 about the importance of finalization for managing native/remote resources;
 that's an important consideration but it's a separate one. When I talk
 about why weak references are important, I mean for the purposes of
 building large applications without creating uncollectable cycles in object
 graphs. Doing this without weak references is *very* difficult in some
 scenarios, and in other scenarios requires manual management of all object
 lifetimes (addref/release style, or having a single lifetime owner that
 'deletes' an object on demand).

 That's the sort of obstacle that factors into a developer's choice of
 language and toolset. I've seen this particular concern with ES crop up in
 the past on real projects, and I've seen firsthand how difficult it is to
 avoid uncollectable cycles in a language environment without any sort of
 weak reference mechanism. Leaking large uncollectable cycles can have
 catastrophic consequences in multimedia applications and games, where those
 cycles might be retaining images or sounds or other huge game assets.


 On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote:

 On 11/06/2013 07:37 PM, K. Gadd wrote:
  Generally speaking, all the discussions on this list about WRs so far
 have
  not suggested that there is any way to introduce WeakRefs without
 making GC
  behavior observable in some fashion. 

Re: Weak callbacks?

2013-11-07 Thread felix lee
Ah, sorry, I misread your description of the relationships. Yeah, that
would be hard to do with WeakMaps.

On Thu Nov 07 2013 at 3:02:02 PM, K. Gadd k...@luminance.org wrote:

 I am not aware of any way to implement my described scenario using
 WeakMaps without having the same cycle collection issues. I haven't seen
 any examples of WeakMap used for this in the wild either.


 On Thu, Nov 7, 2013 at 2:48 PM, felix lee feli...@gmail.com wrote:

 That example looks to me like it could be implemented with WeakMap instead
 of WeakRef. Am I missing something?


 On Thu Nov 07 2013 at 2:43:45 PM, K. Gadd k...@luminance.org wrote:

 I'll try and restate an example I used before.

 Let's say you're building a somewhat simple tab-based application, where
 each tab represents a different 'mode'. In this case, you need a higher
 level coordinating object that manages the tab bar, and it needs to own
 references to all of the active modes in order to manage the tabs.
 Similarly, each mode may need to have a reference to the coordinator in
 order to interact with it - like by setting the title of the tab, or
 opening a new tab containing another mode - and it may need to have
 references to other modes in order to communicate (like if one tab opens a
 tab containing related information).

 In a model like that, you can trivially end up with object cycles. All the
 references (going in every direction) are strong, so to successfully
 collect a mode you need to ensure that every reference to it from live
 objects is released. This is problematic because it means that, for example:

 If Mode A opens a new tab containing Mode B, and Mode A wants to respond
 to things happening in Mode B, Mode A now has to register some sort of
 event listener on Mode B. This means that Mode A and Mode B have now formed
 a strong cycle: Mode B's event listener list contains a strong reference to
 Mode A (to fire the event notification), and Mode A has a strong reference
 to Mode B in order to be able to respond to those events.

 Now, if you close Mode B, the coordinator gets rid of the tab and drops
 its strong references to Mode B - the tab is 'gone' - but there's no
 trivial way to ensure that everyone else holding a reference to it is dead.
 If multiple tabs interact in this way it's possible for a huge graph of
 objects to be hanging off one live tab. Eventually, if you close enough
 tabs you might 'free' the graph, but if you aren't careful the coordinator
 itself can end up keeping dead tabs alive, with things like event listener
 lists.

 In the real apps I've worked on like this, the solution was some form of
 weak references - making event listeners own weak self-references instead
 of strong self-references, so that in normal circumstances event
 subscriptions expire along with the subscriber, along with using weak
 references directly in cases like 'tab a spawns tab b' in order to ensure
 that you aren't keeping an object alive just to monitor it.

 IIRC, cycles like this are already common in some DOM scenarios, where
 event subscription and such result in big graphs of objects hanging off a
 single live object? I've certainly run into it in a few cases, where an
 event listener hanging off an audio element caused a huge graph of
 objects to leak, and I had to manually remove the event listeners at an
 appropriate time (and finding an appropriate time can be difficult!)


 On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.com wrote:

 Could you give an example, hopefully simple, of such a problem you can
 solve better with GC + weakmaps + weakrefs but without finalization, vs
 just GC + weakmaps ? Thanks.


 On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote:

 When I talk about the importance of weak references I am *not* talking
 about the importance of finalization for managing native/remote resources;
 that's an important consideration but it's a separate one. When I talk
 about why weak references are important, I mean for the purposes of
 building large applications without creating uncollectable cycles in object
 graphs. Doing this without weak references is *very* difficult in some
 scenarios, and in other scenarios requires manual management of all object
 lifetimes (addref/release style, or having a single lifetime owner that
 'deletes' an object on demand).

 That's the sort of obstacle that factors into a developer's choice of
 language and toolset. I've seen this particular concern with ES crop up in
 the past on real projects, and I've seen firsthand how difficult it is to
 avoid uncollectable cycles in a language environment without any sort of
 weak reference mechanism. Leaking large uncollectable cycles can have
 catastrophic consequences in multimedia applications and games, where those
 cycles might be retaining images or sounds or other huge game assets.


 On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote:

 On 11/06/2013 07:37 PM, K. Gadd wrote:
  Generally 

Re: Weak callbacks?

2013-11-07 Thread David Bruant

Le 07/11/2013 22:46, K. Gadd a écrit :
That's the sort of obstacle that factors into a developer's choice of 
language and toolset. I've seen this particular concern with ES crop 
up in the past on real projects, and I've seen firsthand how difficult 
it is to avoid uncollectable cycles in a language environment without 
any sort of weak reference mechanism. Leaking large uncollectable 
cycles can have catastrophic consequences in multimedia applications 
and games, where those cycles might be retaining images or sounds or 
other huge game assets.
The repeated use of the word cycle worries me. Cycles aren't a problem 
by themselves with mark and sweep, do we agree?


David
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-07 Thread K. Gadd
The problem is that the cycles remain uncollectable for a very long period
of time, even though functionally the references don't need to be strong.


On Thu, Nov 7, 2013 at 3:10 PM, David Bruant bruan...@gmail.com wrote:

 Le 07/11/2013 22:46, K. Gadd a écrit :

  That's the sort of obstacle that factors into a developer's choice of
 language and toolset. I've seen this particular concern with ES crop up in
 the past on real projects, and I've seen firsthand how difficult it is to
 avoid uncollectable cycles in a language environment without any sort of
 weak reference mechanism. Leaking large uncollectable cycles can have
 catastrophic consequences in multimedia applications and games, where those
 cycles might be retaining images or sounds or other huge game assets.

 The repeated use of the word cycle worries me. Cycles aren't a problem
 by themselves with mark and sweep, do we agree?

 David

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-07 Thread Mark Miller
I agree. This is a good use for weakrefs without the need for finalization.
Thanks!


On Thu, Nov 7, 2013 at 3:12 PM, K. Gadd k...@luminance.org wrote:

 The problem is that the cycles remain uncollectable for a very long period
 of time, even though functionally the references don't need to be strong.


 On Thu, Nov 7, 2013 at 3:10 PM, David Bruant bruan...@gmail.com wrote:

 Le 07/11/2013 22:46, K. Gadd a écrit :

  That's the sort of obstacle that factors into a developer's choice of
 language and toolset. I've seen this particular concern with ES crop up in
 the past on real projects, and I've seen firsthand how difficult it is to
 avoid uncollectable cycles in a language environment without any sort of
 weak reference mechanism. Leaking large uncollectable cycles can have
 catastrophic consequences in multimedia applications and games, where those
 cycles might be retaining images or sounds or other huge game assets.

 The repeated use of the word cycle worries me. Cycles aren't a problem
 by themselves with mark and sweep, do we agree?

 David



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-07 Thread Domenic Denicola
Would someone be interested in putting together a small code example, before 
and after weak refs, illustrating this situation? I have a feeling this 
conversation will be referenced in many future threads, and the added clarity 
of code would be greatly helpful.

On 7 Nov 2013, at 18:16, Mark Miller 
erig...@gmail.commailto:erig...@gmail.com wrote:

I agree. This is a good use for weakrefs without the need for finalization. 
Thanks!


On Thu, Nov 7, 2013 at 3:12 PM, K. Gadd 
k...@luminance.orgmailto:k...@luminance.org wrote:
The problem is that the cycles remain uncollectable for a very long period of 
time, even though functionally the references don't need to be strong.


On Thu, Nov 7, 2013 at 3:10 PM, David Bruant 
bruan...@gmail.commailto:bruan...@gmail.com wrote:
Le 07/11/2013 22:46, K. Gadd a ?crit :

That's the sort of obstacle that factors into a developer's choice of language 
and toolset. I've seen this particular concern with ES crop up in the past on 
real projects, and I've seen firsthand how difficult it is to avoid 
uncollectable cycles in a language environment without any sort of weak 
reference mechanism. Leaking large uncollectable cycles can have catastrophic 
consequences in multimedia applications and games, where those cycles might be 
retaining images or sounds or other huge game assets.
The repeated use of the word cycle worries me. Cycles aren't a problem by 
themselves with mark and sweep, do we agree?

David


___
es-discuss mailing list
es-discuss@mozilla.orgmailto:es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss




--
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.orgmailto:es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-07 Thread Marius Gundersen
On Thu, Nov 7, 2013 at 11:42 PM, K. Gadd k...@luminance.org wrote:

 I'll try and restate an example I used before.

 Let's say you're building a somewhat simple tab-based application, where
 each tab represents a different 'mode'. In this case, you need a higher
 level coordinating object that manages the tab bar, and it needs to own
 references to all of the active modes in order to manage the tabs.
 Similarly, each mode may need to have a reference to the coordinator in
 order to interact with it - like by setting the title of the tab, or
 opening a new tab containing another mode - and it may need to have
 references to other modes in order to communicate (like if one tab opens a
 tab containing related information).

 In a model like that, you can trivially end up with object cycles. All the
 references (going in every direction) are strong, so to successfully
 collect a mode you need to ensure that every reference to it from live
 objects is released. This is problematic because it means that, for example:

 If Mode A opens a new tab containing Mode B, and Mode A wants to respond
 to things happening in Mode B, Mode A now has to register some sort of
 event listener on Mode B. This means that Mode A and Mode B have now formed
 a strong cycle: Mode B's event listener list contains a strong reference to
 Mode A (to fire the event notification), and Mode A has a strong reference
 to Mode B in order to be able to respond to those events.

 Now, if you close Mode B, the coordinator gets rid of the tab and drops
 its strong references to Mode B - the tab is 'gone' - but there's no
 trivial way to ensure that everyone else holding a reference to it is dead.
 If multiple tabs interact in this way it's possible for a huge graph of
 objects to be hanging off one live tab. Eventually, if you close enough
 tabs you might 'free' the graph, but if you aren't careful the coordinator
 itself can end up keeping dead tabs alive, with things like event listener
 lists.

 In the real apps I've worked on like this, the solution was some form of
 weak references - making event listeners own weak self-references instead
 of strong self-references, so that in normal circumstances event
 subscriptions expire along with the subscriber, along with using weak
 references directly in cases like 'tab a spawns tab b' in order to ensure
 that you aren't keeping an object alive just to monitor it.

 IIRC, cycles like this are already common in some DOM scenarios, where
 event subscription and such result in big graphs of objects hanging off a
 single live object? I've certainly run into it in a few cases, where an
 event listener hanging off an audio element caused a huge graph of
 objects to leak, and I had to manually remove the event listeners at an
 appropriate time (and finding an appropriate time can be difficult!)


Instead of using weakRefs to solve your problem you could use weak event
listeners. Using weak event listeners would mean you have an event
dispatcher which has a weak reference to an event handler. This way the
handler object can listen to events from other parts of the system without
being kept alive by those other parts. In your example, each tab can be an
event handler, and they can weakly listen to events from other tabs. Only
the coordinator has a strong reference to the tabs, and so when the
coordinator severs the strong reference, the tabs are eventually garbage
collected.

Or another example would be a page consisting of multiple web components.
Each component is strongly reference by the DOM, but they weakly listen to
events from each other. This means that you can delete a component by
removing it from the DOM. The object will (eventually) be garbage
collected, and will no longer listen to events.

I have created a gist which describes how weak event listeners could work:
https://gist.github.com/mariusGundersen/7364253

It seems that every (real) usecase for weakRefs, weakMaps and weakSets is
to implement a weak event listener system. Unfortunately weak event
listeners cannot be implemented with the current weakSet/weakMap spec,
since they are not iterable. To implement an event dispatch system we need
to be able to iterate over the listeners. A weak event dispatcher has a
hidden iterable weakSet of listeners. It iterates over this weakSet and
notifys each entry of the event which has occured. But it does not expose
this iterable set.

Does it sound like weak event listeners could solve the challenges you
face? Is there a problem which can be implemented with weak references
which cannot be solved by weak event listeners?

Marius Gundersen



 On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.com wrote:

 Could you give an example, hopefully simple, of such a problem you can
 solve better with GC + weakmaps + weakrefs but without finalization, vs
 just GC + weakmaps ? Thanks.


 On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote:

 When I talk about the importance of weak 

Re: Weak callbacks?

2013-11-07 Thread K. Gadd
Please reread my example, events are a part of it but it is not exclusively
about events. My example explicitly demonstrates the modes holding
references in *both* directions, and only one of them is an event listener.

You're correct that weak event listeners solve some of the problems that
are usually used to justify weakrefs, but they're not the only problems.
Sometimes objects really do need to interact bidirectionally without
keeping each other alive :)

To restate things, part of the problem here is that objects need to
interact, so they need to either have references to each other or have a
third party act as an intermediary. You can remove references entirely with
some sort of message bus or other intermediary (interacting through opaque
handles?) but at that point you've just moved all the lifetime management
concerns around, and now you're manually calling addref/decref or doing
things like that. Alternately, you can keep the strong references and
carefully plumb 'release' code through every object that holds references,
so that for example when a tab dies, it tells literally every object in the
application to let go of any references to the tab. I hope the complexity
inherent to *that* method is evident.

Apologies if my contrived example is not clear enough for these purposes;
the applications I write on a day-to-day basis do not use WRs much. I'm
speaking from past experience and the things I hear from users of my
compiler, and my past experience was on closed-source projects I can't
easily reproduce here verbatim.

To contrive a scenario that might illustrate where event listeners aren't
necessarily enough: Let's say I have an entity system for a game that is
modelling thousands of independent entities that interact. In this system,
entity A might decide to chase after entity B, so it grabs a reference to
entity B in order to chase after it. Meanwhile, entity B might be chasing
after entity C, so it has a reference to entity C. Now, let's say entity C
and entity B both are removed from the simulation. At this point, as long
as entity A is alive, so are B and C (in GC terms) even though the latter
two are not participating in the simulation. Now every place where an
entity can refer to another entity has to be manually audited to ensure
that 'dead' references are actually nulled out, which means you're
basically doing your own GC sweeps over your heap using your own lifetime
rules.

On Thu, Nov 7, 2013 at 4:27 PM, Marius Gundersen gunder...@gmail.comwrote:



 On Thu, Nov 7, 2013 at 11:42 PM, K. Gadd k...@luminance.org wrote:

 I'll try and restate an example I used before.

 Let's say you're building a somewhat simple tab-based application, where
 each tab represents a different 'mode'. In this case, you need a higher
 level coordinating object that manages the tab bar, and it needs to own
 references to all of the active modes in order to manage the tabs.
 Similarly, each mode may need to have a reference to the coordinator in
 order to interact with it - like by setting the title of the tab, or
 opening a new tab containing another mode - and it may need to have
 references to other modes in order to communicate (like if one tab opens a
 tab containing related information).

 In a model like that, you can trivially end up with object cycles. All
 the references (going in every direction) are strong, so to successfully
 collect a mode you need to ensure that every reference to it from live
 objects is released. This is problematic because it means that, for example:

 If Mode A opens a new tab containing Mode B, and Mode A wants to respond
 to things happening in Mode B, Mode A now has to register some sort of
 event listener on Mode B. This means that Mode A and Mode B have now formed
 a strong cycle: Mode B's event listener list contains a strong reference to
 Mode A (to fire the event notification), and Mode A has a strong reference
 to Mode B in order to be able to respond to those events.

 Now, if you close Mode B, the coordinator gets rid of the tab and drops
 its strong references to Mode B - the tab is 'gone' - but there's no
 trivial way to ensure that everyone else holding a reference to it is dead.
 If multiple tabs interact in this way it's possible for a huge graph of
 objects to be hanging off one live tab. Eventually, if you close enough
 tabs you might 'free' the graph, but if you aren't careful the coordinator
 itself can end up keeping dead tabs alive, with things like event listener
 lists.

 In the real apps I've worked on like this, the solution was some form of
 weak references - making event listeners own weak self-references instead
 of strong self-references, so that in normal circumstances event
 subscriptions expire along with the subscriber, along with using weak
 references directly in cases like 'tab a spawns tab b' in order to ensure
 that you aren't keeping an object alive just to monitor it.

 IIRC, cycles like this are already common in some DOM scenarios, 

Re: Weak callbacks?

2013-11-07 Thread Mark Miller
On Thu, Nov 7, 2013 at 4:27 PM, Marius Gundersen gunder...@gmail.comwrote:

 It seems that every (real) usecase for weakRefs, weakMaps and weakSets is
 to implement a weak event listener system.


Not true. Even silly.


 Unfortunately weak event listeners cannot be implemented with the current
 weakSet/weakMap spec, since they are not iterable.


If they were iterable, they would be broken, and fail to solve their actual
real use cases. They are not the right tool for the job -- they have
nothing to do with weak event listeners.

It seems like the only real use case for email is to make toast.
Unfortunately, email can't be used to make toast because it isn't hot
enough.


-- 
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak callbacks?

2013-11-07 Thread Marius Gundersen
On Nov 8, 2013 1:46 AM, Mark Miller erig...@gmail.com wrote:

 On Thu, Nov 7, 2013 at 4:27 PM, Marius Gundersen gunder...@gmail.com
wrote:

 It seems that every (real) usecase for weakRefs, weakMaps and weakSets
is to implement a weak event listener system.


 Not true. Even silly.

Sorry, I may have worded that a bit strongly



 Unfortunately weak event listeners cannot be implemented with the
current weakSet/weakMap spec, since they are not iterable.


 If they were iterable, they would be broken, and fail to solve their
actual real use cases. They are not the right tool for the job -- they have
nothing to do with weak event listeners.


Yes, that was my point. Weak event listeners should be implemented in the
browser to solve the kind of problems brought up towards the end of this
thread. I never meant to say that weak sets or maps should be used to
implement weak event listeners. Many common problems can be solved with
weak event listeners, and so they should be standardized and implemented in
the language.

 It seems like the only real use case for email is to make toast.
Unfortunately, email can't be used to make toast because it isn't hot
enough.


 --
 Text by me above is hereby placed in the public domain

   Cheers,
   --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss