Skip to content

Commit 646a790

Browse files
committed
fix(flamegraph): More accurate average computation for flamegraph metrics
Take 2 of #635. This aims to consolidate all the metrics into the frame into list and deprecates the metrics list.
1 parent 0829ec7 commit 646a790

File tree

10 files changed

+381
-147
lines changed

10 files changed

+381
-147
lines changed

internal/chunk/sample_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func TestCallTrees(t *testing.T) {
4040
"1": {
4141
{
4242
DurationNS: 40_000_000,
43+
DurationsNS: []uint64{40_000_000},
4344
EndNS: 50_000_000,
4445
Fingerprint: 15444731332182868858,
4546
IsApplication: true,
@@ -52,6 +53,7 @@ func TestCallTrees(t *testing.T) {
5253
Children: []*nodetree.Node{
5354
{
5455
DurationNS: 40_000_000,
56+
DurationsNS: []uint64{40_000_000},
5557
EndNS: 50_000_000,
5658
StartNS: 10_000_000,
5759
Fingerprint: 14164357600995800812,
@@ -64,6 +66,7 @@ func TestCallTrees(t *testing.T) {
6466
Children: []*nodetree.Node{
6567
{
6668
DurationNS: 10_000_000,
69+
DurationsNS: []uint64{10_000_000},
6770
EndNS: 50_000_000,
6871
Fingerprint: 9531802423075301657,
6972
IsApplication: true,
@@ -104,6 +107,7 @@ func TestCallTrees(t *testing.T) {
104107
"1": {
105108
{
106109
DurationNS: 30_000_000,
110+
DurationsNS: []uint64{30_000_000},
107111
EndNS: 40_000_000,
108112
Fingerprint: 15444731332182868858,
109113
IsApplication: true,
@@ -116,6 +120,7 @@ func TestCallTrees(t *testing.T) {
116120
Children: []*nodetree.Node{
117121
{
118122
DurationNS: 30_000_000,
123+
DurationsNS: []uint64{30_000_000},
119124
EndNS: 40_000_000,
120125
Fingerprint: 14164357600995800812,
121126
IsApplication: true,
@@ -156,6 +161,7 @@ func TestCallTrees(t *testing.T) {
156161
"1": {
157162
{
158163
DurationNS: 10_000_000,
164+
DurationsNS: []uint64{10_000_000},
159165
EndNS: 20_000_000,
160166
Fingerprint: 15444731332182868858,
161167
IsApplication: true,
@@ -168,6 +174,7 @@ func TestCallTrees(t *testing.T) {
168174
},
169175
{
170176
DurationNS: 10_000_000,
177+
DurationsNS: []uint64{10_000_000},
171178
EndNS: 30_000_000,
172179
Fingerprint: 15444731332182868859,
173180
IsApplication: true,

internal/flamegraph/flamegraph.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ func addCallTreeToFlamegraph(flamegraphTree *[]*nodetree.Node, callTree []*nodet
6363
currentNode.Occurrence += node.Occurrence
6464
currentNode.SampleCount += node.SampleCount
6565
currentNode.DurationNS += node.DurationNS
66+
currentNode.SelfTimeNS += node.SelfTimeNS
67+
currentNode.DurationsNS = append(currentNode.DurationsNS, node.DurationsNS...)
6668
} else {
6769
currentNode = node.ShallowCopyWithoutChildren()
6870
*flamegraphTree = append(*flamegraphTree, currentNode)
@@ -186,6 +188,16 @@ func toSpeedscope(
186188
fd.visitCalltree(tree, &stack)
187189
}
188190

191+
for i, frameInfo := range fd.frameInfos {
192+
sort.Slice(frameInfo.DurationsNS, func(i, j int) bool {
193+
return frameInfo.DurationsNS[i] < frameInfo.DurationsNS[j]
194+
})
195+
frameInfo.P75Duration, _ = metrics.Quantile(frameInfo.DurationsNS, 0.75)
196+
frameInfo.P95Duration, _ = metrics.Quantile(frameInfo.DurationsNS, 0.95)
197+
frameInfo.P99Duration, _ = metrics.Quantile(frameInfo.DurationsNS, 0.99)
198+
fd.frameInfos[i] = frameInfo
199+
}
200+
189201
s.SetData("total_samples", fd.totalSamples)
190202
s.SetData("final_samples", fd.Len())
191203

@@ -228,6 +240,9 @@ func (f *flamegraph) visitCalltree(node *nodetree.Node, currentStack *[]int) {
228240
*currentStack = append(*currentStack, i)
229241
f.frameInfos[i].Count += node.Occurrence
230242
f.frameInfos[i].Weight += node.DurationNS
243+
f.frameInfos[i].SumDuration += node.DurationNS
244+
f.frameInfos[i].SumSelfTime += node.SelfTimeNS
245+
f.frameInfos[i].DurationsNS = append(f.frameInfos[i].DurationsNS, node.DurationsNS...)
231246
} else {
232247
frame := node.ToFrame()
233248
sfr := speedscope.Frame{
@@ -245,8 +260,11 @@ func (f *flamegraph) visitCalltree(node *nodetree.Node, currentStack *[]int) {
245260
*currentStack = append(*currentStack, len(f.frames))
246261
f.frames = append(f.frames, sfr)
247262
f.frameInfos = append(f.frameInfos, speedscope.FrameInfo{
248-
Count: node.Occurrence,
249-
Weight: node.DurationNS,
263+
Count: node.Occurrence,
264+
Weight: node.DurationNS,
265+
SumDuration: node.DurationNS,
266+
SumSelfTime: node.SelfTimeNS,
267+
DurationsNS: node.DurationsNS,
250268
})
251269
}
252270

0 commit comments

Comments
 (0)