From b6f15b3c5e48455b1a86ce1436572488b41ae6c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bo=CC=88wer?= Date: Wed, 2 Jul 2025 19:09:21 +0200 Subject: [PATCH 1/3] feat(profiling): Add `--trace-profile` flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduces a new --trace-profile [file] flag to generate a Go execution trace, enabling easier diagnosis of latency-related performance issues Signed-off-by: Jonas Böwer Signed-off-by: Jonas Böwer --- cmd/buildah/main.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cmd/buildah/main.go b/cmd/buildah/main.go index 4271fd9b7..0e5f9a229 100644 --- a/cmd/buildah/main.go +++ b/cmd/buildah/main.go @@ -7,6 +7,7 @@ import ( "os/exec" "runtime" "runtime/pprof" + "runtime/trace" "strings" "syscall" @@ -38,6 +39,8 @@ type globalFlags struct { CPUProfile string cpuProfileFile *os.File MemoryProfile string + TraceProfile string + traceProfileFile *os.File UserShortNameAliasConfPath string CgroupManager string } @@ -105,6 +108,7 @@ func init() { rootCmd.PersistentFlags().StringVar(&globalFlagResults.LogLevel, logLevel, "warn", `the log level to be used, one of "trace", "debug", "info", "warn", "error", "fatal", or "panic"`) rootCmd.PersistentFlags().StringVar(&globalFlagResults.CPUProfile, "cpu-profile", "", "`file` to write CPU profile") rootCmd.PersistentFlags().StringVar(&globalFlagResults.MemoryProfile, "memory-profile", "", "`file` to write memory profile") + rootCmd.PersistentFlags().StringVar(&globalFlagResults.TraceProfile, "trace-profile", "", "`file` to write trace profile") if err := rootCmd.PersistentFlags().MarkHidden("cpu-profile"); err != nil { logrus.Fatalf("unable to mark cpu-profile flag as hidden: %v", err) @@ -118,6 +122,9 @@ func init() { if err := rootCmd.PersistentFlags().MarkHidden("memory-profile"); err != nil { logrus.Fatalf("unable to mark memory-profile flag as hidden: %v", err) } + if err := rootCmd.PersistentFlags().MarkHidden("trace-profile"); err != nil { + logrus.Fatalf("unable to mark trace-profile flag as hidden: %v", err) + } } func initConfig() { @@ -157,6 +164,16 @@ func before(cmd *cobra.Command) error { } } + if globalFlagResults.TraceProfile != "" { + globalFlagResults.traceProfileFile, err = os.Create(globalFlagResults.TraceProfile) + if err != nil { + logrus.Fatalf("could not create trace output file %s: %v", globalFlagResults.TraceProfile, err) + } + if err := trace.Start(globalFlagResults.traceProfileFile); err != nil { + logrus.Fatalf("could not start trace: %v", err) + } + } + defaultContainerConfig, err := config.Default() if err != nil { return err @@ -219,6 +236,10 @@ func after(cmd *cobra.Command) error { logrus.Fatalf("could not write memory profile %s: %v", globalFlagResults.MemoryProfile, err) } } + if globalFlagResults.TraceProfile != "" { + trace.Stop() + globalFlagResults.traceProfileFile.Close() + } return nil } From 8863f8c9ed5b637ab21d77576b8f4bef87e2c476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bo=CC=88wer?= Date: Fri, 11 Jul 2025 12:16:32 +0200 Subject: [PATCH 2/3] tests: add profiling.bats to test --trace-profile, --cpu-profile, and --memory-profile flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Böwer --- tests/profiling.bats | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/profiling.bats diff --git a/tests/profiling.bats b/tests/profiling.bats new file mode 100644 index 000000000..d759be522 --- /dev/null +++ b/tests/profiling.bats @@ -0,0 +1,33 @@ +#!/usr/bin/env bats + +load helpers + +@test "trace-profile flag creates a valid Go trace" { + tmpfile="$TEST_SCRATCH_DIR/buildah-trace.$RANDOM.$RANDOM" + run_buildah info --trace-profile="$tmpfile" + assert "$status" -eq 0 "buildah info with --trace-profile should succeed" + [ -s "$tmpfile" ] || die "trace profile should not be empty" + run go tool trace -d=2 "$tmpfile" + assert "$status" -eq 0 "go tool trace should succeed" + rm -f "$tmpfile" +} + +@test "cpu-profile flag creates a valid CPU profile" { + tmpfile="$TEST_SCRATCH_DIR/buildah-cpu.$RANDOM.$RANDOM" + run_buildah info --cpu-profile="$tmpfile" + assert "$status" -eq 0 "buildah info with --cpu-profile should succeed" + [ -s "$tmpfile" ] || die "CPU profile should not be empty" + run go tool pprof -top "$tmpfile" + assert "$status" -eq 0 "go tool pprof should succeed on CPU profile" + rm -f "$tmpfile" +} + +@test "memory-profile flag creates a valid memory profile" { + tmpfile="$TEST_SCRATCH_DIR/buildah-mem.$RANDOM.$RANDOM" + run_buildah info --memory-profile="$tmpfile" + assert "$status" -eq 0 "buildah info with --memory-profile should succeed" + [ -s "$tmpfile" ] || die "memory profile should not be empty" + run go tool pprof -top "$tmpfile" + assert "$status" -eq 0 "go tool pprof should succeed on memory profile" + rm -f "$tmpfile" +} \ No newline at end of file From e897bd8e47caafd6144ea3e3f52ed5c2c4bc49df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bo=CC=88wer?= Date: Fri, 11 Jul 2025 12:43:05 +0200 Subject: [PATCH 3/3] tests: use stable -pprof=net flag for go tool trace validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Böwer --- tests/profiling.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/profiling.bats b/tests/profiling.bats index d759be522..1d02434e9 100644 --- a/tests/profiling.bats +++ b/tests/profiling.bats @@ -7,7 +7,7 @@ load helpers run_buildah info --trace-profile="$tmpfile" assert "$status" -eq 0 "buildah info with --trace-profile should succeed" [ -s "$tmpfile" ] || die "trace profile should not be empty" - run go tool trace -d=2 "$tmpfile" + run go tool trace -pprof=net "$tmpfile" assert "$status" -eq 0 "go tool trace should succeed" rm -f "$tmpfile" } @@ -30,4 +30,4 @@ load helpers run go tool pprof -top "$tmpfile" assert "$status" -eq 0 "go tool pprof should succeed on memory profile" rm -f "$tmpfile" -} \ No newline at end of file +}