Skip to content

Commit

Permalink
pprof: take cpu and memory profiles by setting environment variables
Browse files Browse the repository at this point in the history
When run in standalone mode, the environment variables
`DOCKER_BUILDX_CPU_PROFILE` and `DOCKER_BUILDX_MEM_PROFILE` will cause
profiles to be written by the CLI.

Signed-off-by: Jonathan A. Sternberg <[email protected]>
  • Loading branch information
jsternberg committed Oct 17, 2024
1 parent 9f0ebd2 commit de4f299
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
75 changes: 75 additions & 0 deletions cmd/buildx/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"context"
"os"
"runtime"
"runtime/pprof"

"github.com/moby/buildkit/util/bklog"
"github.com/sirupsen/logrus"
)

func setupDebugProfiles(ctx context.Context) (stop func()) {
var stopFuncs []func()
if fn := setupCPUProfile(ctx); fn != nil {
stopFuncs = append(stopFuncs, fn)
}
if fn := setupHeapProfile(ctx); fn != nil {
stopFuncs = append(stopFuncs, fn)
}
return func() {
for _, fn := range stopFuncs {
fn()
}
}
}

func setupCPUProfile(ctx context.Context) (stop func()) {
if cpuProfile := os.Getenv("DOCKER_BUILDX_CPU_PROFILE"); cpuProfile != "" {
f, err := os.Create(cpuProfile)
if err != nil {
bklog.G(ctx).Warn("could not create cpu profile", logrus.WithError(err))
return nil
}

if err := pprof.StartCPUProfile(f); err != nil {
bklog.G(ctx).Warn("could not start cpu profile", logrus.WithError(err))
_ = f.Close()
return nil
}

return func() {
pprof.StopCPUProfile()
if err := f.Close(); err != nil {
bklog.G(ctx).Warn("could not close file for cpu profile", logrus.WithError(err))
}
}
}
return nil
}

func setupHeapProfile(ctx context.Context) (stop func()) {
if heapProfile := os.Getenv("DOCKER_BUILDX_MEM_PROFILE"); heapProfile != "" {
// Memory profile is only created on stop.
return func() {
f, err := os.Create(heapProfile)
if err != nil {
bklog.G(ctx).Warn("could not create memory profile", logrus.WithError(err))
return
}

// get up-to-date statistics
runtime.GC()

if err := pprof.WriteHeapProfile(f); err != nil {
bklog.G(ctx).Warn("could not write memory profile", logrus.WithError(err))
}

if err := f.Close(); err != nil {
bklog.G(ctx).Warn("could not close file for memory profile", logrus.WithError(err))
}
}
}
return nil
}
3 changes: 3 additions & 0 deletions cmd/buildx/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ func init() {
}

func runStandalone(cmd *command.DockerCli) error {
stopProfiles := setupDebugProfiles(context.TODO())
defer stopProfiles()

if err := cmd.Initialize(cliflags.NewClientOptions()); err != nil {
return err
}
Expand Down

0 comments on commit de4f299

Please sign in to comment.