github.com/pyroscope-io/godeltaprof@v0.1.3-0.20230906152420-0d7eeca7b8c1/internal/pprof/delta_mutex.go (about) 1 package pprof 2 3 import ( 4 "io" 5 "runtime" 6 ) 7 8 type DeltaMutexProfiler struct { 9 m profMap 10 } 11 12 // PrintCountCycleProfile outputs block profile records (for block or mutex profiles) 13 // as the pprof-proto format output. Translations from cycle count to time duration 14 // are done because The proto expects count and time (nanoseconds) instead of count 15 // and the number of cycles for block, contention profiles. 16 // Possible 'scaler' functions are scaleBlockProfile and scaleMutexProfile. 17 func (d *DeltaMutexProfiler) PrintCountCycleProfile(w io.Writer, countName, cycleName string, scaler func(int64, float64) (int64, float64), records []runtime.BlockProfileRecord) error { 18 // Output profile in protobuf form. 19 b := newProfileBuilder(w) 20 b.pbValueType(tagProfile_PeriodType, countName, "count") 21 b.pb.int64Opt(tagProfile_Period, 1) 22 b.pbValueType(tagProfile_SampleType, countName, "count") 23 b.pbValueType(tagProfile_SampleType, cycleName, "nanoseconds") 24 25 cpuGHz := float64(runtime_cyclesPerSecond()) / 1e9 26 27 values := []int64{0, 0} 28 var locs []uint64 29 for _, r := range records { 30 count, nanosec := scaler(r.Count, float64(r.Cycles)/cpuGHz) 31 inanosec := int64(nanosec) 32 33 // do the delta 34 entry := d.m.Lookup(r.Stack(), 0) 35 values[0] = count - entry.count.v1 36 values[1] = inanosec - entry.count.v2 37 entry.count.v1 = count 38 entry.count.v2 = inanosec 39 40 // For count profiles, all stack addresses are 41 // return PCs, which is what appendLocsForStack expects. 42 locs = b.appendLocsForStack(locs[:0], r.Stack()) 43 b.pbSample(values, locs, nil) 44 } 45 b.build() 46 return nil 47 }