Skip to content

Commit

Permalink
Set time and duration of profile (#18)
Browse files Browse the repository at this point in the history
Co-authored-by: Felix Geisend枚rfer <felix@felixge.de>
  • Loading branch information
brancz and felixge committed Aug 27, 2022
1 parent 1fa9aa6 commit 3cad799
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 5 deletions.
12 changes: 11 additions & 1 deletion fgprof.go
Expand Up @@ -14,6 +14,8 @@ import (
// that needs to be invoked by the caller to stop the profiling and write the
// results to w using the given format.
func Start(w io.Writer, format Format) func() error {
startTime := time.Now()

// Go's CPU profiler uses 100hz, but 99hz might be less likely to result in
// accidental synchronization with the program we're profiling.
const hz = 99
Expand All @@ -39,7 +41,15 @@ func Start(w io.Writer, format Format) func() error {

return func() error {
stopCh <- struct{}{}
return writeFormat(w, stackCounts.HumanMap(prof.SelfFrame()), format, hz)
endTime := time.Now()
return writeFormat(
w,
stackCounts.HumanMap(prof.SelfFrame()),
format,
hz,
startTime,
endTime,
)
}
}

Expand Down
9 changes: 6 additions & 3 deletions format.go
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"sort"
"strings"
"time"

"github.com/google/pprof/profile"
)
Expand All @@ -21,12 +22,12 @@ const (
FormatPprof Format = "pprof"
)

func writeFormat(w io.Writer, s map[string]int, f Format, hz int) error {
func writeFormat(w io.Writer, s map[string]int, f Format, hz int, startTime, endTime time.Time) error {
switch f {
case FormatFolded:
return writeFolded(w, s)
case FormatPprof:
return toPprof(s, hz).Write(w)
return toPprof(s, hz, startTime, endTime).Write(w)
default:
return fmt.Errorf("unknown format: %q", f)
}
Expand All @@ -42,14 +43,16 @@ func writeFolded(w io.Writer, s map[string]int) error {
return nil
}

func toPprof(s map[string]int, hz int) *profile.Profile {
func toPprof(s map[string]int, hz int, startTime, endTime time.Time) *profile.Profile {
functionID := uint64(1)
locationID := uint64(1)
line := int64(1)

p := &profile.Profile{}
m := &profile.Mapping{ID: 1, HasFunctions: true}
p.Period = int64(1e9 / hz) // Number of nanoseconds between samples.
p.TimeNanos = startTime.UnixNano()
p.DurationNanos = int64(endTime.Sub(startTime))
p.Mapping = []*profile.Mapping{m}
p.SampleType = []*profile.ValueType{
{
Expand Down
11 changes: 10 additions & 1 deletion format_test.go
Expand Up @@ -3,6 +3,7 @@ package fgprof
import (
"strings"
"testing"
"time"
)

func Test_toPprof(t *testing.T) {
Expand All @@ -11,14 +12,22 @@ func Test_toPprof(t *testing.T) {
"foo": 1,
}

p := toPprof(s, 99)
before := time.Local
defer func() { time.Local = before }()
time.Local = time.UTC

start := time.Date(2022, 8, 27, 14, 32, 23, 0, time.UTC)
end := start.Add(time.Second)
p := toPprof(s, 99, start, end)
if err := p.CheckValid(); err != nil {
t.Fatal(err)
}

want := strings.TrimSpace(`
PeriodType: wallclock nanoseconds
Period: 10101010
Time: 2022-08-27 14:32:23 +0000 UTC
Duration: 1s
Samples:
samples/count time/nanoseconds
1 10101010: 1
Expand Down

0 comments on commit 3cad799

Please sign in to comment.