00:28 | <shu> | as it turns out, it is super hard to use weakrefs correctly, whoda thought |
00:45 | <devsnek> | whatcha' weakref'n |
00:47 | <drousso_> | really? |
00:48 | <drousso_> | i'd love to know more |
00:48 | <drousso_> | i have plans/hopes to use them quite extensively for certain things |
00:48 | <shu> | i was writing an example for a talk which wraps event listeners in weakrefs so you don't have to manually unregister event listeners |
00:48 | <shu> | since that's a super common way to leak memory |
00:49 | <shu> | my example had a class like so: |
00:49 | <devsnek> | i don't think i've ever heard of memory being leaked via event listeners |
00:49 | <devsnek> | except code that accidentally attaches them in a loop |
00:52 | <shu> | https://gist.github.com/syg/13d44f2b1a36095a90f722a1b84e6da2 |
00:53 | <shu> | if you forget to unregister an event listener when you close a panel, for instance, it tends to leak everything the listener held onto |
00:54 | <shu> | it is my impression that's a common gotcha in frontend programming |
00:54 | <shu> | oops, that gist has a bug |
00:55 | <shu> | reload please |
00:55 | <shu> | drousso_: can you spot the bug? `this.listener` isn't collectable in V8's GC |
00:55 | <shu> | and i reckon in JSC's GC as well |
00:56 | <drousso_> | shu that's actually one of the primary use cases i'd want 😅 |
00:56 | <drousso_> | Web Inspector has it's own event listener system which keeps things alive |
00:56 | <shu> | drousso_: yep! |
00:56 | <drousso_> | using a `WeakRef` to hold the `thisObject` would likely eliminate that issue |
00:56 | <shu> | there're plenty of google JS code that has some notion of "observer" that gets misused |
00:56 | <shu> | and leaks craptons |
00:57 | <devsnek> | the listener function isn't collectable? |
00:57 | <shu> | nope |
00:57 | <drousso_> | shu is the issue that `this` is captured by the arrow function? |
00:57 | <shu> | it's for a really shitty subtle reason |
00:57 | <shu> | drousso_: bingo, specifically, this chain: |
00:57 | <shu> | - this.listener captures `this` |
00:57 | <drousso_> | ya |
00:57 | <devsnek> | but `this` is the only thing that holds it |
00:57 | <devsnek> | isn't that a normal cycle |
00:57 | <shu> | - the wrapper arrow function is held onto strongly by the holdings of the FR |
00:58 | <drousso_> | shu i agree that that's a pretty massive footgun |
00:58 | <shu> | the wrapper arrow holds alive the environment of the function |
00:58 | <devsnek> | oh the other arrow function |
00:58 | <shu> | the environment has references to two things: the `this`, and `weakRef` |
00:58 | <devsnek> | y'all should not capture `this` if nothing inside references it |
00:58 | <drousso_> | shu if you're curious, i prototyped a patch for Web Inspector's event listener system to use `WeakRef` <https://webkit.org/b/196956> |
00:59 | <shu> | which means the FR can reach the `this` in the environment, and thus `this.listener`, making `this.listener` held alive by the FR |
00:59 | <drousso_> | the way i did it was just to manually change it so that we never used an arrow function :P |
00:59 | <shu> | devsnek: V8 tried a patch to split the environment so that there are different environments for different inner closures |
00:59 | <Bakkot> | off |
00:59 | <drousso_> | the majority of Web Inspector's event listener usage is bound to a prototype function anyways (i.e. non-local non-anonymous functions) so it's not that bad IMO |
00:59 | <Bakkot> | *oof |
00:59 | <shu> | e.g., in that example, the first arrow only captures `this`, but the second arrow only captures `weakRef`, so they shouldn't both capture the *same* environment that has both things alive |
00:59 | <shu> | that patch ended up causing memory regressions and couldn't land |
01:00 | <shu> | so there is no easy answer atm |
01:00 | <devsnek> | aw |
01:00 | <Bakkot> | I do not think we should be telling webdevs about weakrefs |
01:00 | <shu> | haha |
01:00 | <Bakkot> | weakrefs are for chains with wasm, and for no other purpose |
01:00 | <Bakkot> | s/chains/cycles/ |
01:00 | <shu> | drousso_: yeah, bind() is okay for V8 |
01:00 | <drousso_> | oh we don't even use `bind()` |
01:00 | <drousso_> | sorry i should've clarified |
01:00 | <devsnek> | Bakkot: web devs write wasm now |
01:00 | <shu> | Bakkot: fwiw i do think the event listener case *is* compelling |
01:00 | <Bakkot> | devsnek no they don't |
01:00 | <shu> | you almost never want to hold onto event listeners strongly |
01:00 | <Bakkot> | devsnek their tools do |
01:01 | <devsnek> | nah they manually write the heap implementation |
01:01 | <drousso_> | shu because we have our own Event Listener system, we allow the `thisObject` to passed in along with the `listener`, which are both held by the `eventTarget` |
01:01 | <Bakkot> | devsnek well, they should not do that either |
01:01 | <shu> | drousso_: ah ha |
01:01 | <Bakkot> | webdevs use weakrefs too I'm sure |
01:01 | <Bakkot> | but, like, don't |
01:01 | <devsnek> | i use weakrefs sometimes |
01:01 | <drousso_> | shu this way we can avoid creating new functions when using a prototype/class function as the `listener` |
01:01 | <shu> | i mean the "you must be this tall to ride" is like 10ft |
01:01 | <devsnek> | i should check for that in my usage of them |
01:02 | <shu> | because it requires you to understand, like this example shows, to understand not only the GC but how closures are represented |
01:02 | <shu> | which seems unreasonable to ask of for most web devs |
01:02 | <Bakkot> | shu I clean up my listeners manually when I'm done with them, which seems... obviously superior? |
01:02 | <Bakkot> | I guess this is the manual vs automatic memory management debate |
01:02 | <shu> | Bakkot: correct |
01:02 | <Bakkot> | except that the automatic one is way harder to use because it is not automatic at all |
01:02 | <devsnek> | why do js devs not leaksan |
01:02 | <drousso_> | Bakkot the "problem" with that is knowing when you're done with them |
01:03 | <drousso_> | it's totally doable |
01:03 | <shu> | Bakkot: at even google levels of effort, whatever you take that to mean, there is evidence that manual management does not scale to complex projects, like GSuite |
01:03 | <drousso_> | just can be hard to keep track of as the size of something increases |
01:03 | <shu> | leaks abound |
01:03 | <shu> | there is a Disposable pattern that people recommend using |
01:03 | <drousso_> | ^ same here |
01:03 | <shu> | but it is buggy |
01:04 | <Bakkot> | shu I am not convinced leaks will go down if we tell people about weakrefs, though |
01:04 | <shu> | that's a separate discussion |
01:04 | <drousso_> | i think it's more library/framework authors that'll benefit |
01:04 | <shu> | i definitely agree most people will use them wrong |
01:04 | <shu> | but yeah i agree with drousso_ |
01:04 | <Bakkot> | right, so, we shouldn't tell webdevs about weakrefs :P |
01:04 | <shu> | i want the framework people at the big web property cos to hear about it |
01:05 | <drousso_> | lol |
01:05 | <drousso_> | ah poop i gtg |
01:05 | <devsnek> | when someone asks about weakrefs "who's asking 👀" |
01:05 | <drousso_> | have a good night yall :) |
01:05 | <drousso_> | (or equivalent wherever you are) |
01:05 | <shu> | g'night |
01:05 | <Bakkot> | we should get yusuke or someone to write a library that does the right thing and tell people about that instea |
01:05 | <Bakkot> | d |
01:06 | <Bakkot> | maybe I'll ask Gilad if he wants to do that after his current project |
01:07 | <Bakkot> | the answer will be no, though |
01:07 | <shu> | gilad? |
01:07 | <Bakkot> | https://en.wikipedia.org/wiki/Gilad_Bracha |
01:08 | <Bakkot> | used to sit two desks over from me, back when being proximate to other people was not illegal |
01:08 | <devsnek> | oh he made java |
01:08 | <shu> | ah *the* gilad |
01:08 | <shu> | he's at f5? |
01:09 | <Bakkot> | yeah, joined Shape a few months before the acquisition |
01:09 | <shu> | oh wow, good catch |
01:09 | <shu> | sure ask away, i'm also sure it'll be a no |
01:09 | <rkirsling> | lol he made a Newspeak language with all sorts of associated 1984 references? |
01:10 | <rkirsling> | amusing |
14:37 | <littledan> | shu: Everyone's been talking about this observer pattern as a primary use case; it'd be great to have some code for this in the WeakRefs README so people can use it as a "cookbook" |
14:37 | <littledan> | once you work it out correctly... |
15:08 | <shu> | littledan: a cookbook sounds good... |