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
14 changes: 13 additions & 1 deletion src/components/calltree/CallTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import React, { PureComponent } from 'react';
import memoize from 'memoize-immutable';
import explicitConnect from 'firefox-profiler/utils/connect';
import { TreeView } from 'firefox-profiler/components/shared/TreeView';
import {
TreeView,
ColumnSortState,
} from 'firefox-profiler/components/shared/TreeView';
import { CallTreeEmptyReasons } from './CallTreeEmptyReasons';
import { Icon } from 'firefox-profiler/components/shared/Icon';
import { getCallNodePathFromIndex } from 'firefox-profiler/profile-logic/profile-data';
Expand Down Expand Up @@ -87,6 +90,8 @@ class CallTreeImpl extends PureComponent<Props> {
};
_treeView: TreeView<CallNodeDisplayData> | null = null;
_takeTreeViewRef = (treeView) => (this._treeView = treeView);
_sortableColumns = new Set(['self', 'total']);
_sortedColumns = new ColumnSortState([{ column: 'total', ascending: false }]);

/**
* Call Trees can have different types of "weights" for the data. Choose the
Expand Down Expand Up @@ -260,6 +265,10 @@ class CallTreeImpl extends PureComponent<Props> {
}
}

_onSort = (sortedColumns: ColumnSortState) => {
this._sortedColumns = sortedColumns;
};

render() {
const {
tree,
Expand Down Expand Up @@ -296,6 +305,9 @@ class CallTreeImpl extends PureComponent<Props> {
onKeyDown={this._onKeyDown}
onEnterKey={this._onEnterOrDoubleClick}
onDoubleClick={this._onEnterOrDoubleClick}
initialSortedColumns={this._sortedColumns}
onSort={this._onSort}
sortableColumns={this._sortableColumns}
/>
);
}
Expand Down
58 changes: 51 additions & 7 deletions src/components/marker-table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React, { PureComponent } from 'react';
import memoize from 'memoize-immutable';

import explicitConnect from '../../utils/connect';
import { TreeView } from '../shared/TreeView';
import { TreeView, ColumnSortState } from '../shared/TreeView';
import { MarkerTableEmptyReasons } from './MarkerTableEmptyReasons';
import {
getZeroAt,
Expand Down Expand Up @@ -42,7 +42,9 @@ const MAX_DESCRIPTION_CHARACTERS = 500;

type MarkerDisplayData = {|
start: string,
rawStart: Milliseconds,
duration: string | null,
rawDuration: Milliseconds | null,
name: string,
type: string,
|};
Expand Down Expand Up @@ -70,12 +72,40 @@ class MarkerTree {
this._getMarkerLabel = getMarkerLabel;
}

getRoots(): MarkerIndex[] {
getRoots(sort: ColumnSortState | null = null): MarkerIndex[] {
if (sort !== null) {
return sort.sortItemsHelper(
this._markerIndexes,
(first: MarkerIndex, second: MarkerIndex, column: string) => {
const firstData = this.getDisplayData(first);
const secondData = this.getDisplayData(second);
switch (column) {
case 'start':
return secondData.rawStart - firstData.rawStart;
case 'duration':
if (firstData.rawDuration === null) {
return -1;
}
if (secondData.rawDuration === null) {
return 1;
}
return secondData.rawDuration - firstData.rawDuration;
case 'type':
return firstData.type.localeCompare(secondData.type);
default:
throw new Error('Invalid column ' + column);
}
}
);
}
return this._markerIndexes;
}

getChildren(markerIndex: MarkerIndex): MarkerIndex[] {
return markerIndex === -1 ? this.getRoots() : [];
getChildren(
markerIndex: MarkerIndex,
sort: ColumnSortState | null = null
): MarkerIndex[] {
return markerIndex === -1 ? this.getRoots(sort) : [];
}

hasChildren(_markerIndex: MarkerIndex): boolean {
Expand Down Expand Up @@ -113,10 +143,13 @@ class MarkerTree {
}

let duration = null;
let rawDuration: number | null = null;
const markerEnd = marker.end;
if (marker.incomplete) {
duration = 'unknown';
} else if (marker.end !== null) {
duration = formatTimestamp(marker.end - marker.start);
} else if (markerEnd !== null) {
duration = formatTimestamp(markerEnd - marker.start);
rawDuration = markerEnd - marker.start;
}

displayData = {
Expand All @@ -128,6 +161,8 @@ class MarkerTree {
marker.name,
marker.data
),
rawDuration: rawDuration,
rawStart: marker.start,
};
this._displayDataByIndex.set(markerIndex, displayData);
}
Expand Down Expand Up @@ -164,11 +199,13 @@ class MarkerTableImpl extends PureComponent<Props> {
{ propName: 'duration', titleL10nId: 'MarkerTable--duration' },
{ propName: 'type', titleL10nId: 'MarkerTable--type' },
];
_sortableColumns = new Set(['start', 'duration', 'type', 'name']);
_mainColumn = { propName: 'name', titleL10nId: 'MarkerTable--description' };
_expandedNodeIds: Array<MarkerIndex | null> = [];
_onExpandedNodeIdsChange = () => {};
_treeView: ?TreeView<MarkerDisplayData>;
_takeTreeViewRef = (treeView) => (this._treeView = treeView);
_sortedColumns = new ColumnSortState([{ column: 'start', ascending: true }]);

getMarkerTree = memoize((...args) => new MarkerTree(...args), { limit: 1 });

Expand Down Expand Up @@ -204,6 +241,10 @@ class MarkerTableImpl extends PureComponent<Props> {
changeRightClickedMarker(threadsKey, selectedMarker);
};

_onSort = (sortedColumns: ColumnSortState) => {
this._sortedColumns = sortedColumns;
};

render() {
const {
getMarker,
Expand All @@ -214,7 +255,7 @@ class MarkerTableImpl extends PureComponent<Props> {
markerSchemaByName,
getMarkerLabel,
} = this.props;
const tree = this.getMarkerTree(
const tree: MarkerTree = this.getMarkerTree(
getMarker,
markerIndexes,
zeroAt,
Expand Down Expand Up @@ -247,6 +288,9 @@ class MarkerTableImpl extends PureComponent<Props> {
contextMenuId="MarkerContextMenu"
rowHeight={16}
indentWidth={10}
initialSortedColumns={this._sortedColumns}
onSort={this._onSort}
sortableColumns={this._sortableColumns}
/>
)}
</div>
Expand Down
13 changes: 13 additions & 0 deletions src/components/shared/TreeView.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,19 @@
border-right: 1px solid var(--grey-30);
}

.treeViewHeaderColumn.sortInactive::after {
content: ' ▲';
opacity: 0;
}

.treeViewHeaderColumn.sortDescending::after {
content: ' ▲';
}

.treeViewHeaderColumn.sortAscending::after {
content: ' ▼ ';
}

.treeBadge {
display: inline-block;
overflow: hidden;
Expand Down
Loading