github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/runtime/pprof/protomem.go (about) 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. 4 5 package pprof 6 7 import ( 8 "internal/pprof/profile" 9 "math" 10 "runtime" 11 "time" 12 ) 13 14 // encodeMemProfile converts MemProfileRecords to a Profile. 15 func encodeMemProfile(mr []runtime.MemProfileRecord, rate int64, t time.Time) *profile.Profile { 16 p := &profile.Profile{ 17 Period: rate, 18 PeriodType: &profile.ValueType{Type: "space", Unit: "bytes"}, 19 SampleType: []*profile.ValueType{ 20 {Type: "alloc_objects", Unit: "count"}, 21 {Type: "alloc_space", Unit: "bytes"}, 22 {Type: "inuse_objects", Unit: "count"}, 23 {Type: "inuse_space", Unit: "bytes"}, 24 }, 25 TimeNanos: int64(t.UnixNano()), 26 } 27 28 locs := make(map[uintptr]*profile.Location) 29 for _, r := range mr { 30 stack := r.Stack() 31 sloc := make([]*profile.Location, len(stack)) 32 for i, addr := range stack { 33 loc := locs[addr] 34 if loc == nil { 35 loc = &profile.Location{ 36 ID: uint64(len(p.Location) + 1), 37 Address: uint64(addr), 38 } 39 locs[addr] = loc 40 p.Location = append(p.Location, loc) 41 } 42 sloc[i] = loc 43 } 44 45 ao, ab := scaleHeapSample(r.AllocObjects, r.AllocBytes, rate) 46 uo, ub := scaleHeapSample(r.InUseObjects(), r.InUseBytes(), rate) 47 48 p.Sample = append(p.Sample, &profile.Sample{ 49 Value: []int64{ao, ab, uo, ub}, 50 Location: sloc, 51 }) 52 } 53 if runtime.GOOS == "linux" { 54 addMappings(p) 55 } 56 return p 57 } 58 59 // scaleHeapSample adjusts the data from a heap Sample to 60 // account for its probability of appearing in the collected 61 // data. heap profiles are a sampling of the memory allocations 62 // requests in a program. We estimate the unsampled value by dividing 63 // each collected sample by its probability of appearing in the 64 // profile. heap profiles rely on a poisson process to determine 65 // which samples to collect, based on the desired average collection 66 // rate R. The probability of a sample of size S to appear in that 67 // profile is 1-exp(-S/R). 68 func scaleHeapSample(count, size, rate int64) (int64, int64) { 69 if count == 0 || size == 0 { 70 return 0, 0 71 } 72 73 if rate <= 1 { 74 // if rate==1 all samples were collected so no adjustment is needed. 75 // if rate<1 treat as unknown and skip scaling. 76 return count, size 77 } 78 79 avgSize := float64(size) / float64(count) 80 scale := 1 / (1 - math.Exp(-avgSize/float64(rate))) 81 82 return int64(float64(count) * scale), int64(float64(size) * scale) 83 }