TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

On the Algebraic Properties of Flame Graphs

129 pointsby p403n1x87over 2 years ago

6 comments

defrostover 2 years ago
Oddly enough I&#x27;ve generated similar graphs for stack tracing and profiling in the far far distant past and had not realised they&#x27;d been named and formalised.<p>For anyone else who has not recognised the name, I found these origin links which may interest some:<p><pre><code> Abstract [2]: Flame graphs are a simple stack trace visualization that helps answer an everyday problem: how is software consuming resources, especially CPUs, and how did this change since the last software version? Flame graphs have been adopted by many languages, products, and companies, including Netflix, and have become a standard tool for performance analysis. They were published in &quot;The Flame Graph&quot; article in the June 2016 issue of Communications of the ACM, by their creator, Brendan Gregg. </code></pre> [1] <a href="https:&#x2F;&#x2F;www.brendangregg.com&#x2F;flamegraphs.html" rel="nofollow">https:&#x2F;&#x2F;www.brendangregg.com&#x2F;flamegraphs.html</a><p>[2] <a href="https:&#x2F;&#x2F;www.usenix.org&#x2F;conference&#x2F;atc17&#x2F;program&#x2F;presentation&#x2F;gregg-flame" rel="nofollow">https:&#x2F;&#x2F;www.usenix.org&#x2F;conference&#x2F;atc17&#x2F;program&#x2F;presentation...</a><p>(hour long usenix talk of [2]) <a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=D53T1Ejig1Q">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=D53T1Ejig1Q</a><p>This paper appears to be formalising the nature of a flame graph, recognising that they rest on data from <i>sampling profilers</i> and as such suffer a &quot;never the same twice&quot; variation when repeatedly run, and thus seeking to quantify &quot;distance&quot; of one graph from another as well as &quot;average&quot; of multiple graphs (for the &quot;one true mean reference graph&quot; I guess).<p>The motivation is then to be able to <i>reliably</i> measure &quot;distance&quot; from one group of profiling runs to another, before and after changes of interest.<p>I dare say much more is possible, but I fear I&#x27;ve barely skimmed the material before bedtime :&#x2F;
BlackFlyover 2 years ago
I don&#x27;t think this algebra is a full description of flame graphs but it feels like it captures part of what you want for the limited purpose of global performance analysis.<p>I feel like a flame graph cannot be an element of a vector space since vectors are commutative and the stacks of a flame graph are ordered. From a performance perspective, ignoring the ordering can simplify the algebra (apparently by turning it into a vector space) and will still correspond with your overall impression of &quot;time spent in a frame&quot;.<p>Specifically,<p><pre><code> |A|B |A| |C|C |C| </code></pre> is (1, C;A), (2, C;B), (1, A;C) but as (1, C;A) + (2, C;B) + (1, A;C) with vector addition we can rearrange this to (2, C;A) + (2, C;B)<p>or<p><pre><code> |A |B | |C |C | </code></pre> which of course still captures the time spent in C;A and C;B, but it has lost some information. We think of it as a different flame graph. Of course, ignoring that information can be meaningful to a performance analysis.<p>Indeed the ordering can only be important to application semantics. This is clearly accentuated by the norm, which is even destroying the information of the basis elements.
评论 #34516625 未加载
评论 #34518141 未加载
评论 #34519272 未加载
nirinorover 2 years ago
Very nice formalization.<p>One area for refinement: it considers two stacks either identical or unrelated. Consider that stack A;B is actually very close to A;B;C, the difference might be due to a sample time occurring just before or just after the call to C. OP considers them just as different as A;B and Z;W, therefore amplifying a measurement noise.<p>This suggests using a refined metric between stacks (e.g., an edit distance counting pushes and pops), and then we can use it in defining the metric between flamegraphs (e.g., an optimal transport metric [1], instead of the proposed L1).<p>Avoiding that noise amplification reduces the background noise level, therefore the cost of effective measurements. From another perspective, the current OP scheme creates an avoidable curse of dimensionality in the form of the Hotelling test&#x27;s requirement that each sample has more measurements have more samples than distinct stack frames. So the same code split into more functions is harder to measure, and too-small samples are useless. I think neither of those is necessary if we take stack similarity into account.<p>[1] <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Wasserstein_metric" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Wasserstein_metric</a>
m1elover 2 years ago
As a developer who doesn&#x27;t use mathematical notation very often, I&#x27;ve had some difficulty reading it. From my understanding, the paper goes as follows:<p>2.1 Define FlameGraph<p><pre><code> Frame = something that identifies function&#x2F;location in the code Stack = Vec&lt;Frame&gt; FlameGraph = Map&lt;Stack, Real&gt; FlameGraphPositive = Map&lt;Stack, RealPositive&gt; </code></pre> 2.2 Define FlameChart<p><pre><code> FlameChart = Vec&lt;{ start: Real, flame_graph: FlameGraphPositive }&gt; # such that the start values are strictly ordered fn to_flamegraph(flame_chart: FlameChart) -&gt; FlameGraphPositive { flame_chart .map(|{ start, flame_graph }| flame_graph) .sum() } </code></pre> Personally, I think a better definition of FlameChart is:<p><pre><code> FlameChart = Vec&lt;{ end_time: RealPositive, stack: Stack }&gt; # such that sampling starts at 0 and Vec is strictly ordered by end_time fn to_flamegraph(flame_chart: FlameChart) -&gt; FlameGraphPositive { let mut start = 0.0; flame_chart.map(|{ end_time, stack }| { let elapsed = end_time - start; start = end_time; FlameGraphPositive::from_stack(stack, elapsed) }).sum() } </code></pre> 3.1 Define diff<p><pre><code> # a,b: FlameGraphPositive fn diff(a, b) -&gt; FlameGraph; # such that a + diff = b # diff: FlameGraph # add, sub: FlameGraphPositive fn to_positive(diff) -&gt; { add, sub }; # such that diff = add - sub </code></pre> 3.2 Define a naive diff metric<p><pre><code> # a,b: FlameGraphPositive fn diff_metric(a, b) -&gt; RealPositive { diff(a, b).size() &#x2F; (a.size() + b.size()) } # diff_metric(a, b) \in [0, 1]^Real </code></pre> 3.3 Define a more sophisticated diff metric<p>Using Hotelling T^2 Test, the author defines a metric, which takes sampling variance into account, and allows to detect performance regression, even when the sampling profile is noisy. (you&#x27;d have to read the paper for the exact method)<p>The code for this test is here: <a href="https:&#x2F;&#x2F;github.com&#x2F;P403n1x87&#x2F;flamegraph-experiment&#x2F;blob&#x2F;04db2aa&#x2F;flamegraph.py#L65-L89">https:&#x2F;&#x2F;github.com&#x2F;P403n1x87&#x2F;flamegraph-experiment&#x2F;blob&#x2F;04db...</a> <a href="https:&#x2F;&#x2F;github.com&#x2F;P403n1x87&#x2F;flamegraph-experiment&#x2F;blob&#x2F;04db2aa&#x2F;stats.py#L7">https:&#x2F;&#x2F;github.com&#x2F;P403n1x87&#x2F;flamegraph-experiment&#x2F;blob&#x2F;04db...</a>
Verviousover 2 years ago
I&#x27;m confused, what are the takeaways, and why are there 83 upvotes with no discussion?
评论 #34519002 未加载
评论 #34517476 未加载
KyleBerezinover 2 years ago
A link to a paper on the usefulness of a certain type of graph... Never change HN