Skip to content

Instantly share code, notes, and snippets.

@akpsgit
Created May 26, 2024 09:47
Show Gist options
  • Save akpsgit/62af6e4232e8ddfb88cc12d050200ef3 to your computer and use it in GitHub Desktop.
Save akpsgit/62af6e4232e8ddfb88cc12d050200ef3 to your computer and use it in GitHub Desktop.
Syft 1.4.1 memory profiling for big image
package main
// Using github.com/anchore/syft@v1.4.1/examples/create_simple_sbom/main.go
import (
"context"
"fmt"
"github.com/anchore/syft/syft/format"
"github.com/anchore/syft/syft/format/syftjson"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
"log"
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"time"
"github.com/anchore/syft/syft"
)
const defaultImage = "public.ecr.aws/ciscoeti/apa/bestbags-delivery@sha256:a560bdbb72f563b4be354f414aa812d442a9c1a0527d6687f95f67c8c57a65bc"
func main() {
go PrintMemUsage()
// automagically get a source.Source for arbitrary string input
src := getSource(imageReference())
// catalog the given source and return a SBOM
_ = getSBOM(src)
// take the SBOM object and encode it into the syft-json representation
//bytes := formatSBOM(sbom)
// show the SBOM!
//fmt.Println(string(bytes))
}
func imageReference() string {
// read an image string reference from the command line or use a default
if len(os.Args) > 1 {
return os.Args[1]
}
return defaultImage
}
func getSource(input string) source.Source {
src, err := syft.GetSource(context.Background(), input, nil)
if err != nil {
panic(err)
}
return src
}
func getSBOM(src source.Source) sbom.SBOM {
s, err := syft.CreateSBOM(context.Background(), src, nil)
if err != nil {
panic(err)
}
return *s
}
func formatSBOM(s sbom.SBOM) []byte {
bytes, err := format.Encode(s, syftjson.NewFormatEncoder())
if err != nil {
panic(err)
}
return bytes
}
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