compiler: rationalize external symbol names
[official-gcc.git] / libgo / go / runtime / pprof / protomem.go
blob2756cfd28d83172bcb3fbdbe220b00b0e4bc4946
1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package pprof
7 import (
8 "io"
9 "math"
10 "runtime"
11 "strings"
14 // writeHeapProto writes the current heap profile in protobuf format to w.
15 func writeHeapProto(w io.Writer, p []runtime.MemProfileRecord, rate int64) error {
16 b := newProfileBuilder(w)
17 b.pbValueType(tagProfile_PeriodType, "space", "bytes")
18 b.pb.int64Opt(tagProfile_Period, rate)
19 b.pbValueType(tagProfile_SampleType, "alloc_objects", "count")
20 b.pbValueType(tagProfile_SampleType, "alloc_space", "bytes")
21 b.pbValueType(tagProfile_SampleType, "inuse_objects", "count")
22 b.pbValueType(tagProfile_SampleType, "inuse_space", "bytes")
24 values := []int64{0, 0, 0, 0}
25 var locs []uint64
26 for _, r := range p {
27 locs = locs[:0]
28 hideRuntime := true
29 for tries := 0; tries < 2; tries++ {
30 for _, addr := range r.Stack() {
31 // For heap profiles, all stack
32 // addresses are return PCs, which is
33 // what locForPC expects.
34 if hideRuntime {
35 if f := runtime.FuncForPC(addr); f != nil && strings.HasPrefix(f.Name(), "runtime.") {
36 continue
38 // Found non-runtime. Show any runtime uses above it.
39 hideRuntime = false
41 l := b.locForPC(addr)
42 if l == 0 { // runtime.goexit
43 continue
45 locs = append(locs, l)
47 if len(locs) > 0 {
48 break
50 hideRuntime = false // try again, and show all frames
53 values[0], values[1] = scaleHeapSample(r.AllocObjects, r.AllocBytes, rate)
54 values[2], values[3] = scaleHeapSample(r.InUseObjects(), r.InUseBytes(), rate)
55 var blockSize int64
56 if values[0] > 0 {
57 blockSize = values[1] / values[0]
59 b.pbSample(values, locs, func() {
60 if blockSize != 0 {
61 b.pbLabel(tagSample_Label, "bytes", "", blockSize)
65 b.build()
66 return nil
69 // scaleHeapSample adjusts the data from a heap Sample to
70 // account for its probability of appearing in the collected
71 // data. heap profiles are a sampling of the memory allocations
72 // requests in a program. We estimate the unsampled value by dividing
73 // each collected sample by its probability of appearing in the
74 // profile. heap profiles rely on a poisson process to determine
75 // which samples to collect, based on the desired average collection
76 // rate R. The probability of a sample of size S to appear in that
77 // profile is 1-exp(-S/R).
78 func scaleHeapSample(count, size, rate int64) (int64, int64) {
79 if count == 0 || size == 0 {
80 return 0, 0
83 if rate <= 1 {
84 // if rate==1 all samples were collected so no adjustment is needed.
85 // if rate<1 treat as unknown and skip scaling.
86 return count, size
89 avgSize := float64(size) / float64(count)
90 scale := 1 / (1 - math.Exp(-avgSize/float64(rate)))
92 return int64(float64(count) * scale), int64(float64(size) * scale)