package main

import (
	"fmt"
	"os"
	"runtime"
	"runtime/metrics"
)

var live [][]byte
var scratch []byte

func snapshot(label string) {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	s := []metrics.Sample{{Name: "/gc/heap/goal:bytes"}, {Name: "/gc/heap/live:bytes"}, {Name: "/gc/gogc:percent"}, {Name: "/gc/gomemlimit:bytes"}}
	metrics.Read(s)
	fmt.Printf("%s: HeapAlloc=%d NumGC=%d goal=%d live=%d runtime-memory=%d\n", label, m.HeapAlloc, m.NumGC, s[0].Value.Uint64(), s[1].Value.Uint64(), m.Sys-m.HeapReleased)
}
func main() {
	fmt.Println("settings:", "GOGC="+os.Getenv("GOGC"), "GOMEMLIMIT="+os.Getenv("GOMEMLIMIT"))
	for i := range 16 {
		b := make([]byte, 1<<20)
		b[0] = byte(i)
		live = append(live, b)
	}
	runtime.GC()
	snapshot("keep 16 MiB")
	for i := range 128 {
		scratch = make([]byte, 1<<20)
		scratch[0] = byte(i)
	}
	scratch = nil
	snapshot("after allocating 128 MiB")
	runtime.GC()
	snapshot("after forced GC")
	runtime.KeepAlive(live)
	live = nil
	runtime.GC()
	snapshot("after dropping live data")
}
