fix(lotus-sim): write pprof profiles to a directory

We need to know the sizes up-front for tar, and that's not happening.
This commit is contained in:
Steven Allen 2021-06-09 21:51:59 -07:00
parent 7a8bfd8725
commit 977bf1cad9
2 changed files with 26 additions and 19 deletions

View File

@ -1,12 +1,11 @@
package main package main
import ( import (
"archive/tar"
"context" "context"
"fmt" "fmt"
"io"
"os" "os"
"os/signal" "os/signal"
"path/filepath"
"runtime/pprof" "runtime/pprof"
"time" "time"
@ -14,32 +13,35 @@ import (
) )
func takeProfiles(ctx context.Context) (fname string, _err error) { func takeProfiles(ctx context.Context) (fname string, _err error) {
file, err := os.CreateTemp(".", ".profiles*.tar") dir, err := os.MkdirTemp(".", ".profiles-temp*")
if err != nil { if err != nil {
return "", err return "", err
} }
defer file.Close()
if err := writeProfiles(ctx, file); err != nil { if err := writeProfiles(ctx, dir); err != nil {
_ = os.Remove(file.Name()) _ = os.RemoveAll(dir)
return "", err return "", err
} }
fname = fmt.Sprintf("pprof-simulation-%s.tar", time.Now()) fname = fmt.Sprintf("pprof-simulation-%s", time.Now().Format(time.RFC3339))
if err := os.Rename(file.Name(), fname); err != nil { if err := os.Rename(dir, fname); err != nil {
_ = os.Remove(file.Name()) _ = os.RemoveAll(dir)
return "", err return "", err
} }
return fname, nil return fname, nil
} }
func writeProfiles(ctx context.Context, w io.Writer) error { func writeProfiles(ctx context.Context, dir string) error {
tw := tar.NewWriter(w)
for _, profile := range pprof.Profiles() { for _, profile := range pprof.Profiles() {
if err := tw.WriteHeader(&tar.Header{Name: profile.Name()}); err != nil { file, err := os.Create(filepath.Join(dir, profile.Name()+".pprof.gz"))
if err != nil {
return err return err
} }
if err := profile.WriteTo(tw, 0); err != nil { if err := profile.WriteTo(file, 0); err != nil {
_ = file.Close()
return err
}
if err := file.Close(); err != nil {
return err return err
} }
if err := ctx.Err(); err != nil { if err := ctx.Err(); err != nil {
@ -47,20 +49,25 @@ func writeProfiles(ctx context.Context, w io.Writer) error {
} }
} }
if err := tw.WriteHeader(&tar.Header{Name: "cpu"}); err != nil { file, err := os.Create(filepath.Join(dir, "cpu.pprof.gz"))
if err != nil {
return err return err
} }
if err := pprof.StartCPUProfile(tw); err != nil {
if err := pprof.StartCPUProfile(file); err != nil {
_ = file.Close()
return err return err
} }
select { select {
case <-time.After(30 * time.Second): case <-time.After(30 * time.Second):
case <-ctx.Done(): case <-ctx.Done():
pprof.StopCPUProfile()
return ctx.Err()
} }
pprof.StopCPUProfile() pprof.StopCPUProfile()
return tw.Close() err = file.Close()
if err := ctx.Err(); err != nil {
return err
}
return err
} }
func profileOnSignal(cctx *cli.Context, signals ...os.Signal) { func profileOnSignal(cctx *cli.Context, signals ...os.Signal) {

View File

@ -15,7 +15,7 @@ var runSimCommand = &cli.Command{
Signals: Signals:
- SIGUSR1: Print information about the current simulation (equivalent to 'lotus-sim info'). - SIGUSR1: Print information about the current simulation (equivalent to 'lotus-sim info').
- SIGUSR2: Write a pprof profile to pprof-simulation-$DATE.tar`, - SIGUSR2: Write pprof profiles to ./pprof-simulation-$DATE/`,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.IntFlag{ &cli.IntFlag{
Name: "epochs", Name: "epochs",