106 lines
2.7 KiB
Go
106 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"os"
|
|
"runtime"
|
|
"runtime/debug"
|
|
"runtime/pprof"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/pkg/profile"
|
|
|
|
"github.com/alcionai/corso/src/cli"
|
|
"github.com/alcionai/corso/src/pkg/logger"
|
|
)
|
|
|
|
var (
|
|
profileTicker = time.NewTicker(1 * time.Second)
|
|
perMinuteMap = make(map[time.Time]int)
|
|
timeSinceRefresh = time.Now()
|
|
)
|
|
|
|
// var profileTicker = time.NewTicker(120 * time.Second)
|
|
var (
|
|
printTicker = time.NewTicker(1 * time.Second)
|
|
profileCounter = 0
|
|
)
|
|
|
|
func main() {
|
|
defer profile.Start(profile.MemProfile).Stop()
|
|
debug.SetMemoryLimit(1 * 1024 * 1024 * 1024)
|
|
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-profileTicker.C:
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
|
|
// if mem > 3GB and we havent captured a profile this min, capture it
|
|
// or if its been 2 mins since last profile, capture it
|
|
t := time.Now().Truncate(time.Minute)
|
|
// if (m.HeapAlloc > uint64(3*1024*1024*1024) && perMinuteMap[t] == 0) || time.Since(timeSinceRefresh) > 2*time.Minute {
|
|
if time.Since(timeSinceRefresh) > 3*time.Minute {
|
|
filename := "mem." + strconv.Itoa(profileCounter) + ".pprof"
|
|
|
|
f, _ := os.Create(filename)
|
|
if err := pprof.WriteHeapProfile(f); err != nil {
|
|
log.Fatal("could not write memory profile: ", err)
|
|
}
|
|
|
|
f.Close()
|
|
|
|
profileCounter++
|
|
perMinuteMap[t] = 1
|
|
timeSinceRefresh = time.Now()
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-printTicker.C:
|
|
PrintMemUsage()
|
|
}
|
|
}
|
|
}()
|
|
|
|
cli.Handle()
|
|
}
|
|
|
|
// PrintMemUsage outputs the current, total and OS memory being used. As well as the number
|
|
// of garage collection cycles completed.
|
|
func PrintMemUsage() {
|
|
ctx := context.Background()
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
// For info on each, see: https://golang.org/pkg/runtime/#MemStats
|
|
// logger.Ctx(ctx).Info("Alloc = ", bToMb(m.Alloc), " MB")
|
|
// logger.Ctx(ctx).Info("TotalAlloc = ", bToMb(m.TotalAlloc), " MB")
|
|
logger.Ctx(ctx).Info("HeapAlloc = ", bToMb(m.HeapAlloc), " MB") // same as Alloc
|
|
|
|
logger.Ctx(ctx).Info("HeapReleased = ", bToMb(m.HeapReleased), " MB")
|
|
logger.Ctx(ctx).Info("HeapObjects = ", bToMb(m.HeapObjects), " MB")
|
|
logger.Ctx(ctx).Info("HeapSys = ", bToMb(m.HeapSys), " MB")
|
|
logger.Ctx(ctx).Info("HeapIdle = ", bToMb(m.HeapIdle), " MB")
|
|
logger.Ctx(ctx).Info("HeapInuse = ", bToMb(m.HeapInuse), " MB")
|
|
|
|
// logger.Ctx(ctx).Info("Mallocs = ", bToMb(m.Mallocs), " MB")
|
|
// logger.Ctx(ctx).Info("Frees = ", bToMb(m.Frees), " MB")
|
|
|
|
// logger.Ctx(ctx).Info("StackInuse = ", bToMb(m.StackInuse), " MB")
|
|
// logger.Ctx(ctx).Info("StackSys = ", bToMb(m.StackSys), " MB")
|
|
|
|
// logger.Ctx(ctx).Info("Sys = ", bToMb(m.Sys), " MB")
|
|
logger.Ctx(ctx).Info("NumGC = ", m.NumGC)
|
|
}
|
|
|
|
func bToMb(b uint64) uint64 {
|
|
return b / 1024 / 1024
|
|
}
|