Created
May 26, 2024 09:47
-
-
Save akpsgit/62af6e4232e8ddfb88cc12d050200ef3 to your computer and use it in GitHub Desktop.
Syft 1.4.1 memory profiling for big image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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