Skip to content
Open
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
127 changes: 4 additions & 123 deletions src/components/calltree/CallTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { PureComponent } from 'react';
import memoize from 'memoize-immutable';
import explicitConnect from 'firefox-profiler/utils/connect';
import { TreeView } from 'firefox-profiler/components/shared/TreeView';
import { CallTreeEmptyReasons } from './CallTreeEmptyReasons';
import { Icon } from 'firefox-profiler/components/shared/Icon';
import {
getInvertCallstack,
getImplementationFilter,
Expand All @@ -30,7 +28,6 @@ import {
changeTableViewOptions,
updateBottomBoxContentsAndMaybeOpen,
} from 'firefox-profiler/actions/profile-view';
import { assertExhaustiveCheck } from 'firefox-profiler/utils/types';

import type {
State,
Expand All @@ -46,13 +43,10 @@ import type {
import type { CallTree as CallTreeType } from 'firefox-profiler/profile-logic/call-tree';
import type { CallNodeInfo } from 'firefox-profiler/profile-logic/call-node-info';

import type {
Column,
MaybeResizableColumn,
} from 'firefox-profiler/components/shared/TreeView';
import type { ConnectedProps } from 'firefox-profiler/utils/connect';

import './CallTree.css';
import { nameColumn, libColumn, treeColumnsForWeightType } from './columns';

type StateProps = {
readonly threadsKey: ThreadsKey;
Expand Down Expand Up @@ -86,124 +80,11 @@ type DispatchProps = {
type Props = ConnectedProps<{}, StateProps, DispatchProps>;

class CallTreeImpl extends PureComponent<Props> {
_mainColumn: Column<CallNodeDisplayData> = {
propName: 'name',
titleL10nId: '',
};
_appendageColumn: Column<CallNodeDisplayData> = {
propName: 'lib',
titleL10nId: '',
};
_treeView: TreeView<CallNodeDisplayData> | null = null;
_takeTreeViewRef = (treeView: TreeView<CallNodeDisplayData> | null) => {
this._treeView = treeView;
};

/**
* Call Trees can have different types of "weights" for the data. Choose the
* appropriate labels for the call tree based on this weight.
*/
_weightTypeToColumns = memoize(
(weightType: WeightType): MaybeResizableColumn<CallNodeDisplayData>[] => {
switch (weightType) {
case 'tracing-ms':
return [
{
propName: 'totalPercent',
titleL10nId: '',
initialWidth: 55,
hideDividerAfter: true,
},
{
propName: 'total',
titleL10nId: 'CallTree--tracing-ms-total',
minWidth: 30,
initialWidth: 70,
resizable: true,
headerWidthAdjustment: 55 /* totalPercent initialWidth */,
},
{
propName: 'self',
titleL10nId: 'CallTree--tracing-ms-self',
minWidth: 40,
initialWidth: 80,
resizable: true,
},
{
propName: 'icon',
titleL10nId: '',
component: Icon as any,
initialWidth: 20,
},
];
case 'samples':
return [
{
propName: 'totalPercent',
titleL10nId: '',
initialWidth: 55,
hideDividerAfter: true,
},
{
propName: 'total',
titleL10nId: 'CallTree--samples-total',
minWidth: 30,
initialWidth: 70,
resizable: true,
headerWidthAdjustment: 55 /* totalPercent initialWidth */,
},
{
propName: 'self',
titleL10nId: 'CallTree--samples-self',
minWidth: 40,
initialWidth: 80,
resizable: true,
},
{
propName: 'icon',
titleL10nId: '',
component: Icon as any,
initialWidth: 20,
},
];
case 'bytes':
return [
{
propName: 'totalPercent',
titleL10nId: '',
initialWidth: 55,
hideDividerAfter: true,
},
{
propName: 'total',
titleL10nId: 'CallTree--bytes-total',
minWidth: 30,
initialWidth: 140,
resizable: true,
headerWidthAdjustment: 55 /* totalPercent initialWidth */,
},
{
propName: 'self',
titleL10nId: 'CallTree--bytes-self',
minWidth: 40,
initialWidth: 100,
resizable: true,
},
{
propName: 'icon',
titleL10nId: '',
component: Icon as any,
initialWidth: 20,
},
];
default:
throw assertExhaustiveCheck(weightType, 'Unhandled WeightType.');
}
},
// Use a Map cache, as the function only takes one argument, which is a simple string.
{ cache: new Map() }
);

override componentDidMount() {
this.focus();
this.maybeProcureInterestingInitialSelection();
Expand Down Expand Up @@ -367,9 +248,9 @@ class CallTreeImpl extends PureComponent<Props> {
return (
<TreeView
tree={tree}
fixedColumns={this._weightTypeToColumns(weightType)}
mainColumn={this._mainColumn}
appendageColumn={this._appendageColumn}
fixedColumns={treeColumnsForWeightType(weightType)}
mainColumn={nameColumn}
appendageColumn={libColumn}
onSelectionChange={this._onSelectedCallNodeChange}
onRightClickSelection={this._onRightClickSelection}
onExpandedNodesChange={this._onExpandedCallNodesChange}
Expand Down
133 changes: 133 additions & 0 deletions src/components/calltree/columns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { Icon } from 'firefox-profiler/components/shared/Icon';
import { assertExhaustiveCheck } from 'firefox-profiler/utils/types';

import type {
Column,
MaybeResizableColumn,
} from 'firefox-profiler/components/shared/TreeView';
import type { CallNodeDisplayData, WeightType } from 'firefox-profiler/types';

export const nameColumn: Column<CallNodeDisplayData> = {
propName: 'name',
titleL10nId: '',
};

export const libColumn: Column<CallNodeDisplayData> = {
propName: 'lib',
titleL10nId: '',
};

export const treeColumnsForTracingMs: MaybeResizableColumn<CallNodeDisplayData>[] =
[
{
propName: 'totalPercent',
titleL10nId: '',
initialWidth: 55,
hideDividerAfter: true,
},
{
propName: 'total',
titleL10nId: 'CallTree--tracing-ms-total',
minWidth: 30,
initialWidth: 70,
resizable: true,
headerWidthAdjustment: 55 /* totalPercent initialWidth */,
},
{
propName: 'self',
titleL10nId: 'CallTree--tracing-ms-self',
minWidth: 40,
initialWidth: 80,
resizable: true,
},
{
propName: 'icon',
titleL10nId: '',
component: Icon as any,
initialWidth: 20,
},
];

export const treeColumnsForSamples: MaybeResizableColumn<CallNodeDisplayData>[] =
[
{
propName: 'totalPercent',
titleL10nId: '',
initialWidth: 55,
hideDividerAfter: true,
},
{
propName: 'total',
titleL10nId: 'CallTree--samples-total',
minWidth: 30,
initialWidth: 70,
resizable: true,
headerWidthAdjustment: 55 /* totalPercent initialWidth */,
},
{
propName: 'self',
titleL10nId: 'CallTree--samples-self',
minWidth: 40,
initialWidth: 80,
resizable: true,
},
{
propName: 'icon',
titleL10nId: '',
component: Icon as any,
initialWidth: 20,
},
];

export const treeColumnsForBytes: MaybeResizableColumn<CallNodeDisplayData>[] =
[
{
propName: 'totalPercent',
titleL10nId: '',
initialWidth: 55,
hideDividerAfter: true,
},
{
propName: 'total',
titleL10nId: 'CallTree--bytes-total',
minWidth: 30,
initialWidth: 140,
resizable: true,
headerWidthAdjustment: 55 /* totalPercent initialWidth */,
},
{
propName: 'self',
titleL10nId: 'CallTree--bytes-self',
minWidth: 40,
initialWidth: 100,
resizable: true,
},
{
propName: 'icon',
titleL10nId: '',
component: Icon as any,
initialWidth: 20,
},
];

// Returns the call-tree column set appropriate for the given weight type. The
// returned array is the module-level constant for that weight, so the result
// is identity-stable for callers that feed it into PureComponent props.
export function treeColumnsForWeightType(
weightType: WeightType
): MaybeResizableColumn<CallNodeDisplayData>[] {
switch (weightType) {
case 'tracing-ms':
return treeColumnsForTracingMs;
case 'samples':
return treeColumnsForSamples;
case 'bytes':
return treeColumnsForBytes;
default:
throw assertExhaustiveCheck(weightType, 'Unhandled WeightType.');
}
}
Loading