Weak callbacks?

classic Classic list List threaded Threaded
72 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

Weak callbacks?

Domenic Denicola-2
Over lunch I was discussing ES6 and ES7 features with some developers doing JavaScript crypto, and they mentioned an interest in not only weak references, but weak callbacks. That is, a notification when your object gets garbage collected, similar (I think) to what V8 has with its `MakeWeak`, and what C# has with its finalizers.

Such a feature would be non-deterministic, since it depends on when the garbage collector runs; the callback may never run at all. But it could be useful for performing cleanup tasks related to a given weak reference. I imagine it could even be emulated with polling plus weak references, so there should be nothing fundamentally new here.

Personally I would find this feature somewhere between useful and an attractive nuisance. It would have to be carefully advertised as for last-ditch cleanup, not a substitute for deterministic disposal (via e.g. a `dispose()` method). C# has a similar dichotomy, with `IDisposable` for deterministic disposal, and a conventional pattern where you call `dispose()` in your finalizer if the consumer forgot to do so themselves.

What do people think of this feature?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Mark S. Miller-2
On Wed, Nov 6, 2013 at 10:49 AM, Domenic Denicola <[hidden email]> wrote:
Over lunch I was discussing ES6 and ES7 features with some developers doing JavaScript crypto, and they mentioned an interest in not only weak references, but weak callbacks. That is, a notification when your object gets garbage collected, similar (I think) to what V8 has with its `MakeWeak`, and what C# has with its finalizers.

Such a feature would be non-deterministic, since it depends on when the garbage collector runs; the callback may never run at all. But it could be useful for performing cleanup tasks related to a given weak reference. I imagine it could even be emulated with polling plus weak references, so there should be nothing fundamentally new here.

Personally I would find this feature somewhere between useful and an attractive nuisance. It would have to be carefully advertised as for last-ditch cleanup, not a substitute for deterministic disposal (via e.g. a `dispose()` method). C# has a similar dichotomy, with `IDisposable` for deterministic disposal, and a conventional pattern where you call `dispose()` in your finalizer if the consumer forgot to do so themselves.

What do people think of this feature?

In a garbage collected language, this is known as pre-mortem finalization, as in Java's finalize method and finalizer queue, and it is an unmitigated disaster. It is like shared state multi-threading in that it creates a category of bugs -- in this case, resurrection bugs -- that you totally underestimate until you get bitten by them over and over, in code you thought you had carefully thought through.

The problem is that, upon invoking the finalize method of the condemned object, the object is *no longer* garbage because it is running. Since non-garbage is reachable from garbage, the condemned object can make state changes to non-condemned state, including storing a pointer back to itself *or other co-condemned objects*, "resurrecting" them in that they are now non-garbage.

Post-mortem finalization by various Smalltalk folks was a major innovation. Its central insight is that computation never touches condemned state, and so you never need worry about the possibility of resurrection. I have found that anything useful that could be expressed with pre-mortem finalization can be expressed, usually better, with post-mortem finalization by a bit of refactoring.


 
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: Weak callbacks?

Domenic Denicola-2
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?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Mark S. Miller-2
It is part of the WeakRefs proposal. Always has been.


On Wed, Nov 6, 2013 at 11:15 AM, Domenic Denicola <[hidden email]> 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?



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Brian Di Palma
In reply to this post by Domenic Denicola-2
Are these callbacks triggered for the garbage collection of any object
or just weakrefs?
They could be useful to help track down memory leaks, although the
tooling in Chrome is quite good for that.

On Wed, Nov 6, 2013 at 7:15 PM, Domenic Denicola
<[hidden email]> 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?
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Mark S. Miller-2
First, I'll cheekily answer what you asked instead of what you meant to ask:

One of the important properties of post-mortem finalization is that it is *not* triggered by the collection of the weakref itself, and is not triggered if the weakref is co-condemned with the object it points at.

On your real question, the answer is no. This might be appropriate as parts of the guts of some fancy debugger as you suggest. But as something generally available in the language, its cost would be prohibitive.



On Wed, Nov 6, 2013 at 11:18 AM, Brian Di Palma <[hidden email]> wrote:
Are these callbacks triggered for the garbage collection of any object
or just weakrefs?
They could be useful to help track down memory leaks, although the
tooling in Chrome is quite good for that.

On Wed, Nov 6, 2013 at 7:15 PM, Domenic Denicola
<[hidden email]> 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?
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Rick Waldron
In reply to this post by Domenic Denicola-2



On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <[hidden email]> 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?

Rick


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Oliver Hunt-2
On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:




On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Mark S. Miller-2
On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:

On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <[hidden email]> 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,

I don't. I don't believe such a thing is possible, almost by definition. That's why I initially proposed separating the WeakMap and WeakRef concepts, because the first provides some of the benefits of weakness without this exposure.

 
but in general i’m opposed to both them and finalisers :-/

They go together anyway. I am for both of them in ES7, because they have large benefits and we now have an idea (previously posted to the list) of how to retain the portion of these benefits that matter, while limiting the leakage in ways that let us still build secure systems and reason about their security.

More later...


—Oliver

Rick

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Mark Miller-2
In reply to this post by Rick Waldron
The handler gets notified by the garbage collector. There are two conventional ways for this to be specific to the object being gc'ed.

1) Just create a unique handler for each weakref registration. If *this* handler gets notified, then it knows that the object it was about has been gc'ed.

2) (The old Smalltalk way) Have the primitive abstraction be a vector of weakrefs, which for short I'll just call a weak vector. (I avoid the term "array" here only because we're talking about JavaScript.) Handlers are registered on a weak vector as a whole, not on individual indexes. The handler notification message includes the index of the cauterized (nulled) reference.

The WeakRef proposal I wrote up uses technique #1. Technique #2 has implementation advantages and we should consider it.




On Wed, Nov 6, 2013 at 3:14 PM, Rick Waldron <[hidden email]> wrote:



On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <[hidden email]> 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?

Rick


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss




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

  Cheers,
  --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Katelyn Gadd
In reply to this post by Oliver Hunt-2
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?)

On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:




On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Mark S. Miller-2



On Wed, Nov 6, 2013 at 7:37 PM, K. Gadd <[hidden email]> 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?)

Yes, that's the idea. 



 

On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:




On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss





--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Terrence Cole-3
In reply to this post by Katelyn Gadd
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@.../msg00572.html

> On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
>
>> On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:
>>
>>
>>
>>
>> On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <
>> [hidden email]> 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
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Katelyn 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 <[hidden email]> 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@.../msg00572.html

> On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
>
>> On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:
>>
>>
>>
>>
>> On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <
>> [hidden email]> 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
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Mark S. Miller-2
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 <[hidden email]> 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 <[hidden email]> 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@.../msg00572.html

> On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
>
>> On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:
>>
>>
>>
>>
>> On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <
>> [hidden email]> 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
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>





--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Katelyn 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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@.../msg00572.html

> On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
>
>> On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:
>>
>>
>>
>>
>> On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <
>> [hidden email]> 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
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>





--
    Cheers,
    --MarkM


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Felix-54
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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@.../msg00572.html

> On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
>
>> On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:
>>
>>
>>
>>
>> On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <
>> [hidden email]> 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
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>





--
    Cheers,
    --MarkM


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Katelyn 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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@.../msg00572.html

> On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
>
>> On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:
>>
>>
>>
>>
>> On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <
>> [hidden email]> 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
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>





--
    Cheers,
    --MarkM



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

Felix-54
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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@.../msg00572.html

> On Wed, Nov 6, 2013 at 3:23 PM, Oliver Hunt <[hidden email]> wrote:
>
>> On Nov 6, 2013, at 3:14 PM, Rick Waldron <[hidden email]> wrote:
>>
>>
>>
>>
>> On Wed, Nov 6, 2013 at 2:15 PM, Domenic Denicola <
>> [hidden email]> 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
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>





--
    Cheers,
    --MarkM



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Weak callbacks?

David Bruant-5
In reply to this post by Katelyn Gadd
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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
1234