Closed
Description
Because of the internal representation of unique
values, making chains of N unique.Handle
s requires at minimum N GC cycles to reclaim. The root of the issue is the fact that we store canonical values in something like a map[T]weak.Pointer[T]
. They key in the map keeps handles further down the chain alive until they're removed from the map.
We can fix this by using a more bespoke data structure that only stores canonical values as weak.Pointer[T]
and nothing else, as in https://go.dev/cl/650256.
Below is a demonstration of the issue.
type nestedHandle struct {
next Handle[testNestedHandle]
arr [6]int
}
var n0, n1, n2, n3 nestedHandle
func TestNestedHandle(t *testing.T) {
n0 = nestedHandle{arr: [6]int{1, 2, 3, 4, 5, 6}}
n1 = nestHandle(n0)
n2 = nestHandle(n1)
n3 = nestHandle(n2)
n0 = nestedHandle{}
n1 = nestedHandle{}
n2 = nestedHandle{}
n3 = nestedHandle{}
runtime.GC() // Today, this will only enable n3 to be reclaimed.
}
func nestHandle(n nestedHandle) nestedHandle {
return nestedHandle{
next: unique.Make(n),
arr: n.arr,
}
}
https://go.dev/cl/650256 resolves this issue.