Skip to content

Commit

Permalink
make mprof map generic
Browse files Browse the repository at this point in the history
  • Loading branch information
korniltsev committed May 24, 2024
1 parent c2caa4e commit 28e67be
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 41 deletions.
4 changes: 2 additions & 2 deletions godeltaprof/go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/grafana/pyroscope-go/godeltaprof

go 1.16
go 1.18

require github.com/klauspost/compress v1.17.3
require github.com/klauspost/compress v1.17.8
2 changes: 2 additions & 0 deletions godeltaprof/go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA=
github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
38 changes: 24 additions & 14 deletions godeltaprof/internal/pprof/delta_heap.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,20 @@ import (
"strings"
)

type heapPrevValue struct {
allocObjects int64
allocBytes int64
}

type heapAccValue struct {
allocObjects int64
allocBytes int64
inuseObjects int64
inuseBytes int64
}

type DeltaHeapProfiler struct {
m profMap
m profMap[heapPrevValue, heapAccValue]

Check failure on line 22 in godeltaprof/internal/pprof/delta_heap.go

View workflow job for this annotation

GitHub Actions / go (1.16)

syntax error: unexpected [, expecting semicolon or newline or }

Check failure on line 22 in godeltaprof/internal/pprof/delta_heap.go

View workflow job for this annotation

GitHub Actions / go (1.17)

syntax error: unexpected [, expecting semicolon or newline or }
//todo consider adding an option to remove block size label and merge allocations of different size
}

Expand All @@ -25,10 +37,10 @@ func (d *DeltaHeapProfiler) WriteHeapProto(b ProfileBuilder, p []runtime.MemProf
blockSize = r.AllocBytes / r.AllocObjects
}
entry := d.m.Lookup(r.Stack(), uintptr(blockSize))
entry.acc.v1 += r.AllocObjects
entry.acc.v2 += r.AllocBytes
entry.acc2.v1 += r.InUseObjects()
entry.acc2.v2 += r.InUseBytes()
entry.acc.allocObjects += r.AllocObjects
entry.acc.allocBytes += r.AllocBytes
entry.acc.inuseObjects += r.InUseObjects()
entry.acc.inuseBytes += r.InUseBytes()
}
for _, r := range p {
// do the delta
Expand All @@ -41,25 +53,23 @@ func (d *DeltaHeapProfiler) WriteHeapProto(b ProfileBuilder, p []runtime.MemProf
blockSize = r.AllocBytes / r.AllocObjects
}
entry := d.m.Lookup(r.Stack(), uintptr(blockSize))

if entry.acc.v1 == 0 && entry.acc.v2 == 0 && entry.acc2.v1 == 0 && entry.acc2.v2 == 0 {
if entry.acc == (heapAccValue{}) {
continue
}

//todo minimize the number of fields - use tag and only keep object count, we can always multiply by block size (tag) to get the bytes
AllocObjects := entry.acc.v1 - entry.prev.v1
AllocObjects := entry.acc.allocObjects - entry.prev.allocObjects
if AllocObjects < 0 {
continue
}
AllocBytes := entry.acc.v2 - entry.prev.v2
entry.prev.v1 = entry.acc.v1
entry.prev.v2 = entry.acc.v2
AllocBytes := entry.acc.allocBytes - entry.prev.allocBytes
entry.prev.allocObjects = entry.acc.allocObjects
entry.prev.allocBytes = entry.acc.allocBytes

values[0], values[1] = ScaleHeapSample(AllocObjects, AllocBytes, rate)
values[2], values[3] = ScaleHeapSample(entry.acc2.v1, entry.acc2.v2, rate)
values[2], values[3] = ScaleHeapSample(entry.acc.inuseObjects, entry.acc.inuseBytes, rate)

entry.acc = count{}
entry.acc2 = count{}
entry.acc = heapAccValue{}

if values[0] == 0 && values[1] == 0 && values[2] == 0 && values[3] == 0 {
continue
Expand Down
30 changes: 20 additions & 10 deletions godeltaprof/internal/pprof/delta_mutex.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,18 @@ import (
"runtime"
)

type mutexPrevValue struct {
count int64
inanosec int64
}

type mutexAccValue struct {
count int64
cycles int64
}

type DeltaMutexProfiler struct {
m profMap
m profMap[mutexPrevValue, mutexAccValue]

Check failure on line 18 in godeltaprof/internal/pprof/delta_mutex.go

View workflow job for this annotation

GitHub Actions / go (1.17)

syntax error: unexpected [, expecting semicolon or newline or }
}

// PrintCountCycleProfile outputs block profile records (for block or mutex profiles)
Expand All @@ -21,25 +31,25 @@ func (d *DeltaMutexProfiler) PrintCountCycleProfile(b ProfileBuilder, scaler Mut
var locs []uint64
for _, r := range records {
entry := d.m.Lookup(r.Stack(), 0)
entry.acc.v1 += r.Count // accumulate unscaled
entry.acc.v2 += r.Cycles
entry.acc.count += r.Count // accumulate unscaled
entry.acc.cycles += r.Cycles
}
for _, r := range records {
entry := d.m.Lookup(r.Stack(), 0)
accCount := entry.acc.v1
accCycles := entry.acc.v2
accCount := entry.acc.count
accCycles := entry.acc.cycles
if accCount == 0 && accCycles == 0 { //todo check if this is correct
continue
}
entry.acc = count{}
entry.acc = mutexAccValue{}
count, nanosec := ScaleMutexProfile(scaler, accCount, float64(accCycles)/cpuGHz)
inanosec := int64(nanosec)

// do the delta
values[0] = count - entry.prev.v1
values[1] = inanosec - entry.prev.v2
entry.prev.v1 = count
entry.prev.v2 = inanosec
values[0] = count - entry.prev.count
values[1] = inanosec - entry.prev.inanosec
entry.prev.count = count
entry.prev.inanosec = inanosec

if values[0] < 0 || values[1] < 0 {
continue
Expand Down
31 changes: 16 additions & 15 deletions godeltaprof/internal/pprof/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import "unsafe"

// A profMap is a map from (stack, tag) to mapEntry.
// It grows without bound, but that's assumed to be OK.
type profMap struct {
hash map[uintptr]*profMapEntry
all *profMapEntry
last *profMapEntry
free []profMapEntry
type profMap[PREV any, ACC any] struct {

Check failure on line 11 in godeltaprof/internal/pprof/map.go

View workflow job for this annotation

GitHub Actions / go (1.17)

syntax error: unexpected any, expecting ]
hash map[uintptr]*profMapEntry[PREV, ACC]
all *profMapEntry[PREV, ACC]
last *profMapEntry[PREV, ACC]
free []profMapEntry[PREV, ACC]
freeStk []uintptr
}

Expand All @@ -23,17 +23,18 @@ type count struct {
}

// A profMapEntry is a single entry in the profMap.
type profMapEntry struct {
nextHash *profMapEntry // next in hash list
nextAll *profMapEntry // next in list of all entries
// todo remove nextAll
// todo use unsafe.Pointer + len for stk ?
type profMapEntry[PREV any, ACC any] struct {

Check failure on line 28 in godeltaprof/internal/pprof/map.go

View workflow job for this annotation

GitHub Actions / go (1.17)

syntax error: unexpected any, expecting ]
nextHash *profMapEntry[PREV, ACC] // next in hash list
nextAll *profMapEntry[PREV, ACC] // next in list of all entries
stk []uintptr
tag uintptr
prev count
acc count
acc2 count //todo make it generic?? drop go16,go17 support?
prev PREV
acc ACC
}

func (m *profMap) Lookup(stk []uintptr, tag uintptr) *profMapEntry {
func (m *profMap[PREV, ACC]) Lookup(stk []uintptr, tag uintptr) *profMapEntry[PREV, ACC] {

Check failure on line 37 in godeltaprof/internal/pprof/map.go

View workflow job for this annotation

GitHub Actions / go (1.17)

syntax error: unexpected [, expecting comma or )
// Compute hash of (stk, tag).
h := uintptr(0)
for _, x := range stk {
Expand All @@ -44,7 +45,7 @@ func (m *profMap) Lookup(stk []uintptr, tag uintptr) *profMapEntry {
h += uintptr(tag) * 41

// Find entry if present.
var last *profMapEntry
var last *profMapEntry[PREV, ACC]

Check failure on line 48 in godeltaprof/internal/pprof/map.go

View workflow job for this annotation

GitHub Actions / go (1.17)

syntax error: unexpected [ after top level declaration
Search:
for e := m.hash[h]; e != nil; last, e = e, e.nextHash {
if len(e.stk) != len(stk) || e.tag != tag {
Expand All @@ -66,7 +67,7 @@ Search:

// Add new entry.
if len(m.free) < 1 {
m.free = make([]profMapEntry, 128)
m.free = make([]profMapEntry[PREV, ACC], 128)
}
e := &m.free[0]
m.free = m.free[1:]
Expand All @@ -84,7 +85,7 @@ Search:
e.stk[j] = uintptr(stk[j])
}
if m.hash == nil {
m.hash = make(map[uintptr]*profMapEntry)
m.hash = make(map[uintptr]*profMapEntry[PREV, ACC])
}
m.hash[h] = e
if m.all == nil {
Expand Down

0 comments on commit 28e67be

Please sign in to comment.