Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finalizer statistics

Is there a way to obtain the total number of finalizers registered using runtime.SetFinalizer and which have not yet run?

We are considering adding a struct with a registered finalizer to some of our products to release memory allocated using malloc, and the object could potentially have a relatively high allocation rate. It would be nice if we could monitor the number of finalizers, to make sure that they do not pile up and trigger out-of-memory errors (like they tend to with other garbage collectors).

(I'm aware that explicit deallocation would avoid this problem, but we cannot change the existing code, which does not call a Close function or something like that.)

like image 624
Florian Weimer Avatar asked Dec 03 '17 14:12

Florian Weimer


Video Answer


1 Answers

You can keep keep a count of these objects by incrementing and decrementing a unexported package variable when a new object is created and finalized, respectively.

For example:

package main

import (
    "fmt"
    "runtime"
    "sync/atomic"
)

var totalObjects int32

func TotalObjects() int32 {
    return atomic.LoadInt32(&totalObjects)
}

type Object struct {
    p uintptr // C allocated pointer
}

func NewObject() *Object {
    o := &Object{
    }
    // TODO: perform other initializations
    atomic.AddInt32(&totalObjects, 1)
    runtime.SetFinalizer(o, (*Object).finalizer)
    return o
}

func (o *Object) finalizer() {
    atomic.AddInt32(&totalObjects, -1)
    // TODO: perform finalizations
}

func main() {
    fmt.Println("Total objects:", TotalObjects())
    for i := 0; i < 100; i++ {
        _ = NewObject()
        runtime.GC()
    }
    fmt.Println("Total objects:", TotalObjects())
}

https://play.golang.org/p/n35QABBIcj

like image 54
Tim Cooper Avatar answered Sep 19 '22 13:09

Tim Cooper