Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 26 additions & 22 deletions src/profile-logic/call-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ type CallNodeSummary = {
leaf: Float32Array,
total: Float32Array,
};
export type CallTreeCountsAndSummary = {
callNodeChildCount: Uint32Array,
export type CallTreeTimings = {
callNodeHasChildren: Uint8Array,
callNodeSummary: CallNodeSummary,
rootCount: number,
rootTotalSummary: number,
Expand Down Expand Up @@ -74,7 +74,7 @@ export class CallTree {
_callNodeInfo: CallNodeInfo;
_callNodeTable: CallNodeTable;
_callNodeSummary: CallNodeSummary;
_callNodeChildCount: Uint32Array; // A table column matching the callNodeTable
_callNodeHasChildren: Uint8Array; // A table column matching the callNodeTable
_thread: Thread;
_rootTotalSummary: number;
_rootCount: number;
Expand All @@ -90,7 +90,7 @@ export class CallTree {
categories: CategoryList,
callNodeInfo: CallNodeInfo,
callNodeSummary: CallNodeSummary,
callNodeChildCount: Uint32Array,
callNodeHasChildren: Uint8Array,
rootTotalSummary: number,
rootCount: number,
isHighPrecision: boolean,
Expand All @@ -100,7 +100,7 @@ export class CallTree {
this._callNodeInfo = callNodeInfo;
this._callNodeTable = callNodeInfo.callNodeTable;
this._callNodeSummary = callNodeSummary;
this._callNodeChildCount = callNodeChildCount;
this._callNodeHasChildren = callNodeHasChildren;
this._thread = thread;
this._rootTotalSummary = rootTotalSummary;
this._rootCount = rootCount;
Expand Down Expand Up @@ -139,9 +139,9 @@ export class CallTree {
) {
const childTotalSummary =
this._callNodeSummary.total[childCallNodeIndex];
const childChildCount = this._callNodeChildCount[childCallNodeIndex];
const childHasChildren = this._callNodeHasChildren[childCallNodeIndex];

if (childTotalSummary !== 0 || childChildCount !== 0) {
if (childTotalSummary !== 0 || childHasChildren !== 0) {
children.push(childCallNodeIndex);
}
}
Expand All @@ -156,7 +156,7 @@ export class CallTree {
}

hasChildren(callNodeIndex: IndexIntoCallNodeTable): boolean {
return this.getChildren(callNodeIndex).length !== 0;
return this._callNodeHasChildren[callNodeIndex] !== 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could have used the previous childCount too, but I'm not opposed to changing childCount to hasChildren

}

_addDescendantsToSet(
Expand Down Expand Up @@ -512,20 +512,20 @@ function _getStackSelf(
* what type of weight is in the SamplesLikeTable. For instance, it could be
* milliseconds, sample counts, or bytes.
*/
export function computeCallTreeCountsAndSummary(
export function computeCallTreeTimings(
samples: SamplesLikeTable,
sampleIndexToCallNodeIndex: Array<IndexIntoCallNodeTable | null>,
{ callNodeTable }: CallNodeInfo,
invertCallstack: boolean
): CallTreeCountsAndSummary {
): CallTreeTimings {
// Inverted trees need a different method for computing the timing.
const { callNodeSelf, callNodeLeaf } = invertCallstack
? _getInvertedStackSelf(samples, callNodeTable, sampleIndexToCallNodeIndex)
: _getStackSelf(samples, callNodeTable, sampleIndexToCallNodeIndex);

// Compute the following variables:
const callNodeTotalSummary = new Float32Array(callNodeTable.length);
const callNodeChildCount = new Uint32Array(callNodeTable.length);
const callNodeHasChildren = new Uint8Array(callNodeTable.length);
let rootTotalSummary = 0;
let rootCount = 0;

Expand All @@ -542,7 +542,7 @@ export function computeCallTreeCountsAndSummary(
) {
callNodeTotalSummary[callNodeIndex] += callNodeLeaf[callNodeIndex];
rootTotalSummary += abs(callNodeLeaf[callNodeIndex]);
const hasChildren = callNodeChildCount[callNodeIndex] !== 0;
const hasChildren = callNodeHasChildren[callNodeIndex] !== 0;
const hasTotalValue = callNodeTotalSummary[callNodeIndex] !== 0;

if (!hasChildren && !hasTotalValue) {
Expand All @@ -555,7 +555,7 @@ export function computeCallTreeCountsAndSummary(
} else {
callNodeTotalSummary[prefixCallNode] +=
callNodeTotalSummary[callNodeIndex];
callNodeChildCount[prefixCallNode]++;
callNodeHasChildren[prefixCallNode] = 1;
}
}

Expand All @@ -565,7 +565,7 @@ export function computeCallTreeCountsAndSummary(
leaf: callNodeLeaf,
total: callNodeTotalSummary,
},
callNodeChildCount,
callNodeHasChildren,
rootTotalSummary,
rootCount,
};
Expand All @@ -578,19 +578,23 @@ export function getCallTree(
thread: Thread,
callNodeInfo: CallNodeInfo,
categories: CategoryList,
callTreeCountsAndSummary: CallTreeCountsAndSummary,
callTreeTimings: CallTreeTimings,
weightType: WeightType
): CallTree {
return timeCode('getCallTree', () => {
const { callNodeSummary, callNodeChildCount, rootTotalSummary, rootCount } =
callTreeCountsAndSummary;
const {
callNodeSummary,
callNodeHasChildren,
rootTotalSummary,
rootCount,
} = callTreeTimings;

return new CallTree(
thread,
categories,
callNodeInfo,
callNodeSummary,
callNodeChildCount,
callNodeHasChildren,
rootTotalSummary,
rootCount,
Boolean(thread.isJsTracer),
Expand Down Expand Up @@ -670,7 +674,7 @@ export function extractSamplesLikeTable(
}

/**
* This function is extremely similar to computeCallTreeCountsAndSummary,
* This function is extremely similar to computeCallTreeTimings,
* but is specialized for converting sample counts into traced timing. Samples
* don't have duration information associated with them, it's mostly how long they
* were observed to be running. This function computes the timing the exact same
Expand Down Expand Up @@ -730,7 +734,7 @@ export function computeTracedTiming(

// Compute the following variables:
const callNodeTotalSummary = new Float32Array(callNodeTable.length);
const callNodeChildCount = new Uint32Array(callNodeTable.length);
const callNodeHasChildren = new Uint8Array(callNodeTable.length);

// We loop the call node table in reverse, so that we find the children
// before their parents, and the total time is known at the time we reach a
Expand All @@ -741,7 +745,7 @@ export function computeTracedTiming(
callNodeIndex--
) {
callNodeTotalSummary[callNodeIndex] += callNodeLeaf[callNodeIndex];
const hasChildren = callNodeChildCount[callNodeIndex] !== 0;
const hasChildren = callNodeHasChildren[callNodeIndex] !== 0;
const hasTotalValue = callNodeTotalSummary[callNodeIndex] !== 0;

if (!hasChildren && !hasTotalValue) {
Expand All @@ -752,7 +756,7 @@ export function computeTracedTiming(
if (prefixCallNode !== -1) {
callNodeTotalSummary[prefixCallNode] +=
callNodeTotalSummary[callNodeIndex];
callNodeChildCount[prefixCallNode]++;
callNodeHasChildren[prefixCallNode] = 1;
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/profile-logic/flame-graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
IndexIntoCallNodeTable,
} from 'firefox-profiler/types';
import type { UniqueStringArray } from 'firefox-profiler/utils/unique-string-array';
import type { CallTreeCountsAndSummary } from './call-tree';
import type { CallTreeTimings } from './call-tree';

import { bisectionRightByStrKey } from 'firefox-profiler/utils/bisect';

Expand Down Expand Up @@ -229,9 +229,9 @@ export function computeFlameGraphRows(
export function getFlameGraphTiming(
flameGraphRows: FlameGraphRows,
callNodeTable: CallNodeTable,
callTreeCountsAndSummary: CallTreeCountsAndSummary
callTreeTimings: CallTreeTimings
): FlameGraphTiming {
const { callNodeSummary, rootTotalSummary } = callTreeCountsAndSummary;
const { callNodeSummary, rootTotalSummary } = callTreeTimings;
const { total, self } = callNodeSummary;
const { prefix } = callNodeTable;

Expand Down
41 changes: 20 additions & 21 deletions src/selectors/per-thread/stack-sample.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,32 +296,31 @@ export function getStackAndSampleSelectorsPerThread(
(samples) => samples.weightType || 'samples'
);

const getCallTreeCountsAndSummary: Selector<CallTree.CallTreeCountsAndSummary> =
createSelector(
threadSelectors.getPreviewFilteredSamplesForCallTree,
getCallNodeInfo,
ProfileSelectors.getProfileInterval,
UrlState.getInvertCallstack,
(samples, callNodeInfo, interval, invertCallStack) => {
const sampleIndexToCallNodeIndex =
ProfileData.getSampleIndexToCallNodeIndex(
samples.stack,
callNodeInfo.stackIndexToCallNodeIndex
);
return CallTree.computeCallTreeCountsAndSummary(
samples,
sampleIndexToCallNodeIndex,
callNodeInfo,
invertCallStack
const getCallTreeTimings: Selector<CallTree.CallTreeTimings> = createSelector(
threadSelectors.getPreviewFilteredSamplesForCallTree,
getCallNodeInfo,
ProfileSelectors.getProfileInterval,
UrlState.getInvertCallstack,
(samples, callNodeInfo, interval, invertCallStack) => {
const sampleIndexToCallNodeIndex =
ProfileData.getSampleIndexToCallNodeIndex(
samples.stack,
callNodeInfo.stackIndexToCallNodeIndex
);
}
);
return CallTree.computeCallTreeTimings(
samples,
sampleIndexToCallNodeIndex,
callNodeInfo,
invertCallStack
);
}
);

const getCallTree: Selector<CallTree.CallTree> = createSelector(
threadSelectors.getPreviewFilteredThread,
getCallNodeInfo,
ProfileSelectors.getCategories,
getCallTreeCountsAndSummary,
getCallTreeTimings,
getWeightTypeForCallTree,
CallTree.getCallTree
);
Expand Down Expand Up @@ -368,7 +367,7 @@ export function getStackAndSampleSelectorsPerThread(
createSelector(
getFlameGraphRows,
(state) => getCallNodeInfo(state).callNodeTable,
getCallTreeCountsAndSummary,
getCallTreeTimings,
FlameGraph.getFlameGraphTiming
);

Expand Down
6 changes: 3 additions & 3 deletions src/test/fixtures/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// @flow
import {
getCallTree,
computeCallTreeCountsAndSummary,
computeCallTreeTimings,
type CallTree,
} from 'firefox-profiler/profile-logic/call-tree';
import { getEmptyThread } from 'firefox-profiler/profile-logic/data-structures';
Expand Down Expand Up @@ -127,7 +127,7 @@ export function callTreeFromProfile(
thread.funcTable,
defaultCategory
);
const callTreeCountsAndSummary = computeCallTreeCountsAndSummary(
const callTreeTimings = computeCallTreeTimings(
thread.samples,
getSampleIndexToCallNodeIndex(
thread.samples.stack,
Expand All @@ -140,7 +140,7 @@ export function callTreeFromProfile(
thread,
callNodeInfo,
categories,
callTreeCountsAndSummary,
callTreeTimings,
'samples'
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/store/__snapshots__/profile-view.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2292,7 +2292,7 @@ Object {

exports[`snapshots of selectors/profile matches the last stored run of selectedThreadSelector.getCallTree 1`] = `
CallTree {
"_callNodeChildCount": Uint32Array [
"_callNodeHasChildren": Uint8Array [
1,
1,
0,
Expand Down
18 changes: 9 additions & 9 deletions src/test/unit/profile-tree.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '../fixtures/profiles/processed-profile';
import {
getCallTree,
computeCallTreeCountsAndSummary,
computeCallTreeTimings,
} from '../../profile-logic/call-tree';
import { computeFlameGraphRows } from '../../profile-logic/flame-graph';
import {
Expand Down Expand Up @@ -71,7 +71,7 @@ describe('unfiltered call tree', function () {

it('yields expected results', function () {
expect(
computeCallTreeCountsAndSummary(
computeCallTreeTimings(
thread.samples,
getSampleIndexToCallNodeIndex(
thread.samples.stack,
Expand All @@ -83,7 +83,7 @@ describe('unfiltered call tree', function () {
).toEqual({
rootCount: 1,
rootTotalSummary: 3,
callNodeChildCount: new Uint32Array([1, 2, 2, 1, 0, 1, 0, 1, 0]),
callNodeHasChildren: new Uint8Array([1, 1, 1, 1, 0, 1, 0, 1, 0]),
callNodeSummary: {
self: new Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 1]),
leaf: new Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 1]),
Expand Down Expand Up @@ -436,7 +436,7 @@ describe('inverted call tree', function () {
thread.funcTable,
defaultCategory
);
const callTreeCountsAndSummary = computeCallTreeCountsAndSummary(
const callTreeTimings = computeCallTreeTimings(
thread.samples,
getSampleIndexToCallNodeIndex(
thread.samples.stack,
Expand All @@ -449,7 +449,7 @@ describe('inverted call tree', function () {
thread,
callNodeInfo,
categories,
callTreeCountsAndSummary,
callTreeTimings,
'samples'
);

Expand Down Expand Up @@ -477,7 +477,7 @@ describe('inverted call tree', function () {
invertedThread.funcTable,
defaultCategory
);
const invertedCallTreeCountsAndSummary = computeCallTreeCountsAndSummary(
const invertedCallTreeTimings = computeCallTreeTimings(
invertedThread.samples,
getSampleIndexToCallNodeIndex(
invertedThread.samples.stack,
Expand All @@ -490,7 +490,7 @@ describe('inverted call tree', function () {
invertedThread,
invertedCallNodeInfo,
categories,
invertedCallTreeCountsAndSummary,
invertedCallTreeTimings,
'samples'
);

Expand Down Expand Up @@ -627,7 +627,7 @@ describe('diffing trees', function () {
thread.funcTable,
defaultCategory
);
const callTreeCountsAndSummary = computeCallTreeCountsAndSummary(
const callTreeTimings = computeCallTreeTimings(
thread.samples,
getSampleIndexToCallNodeIndex(
thread.samples.stack,
Expand All @@ -636,7 +636,7 @@ describe('diffing trees', function () {
callNodeInfo,
false
);
expect(callTreeCountsAndSummary.rootTotalSummary).toBe(12);
expect(callTreeTimings.rootTotalSummary).toBe(12);
});
});

Expand Down