Skip to content

Commit a3b527a

Browse files
authored
Merge pull request #639 from getsentry/txiao/fix/more-accurate-average-computation-for-flamegraph-metrics-2
fix(flamegraph): More accurate average computation for flamegraph met…
2 parents 0829ec7 + 36e9611 commit a3b527a

File tree

11 files changed

+382
-148
lines changed

11 files changed

+382
-148
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
- Add default non-root user in the Docker image. ([#593](https://github.com/getsentry/vroom/pull/593))
3636
- Classify macOS frames from an application as application frames. ([#604](https://github.com/getsentry/vroom/pull/604))
3737
- Return number of occurrences in flamegraph. ([#622](https://github.com/getsentry/vroom/pull/622), [#625](https://github.com/getsentry/vroom/pull/625))
38-
- Use function duration when computing metrics ([#627](https://github.com/getsentry/vroom/pull/627), [#628](https://github.com/getsentry/vroom/pull/628), [#629](https://github.com/getsentry/vroom/pull/629), [#630](https://github.com/getsentry/vroom/pull/630))
38+
- Use function duration when computing metrics ([#627](https://github.com/getsentry/vroom/pull/627), [#628](https://github.com/getsentry/vroom/pull/628), [#629](https://github.com/getsentry/vroom/pull/629), [#630](https://github.com/getsentry/vroom/pull/630), [#639](https://github.com/getsentry/vroom/pull/639))
3939
- Remove Unused metrics endpoint ([#633](https://github.com/getsentry/vroom/pull/633))
4040

4141
**Bug Fixes**:

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)