gogctuner icon indicating copy to clipboard operation
gogctuner copied to clipboard

What's the use of finalizer.ch?

Open yanxyc opened this issue 3 years ago • 3 comments

Avoid finalizer being collected by GC? why use chan time.Time?

yanxyc avatar Apr 07 '22 08:04 yanxyc

Avoid finalizer being collected by GC? why use chan time.Time?

the original code is from uber's blog article, I think any struct is ok~

cch123 avatar Apr 09 '22 10:04 cch123

can it just simply be runtime.KeepAlive(f.parent) or just be empty (do nothing)?

zjx20 avatar Apr 24 '22 08:04 zjx20

Thanks guys, I have done some experiments after your questions, I think this channel is useless, you can reproduce the result by following demo:

package main

import (
	"runtime"
	"time"
)

type finalizer struct {
	ref *finalizerRef
}

type finalizerRef struct {
	parent *finalizer
}

// default GOGC = 100
var previousGOGC = 100

// don't trigger err log on every failure
var failCounter = -1

func finalizerHandler(f *finalizerRef) {
	println("in final handler")

	runtime.SetFinalizer(f, finalizerHandler)
}

type person struct {
	data []byte
}

// NewTuner
//   set useCgroup to true if your app is in docker
//   set percent to control the gc trigger, 0-100, 100 or upper means no limit
//
//   modify default GOGC value in the case there's an env variable set.

func getFinal() * finalizer {
	var f = &finalizer{
	}
	f.ref = &finalizerRef{parent: f}
	runtime.SetFinalizer(f.ref, finalizerHandler)
	f.ref = nil
	return f
}

func main() {

	f := getFinal()
	println(f)

	for {
		var x = person{make([]byte, 100000)}
		time.Sleep(time.Millisecond*40)
		println(x.data[0])
	}
}

GODEBUG=gctrace=1 go run ./tuner.go

you should see every gc trigger will print a line of 'in final handler'

cch123 avatar May 05 '22 12:05 cch123