Weak pointers in Go: why they matter now
victoriametrics.com
victoriametrics.com
(*) though not all e.g. I think lua doesn't have straight up weakrefs, though tables can be made weak in key or value.
https://cs.opensource.google/go/go/+/master:src/runtime/mhea...
Looks like most of it is implemented directly in the runtime.
The good news is the vast majority of code using Weak semantics is gratuitous - "clever" code that is actually broken premature optimization, and the fix is to just Don't Do That.
- you need to remember to check the result for nil/null, but the type system won't tell you
- if you upgrade twice in a row, you can have both fail, both succeed, or the first one succeed and the second one fail
It can also be tricky to use them as building blocks for weak collections, if you want to avoid unbounded growth.
/facepalm
I appreciate Golang's directness but they _really_ could have done a few things much better.
runtime: pointer 0xc00379ac60 to unused region of span span.base()=0xc001794000 span.limit=0xc001795e00 span.state=1
fatal error: found bad pointer in Go heap (incorrect use of unsafe or cgo?)
runtime: nelems=8 nalloc=5 previous allocCount=4 nfreed=65535
fatal error: sweep increased allocation countI think we have different definitions of "arbitrary"
To me it seems rather arbitrary that appending to a slice concurrently in two different goroutines causes the garbage collector's sweep-phase to internally think another allocation has occurred.
[1] https://wingolog.org/archives/2022/10/31/ephemerons-and-fina...
[2] http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-...
Genuinely curious as I have implemented one such system in Go. Maybe I could improve in some stuff.
I did use some kind of weakreference substitute (using an integer map) but that was because I was lacking a feature (some kind of dependent type).
Imagine input A affects node B affects output C. Then you probably want B to be collected if C becomes garbage. So the strong references need to go C→B→A. But the way a simple push strategy would actually proceed if A changes would be that A triggers a reevaluation of B, which then triggers a reevaluation of C. But A could be either immortal for semantic reasons (e.g. “the left mouse button was clicked” can’t really become garbage) or perhaps kept alive by some entirely unrelated dependent D. So A needs to be able to refer to B if it’s still alive but must not hold B alive, and similarly for the edge between B and C.
The way to deal with this is to have store dependents in a weak set. (I don’t actually see how to implement one with plain weak references without finalizers.) Alternatively, just give up and say the dependency graph needs to be specified up front and only dies as a whole.
My own dependency-graph/reactivity thing is not ready to see the light of day, so if you want some references I guess I can direct you to the author of the Sodium FRP library (not to be confused with the libsodium crypto library) and an FRP book mentioning[1] he implemented a cycle collector as a workaround for the lack of weak references in JavaScript (at the time).
[1] https://web.archive.org/web/20240507181526/http://sodium.nz/...
Unlike reactish frameworks, I do not track dependencies but my reactive model is different and more fine-grained/lower-level. It's not needed.
https://wakatime.com/blog/48-go-desperately-needs-nil-safe-t...
> Interestingly, it used to be more of an internal tool, but recently there’s been a push to make it public
I think your anti-intellectual bubble should be safe.