blob: 3fa9d0d8861739d260f179d7f745c2e030c5fcdf [file] [edit]
package utiltrace
import (
"context"
"runtime"
"runtime/debug"
"time"
)
var compactMemory = func() {
runtime.GC()
debug.FreeOSMemory()
}
var memoryUsageMB = func() float64 {
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
bytes := stats.Sys - stats.HeapReleased
return float64(bytes) / 1024 / 1024
}
// TraceMemoryResult reflects memory usage stats collected by TraceMemory function
type TraceMemoryResult struct {
MemBeforeMB float64
MemAfterMB float64
MemPeakMB float64
MemMeanMB float64
SampleCount int
}
// TraceMemory collects memory usage with specified interval until done channel is closed
func TraceMemory(ctx context.Context, interval time.Duration, resultChannel chan TraceMemoryResult) {
compactMemory()
startMB := memoryUsageMB()
result := TraceMemoryResult{
MemBeforeMB: startMB,
MemPeakMB: startMB,
SampleCount: 1,
}
runningAverageMB := startMB
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
currentMB := memoryUsageMB()
result.SampleCount++
runningAverageMB += (currentMB - runningAverageMB) / float64(result.SampleCount)
if result.MemPeakMB < currentMB {
result.MemPeakMB = currentMB
}
case <-ctx.Done():
compactMemory()
result.MemAfterMB = memoryUsageMB()
result.MemMeanMB = runningAverageMB
resultChannel <- result
return
}
}
}