Skip to content

Commit

Permalink
Optimise max depth computation (PR #2984)
Browse files Browse the repository at this point in the history
  • Loading branch information
canova committed Oct 23, 2020
2 parents 24e3cde + 01b1dbd commit 0eae882
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 16 deletions.
4 changes: 2 additions & 2 deletions docs-developer/call-tree.md
Expand Up @@ -19,7 +19,7 @@ A call tree is a summary representation of sample and stack data. It adds togeth
E G
```

In this case the profiler took 3 samples, each 1 millisecond apart. Visualizing profile information in this form doesn't scale when you have thousands of samples, so it's best to summarize this information. The call tree does this by starting at the root of all the samples, and looks at the functions called. If the functions are the same, then they are combined into a single node. After evaluating the first depth of the stack, the second level is evaluated. If any of the samples do not the same function at the second depth, then the tree is split into multiple nodes, one for each function. This branching continues until all levels of the samples' stacks have been evaluated. Taking the above samples and the corresponding relationship between the stacks would produce the following tree. One special thing to note here is the function F has been called multiple times, but has different positions in the 2nd and 3rd callstacks.
In this case the profiler took 3 samples, each 1 millisecond apart. Visualizing profile information in this form doesn't scale when you have thousands of samples, so it's best to summarize this information. The call tree does this by starting at the root of all the samples, and looks at the functions called. If the functions are the same, then they are combined into a single node. After evaluating the first depth of the stack, the second level is evaluated. If any of the samples do not call the same function at the second depth, then the tree is split into multiple nodes, one for each function. This branching continues until all levels of the samples' stacks have been evaluated. Taking the above samples and the corresponding relationship between the stacks would produce the following tree. One special thing to note here is the function F has been called multiple times, but has different positions in the 2nd and 3rd callstacks.

```
A
Expand Down Expand Up @@ -159,7 +159,7 @@ This would be a surprising result, and many other assumptions would shake out th

What we really care about in the call tree is the execution time of a given function, and its relationship to other functions. Since there can be multiple frames and stacks per function in a call tree, the logical step is to combine all of these stacks and frames together in terms of what function they point to. This combined representation is known in the Firefox Profiler as CallNodes.

However once this happens, it starts to become quite difficult to explain relationships and refer to specific CallNodes within this modified view. Whenever we apply any type of data transformation, these CallNodes need to be regenerated, and the indexes into the CallNodesTable will be different. The only unique identifier that exists is the function, and where it exists in the call tree. So in order refer to a specific CallNode, we need a different way to store a reference to the tree. This structure in the Firefox Profiler is called the CallNodePath.
However once this happens, it starts to become quite difficult to explain relationships and refer to specific CallNodes within this modified view. Whenever we apply any type of data transformation, these CallNodes need to be regenerated, and the indexes into the CallNodesTable will be different. The only unique identifier that exists is the function, and where it exists in the call tree. So in order to refer to a specific CallNode, we need a different way to store a reference to the tree. This structure in the Firefox Profiler is called the CallNodePath.

```
A
Expand Down
21 changes: 7 additions & 14 deletions src/profile-logic/profile-data.js
Expand Up @@ -1763,21 +1763,14 @@ export function computeCallNodeMaxDepth(
thread: Thread,
callNodeInfo: CallNodeInfo
): number {
let maxDepth = 0;
const { samples } = thread;
const { callNodeTable, stackIndexToCallNodeIndex } = callNodeInfo;
for (let i = 0; i < samples.length; i++) {
const stackIndex = samples.stack[i];
if (stackIndex !== null) {
const callNodeIndex = stackIndexToCallNodeIndex[stackIndex];
// Change to one-based depth
const depth = callNodeTable.depth[callNodeIndex] + 1;
if (depth > maxDepth) {
maxDepth = depth;
}
}
if (
thread.samples.length === 0 ||
callNodeInfo.callNodeTable.depth.length === 0
) {
return 0;
}
return maxDepth;

return Math.max(...callNodeInfo.callNodeTable.depth) + 1;
}

export function invertCallstack(
Expand Down

0 comments on commit 0eae882

Please sign in to comment.