ortuman / nuke

⚡ A memory arena implementation for Go.
Apache License 2.0
500 stars 13 forks source link

Arena's allocated memory is not retained and will be garbage collected #15

Closed mumbleskates closed 8 months ago

mumbleskates commented 8 months ago

"Live" arenas are not kept alive by strong pointers, only by weak unsafe.Pointers; as far as the GC is concerned, these do not count as references to the memory and the allocation can be deleted.

package main

import (
    "runtime"

    "github.com/ortuman/nuke"
)

func main() {
    ended := false
    hasGC := 0
    arena := nuke.NewSlabArena(256*1024, 1)
    // We can at least show that the GC will call finalizers for pointers anywhere
    // inside the slab's range when it is released, ignoring the type.
    _ = nuke.MakeSlice[int](arena, 1, 10)
    finalizable := nuke.New[int](arena)
    *finalizable = 55
    runtime.SetFinalizer(finalizable, func(gettingDeleted *int) {
        // This only happens when the memory is freed. Without finalizers,
        // this memory would be immediately available for reuse by the
        // global allocator.
        println(
            "finalizer called successfully:", *gettingDeleted,
            "; main has ended:", ended,
            "; has GC'd:", hasGC, "time",
        )
    })
    runtime.GC()
    hasGC++
    runtime.GC()
    hasGC++
    runtime.GC()
    hasGC++
    runtime.GC()
    hasGC++
    ended = true
}

https://go.dev/play/p/9uDhMWAdBC2

mumbleskates commented 8 months ago

whoops! i am pretty sure i was wrong about this one. the arena's memory is kept alive by the unsafe pointer, it's just getting disposed because arena is not referenced after the garbage collection cycles. i've not been able to make a later-used arena dispose early, or make two arenas' memory alias (unless ownership is stored in another arena, in which case they absolutely get disposed of, due to #14