Skip to content

Instantly share code, notes, and snippets.

@akpsgit
Created September 20, 2023 13:58
Show Gist options
  • Save akpsgit/bc14660363f3217c9df8d1e8900076cf to your computer and use it in GitHub Desktop.
Save akpsgit/bc14660363f3217c9df8d1e8900076cf to your computer and use it in GitHub Desktop.
Syft memory profiling
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"time"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/pkg/cataloger"
"github.com/anchore/syft/syft/source"
)
func main() {
go PrintMemUsage()
detection, err := source.Detect("public.ecr.aws/ciscoeti/apa/bestbags-delivery@sha256:a560bdbb72f563b4be354f414aa812d442a9c1a0527d6687f95f67c8c57a65bc", source.DefaultDetectConfig())
if err != nil {
panic(fmt.Sprintf("failed to detect source: %v", err))
}
s, err := detection.NewSource(source.DefaultDetectionSourceConfig())
if err != nil {
panic(fmt.Sprintf("failed to create source: %v", err))
}
catalogerConfig := cataloger.Config{
Search: cataloger.DefaultSearchConfig(),
}
catalogerConfig.Search.Scope = source.SquashedScope
_, _, _, err = syft.CatalogPackages(s, catalogerConfig)
if err != nil {
panic(fmt.Sprintf("failed to catalog packages: %v", err))
}
}
type Profiler struct {
cpuf *os.File
filesPath string
filesPrefix string
}
func CreateProfiler(path string) *Profiler {
return &Profiler{
filesPath: path,
filesPrefix: time.Now().Format("20060102150405"),
}
}
func (p *Profiler) WriteHeapProfile() error {
memf, err := os.Create(filepath.Join(p.filesPath, p.filesPrefix+"-mem.prof"))
if err != nil {
return fmt.Errorf("failed to create memory file: %v", err)
}
defer memf.Close()
runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(memf); err != nil {
return fmt.Errorf("failed to write memory profile: %v", err)
}
return nil
}
func PrintMemUsage() {
dumped := false
for {
var m runtime.MemStats
runtime.ReadMemStats(&m)
allocMB := m.Alloc / 1024 / 1024
fmt.Printf("Alloc = %v MiB", allocMB)
fmt.Printf("\tTotalAlloc = %v MiB", m.TotalAlloc/1024/1024)
fmt.Printf("\tSys = %v MiB", m.Sys/1024/1024)
fmt.Printf("\tNumGC = %v\n", m.NumGC)
if allocMB > 800 && !dumped {
path, err := os.Getwd()
if err != nil {
panic(fmt.Sprintf("Failed to get path: %v", err))
}
prof := CreateProfiler(path)
log.Println("More than 800 MB is allocated!!! dumping memory profile")
prof.WriteHeapProfile() // go tool pprof -http=:8080 ./20230920165704-mem.prof
if err != nil {
panic(fmt.Sprintf("Failed to write memory profiling: %v", err))
}
dumped = true
}
time.Sleep(time.Second)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment