| Index: chrome/browser/resources/profiler.js
|
| ===================================================================
|
| --- chrome/browser/resources/profiler.js (revision 110261)
|
| +++ chrome/browser/resources/profiler.js (working copy)
|
| @@ -5,10 +5,6 @@
|
| var g_browserBridge;
|
| var g_mainView;
|
|
|
| -// TODO(eroman): Don't repeat the work of grouping, sorting, merging on every
|
| -// redraw. Rather do it only once when one of its dependencies
|
| -// change and cache the result.
|
| -
|
| /**
|
| * Main entry point called once the page has loaded.
|
| */
|
| @@ -723,48 +719,6 @@
|
| // --------------------------------------------------------------------------
|
|
|
| /**
|
| - * Selects all the data in |rows| which are matched by |filterFunc|, and
|
| - * buckets the results using |entryToGroupKeyFunc|. For each bucket aggregates
|
| - * are computed, and the results are sorted.
|
| - *
|
| - * Returns a dictionary whose keys are the group name, and the value is an
|
| - * objected containing two properties: |rows| and |aggregates|.
|
| - */
|
| - function prepareData(rows, entryToGroupKeyFunc, filterFunc, sortingFunc) {
|
| - var groupedData = {};
|
| -
|
| - for (var i = 0; i < rows.length; ++i) {
|
| - var e = rows[i];
|
| -
|
| - if (!filterFunc(e))
|
| - continue; // Not matched by our filter, discard the row.
|
| -
|
| - var groupKey = entryToGroupKeyFunc(e);
|
| -
|
| - var groupData = groupedData[groupKey];
|
| - if (!groupData) {
|
| - groupData = {
|
| - aggregates: initializeAggregates(ALL_KEYS),
|
| - rows: [],
|
| - };
|
| - groupedData[groupKey] = groupData;
|
| - }
|
| -
|
| - // Add the row to our list.
|
| - groupData.rows.push(e);
|
| -
|
| - // Update aggregates for each column.
|
| - consumeAggregates(groupData.aggregates, e);
|
| - }
|
| -
|
| - // Sort all the data.
|
| - for (var groupKey in groupedData)
|
| - groupedData[groupKey].rows.sort(sortingFunc);
|
| -
|
| - return groupedData;
|
| - }
|
| -
|
| - /**
|
| * Adds new derived properties to row. Mutates the provided dictionary |e|.
|
| */
|
| function augmentDataRow(e) {
|
| @@ -913,12 +867,12 @@
|
| /**
|
| * Renders the information for a particular group.
|
| */
|
| - function drawGroup(parent, groupKey, groupData, columns,
|
| + function drawGroup(parent, groupData, columns,
|
| columnOnClickHandler, currentSortKeys) {
|
| var div = addNode(parent, 'div');
|
| div.className = 'group-container';
|
|
|
| - drawGroupTitle(div, groupKey);
|
| + drawGroupTitle(div, groupData.key);
|
|
|
| var table = addNode(div, 'table');
|
|
|
| @@ -1211,38 +1165,96 @@
|
| // Add our computed properties.
|
| augmentDataRow(newRow);
|
|
|
| - this.allData_.push(newRow);
|
| + this.flatData_.push(newRow);
|
| }
|
|
|
| + // Recompute the merged data based on flatData_.
|
| + this.updateMergedData_();
|
| + },
|
| +
|
| + updateMergedData_: function() {
|
| + // Recompute mergedData_.
|
| + this.mergedData_ = mergeRows(this.flatData_,
|
| + this.getMergeColumns_(),
|
| + this.shouldMergeSimilarThreads_());
|
| +
|
| + // Recompute filteredData_ (since it is derived from mergedData_)
|
| + this.updateFilteredData_();
|
| + },
|
| +
|
| + updateFilteredData_: function() {
|
| + // Recompute filteredData_.
|
| + this.filteredData_ = [];
|
| + var filterFunc = this.getFilterFunction_();
|
| + for (var i = 0; i < this.mergedData_.length; ++i) {
|
| + var r = this.mergedData_[i];
|
| + if (!filterFunc(r)) {
|
| + // Not matched by our filter, discard.
|
| + continue;
|
| + }
|
| + this.filteredData_.push(r);
|
| + }
|
| +
|
| + // Recompute groupedData_ (since it is derived from filteredData_)
|
| + this.updateGroupedData_();
|
| + },
|
| +
|
| + updateGroupedData_: function() {
|
| + // Recompute groupedData_.
|
| + var groupKeyToData = {};
|
| + var entryToGroupKeyFunc = this.getGroupingFunction_();
|
| + for (var i = 0; i < this.filteredData_.length; ++i) {
|
| + var r = this.filteredData_[i];
|
| +
|
| + var groupKey = entryToGroupKeyFunc(r);
|
| +
|
| + var groupData = groupKeyToData[groupKey];
|
| + if (!groupData) {
|
| + groupData = {
|
| + key: JSON.parse(groupKey),
|
| + aggregates: initializeAggregates(ALL_KEYS),
|
| + rows: [],
|
| + };
|
| + groupKeyToData[groupKey] = groupData;
|
| + }
|
| +
|
| + // Add the row to our list.
|
| + groupData.rows.push(r);
|
| +
|
| + // Update aggregates for each column.
|
| + consumeAggregates(groupData.aggregates, r);
|
| + }
|
| + this.groupedData_ = groupKeyToData;
|
| +
|
| + // Figure out a display order for the groups themselves.
|
| + this.sortedGroupKeys_ = getDictionaryKeys(groupKeyToData);
|
| + this.sortedGroupKeys_.sort(this.getGroupSortingFunction_());
|
| +
|
| + // Sort the group data.
|
| + this.sortGroupedData_();
|
| + },
|
| +
|
| + sortGroupedData_: function() {
|
| + var sortingFunc = this.getSortingFunction_();
|
| + for (var k in this.groupedData_)
|
| + this.groupedData_[k].rows.sort(sortingFunc);
|
| +
|
| + // Every cached data dependency is now up to date, all that is left is
|
| + // to actually draw the result.
|
| this.redrawData_();
|
| },
|
|
|
| - redrawData_: function() {
|
| - // Eliminate columns which we are merging on.
|
| - var mergedKeys = this.getMergeColumns_();
|
| - var data = mergeRows(
|
| - this.allData_, mergedKeys, this.shouldMergeSimilarThreads_());
|
| -
|
| + getVisibleColumnKeys_: function() {
|
| // Figure out what columns to include, based on the selected checkboxes.
|
| var columns = this.getSelectionColumns_();
|
| - deleteValuesFromArray(columns, mergedKeys);
|
|
|
| - // Group, aggregate, filter, and sort the data.
|
| - var groupedData = prepareData(
|
| - data, this.getGroupingFunction_(), this.getFilterFunction_(),
|
| - this.getSortingFunction_());
|
| + // Eliminate columns which we are merging on.
|
| + deleteValuesFromArray(columns, this.getMergeColumns_());
|
|
|
| - // Figure out a display order for the groups.
|
| - var groupKeys = getDictionaryKeys(groupedData);
|
| - groupKeys.sort(this.getGroupSortingFunction_());
|
| -
|
| - // Clear the results div, sine we may be overwriting older data.
|
| - var parent = $(RESULTS_DIV_ID);
|
| - parent.innerHTML = '';
|
| -
|
| - if (groupKeys.length > 0) {
|
| + // Eliminate columns which we are grouped on.
|
| + if (this.sortedGroupKeys_.length > 0) {
|
| // The grouping will be the the same for each so just pick the first.
|
| - var randomGroupKey = JSON.parse(groupKeys[0]);
|
| + var randomGroupKey = this.groupedData_[this.sortedGroupKeys_[0]].key;
|
|
|
| // The grouped properties are going to be the same for each row in our,
|
| // table, so avoid drawing them in our table!
|
| @@ -1254,21 +1266,46 @@
|
| deleteValuesFromArray(columns, keysToExclude);
|
| }
|
|
|
| + return columns;
|
| + },
|
| +
|
| + redrawData_: function() {
|
| + // Clear the results div, sine we may be overwriting older data.
|
| + var parent = $(RESULTS_DIV_ID);
|
| + parent.innerHTML = '';
|
| +
|
| + var columns = this.getVisibleColumnKeys_();
|
| +
|
| var columnOnClickHandler = this.onClickColumn_.bind(this);
|
|
|
| // Draw each group.
|
| - for (var i = 0; i < groupKeys.length; ++i) {
|
| - var groupKeyString = groupKeys[i];
|
| - var groupData = groupedData[groupKeyString];
|
| - var groupKey = JSON.parse(groupKeyString);
|
| -
|
| - drawGroup(parent, groupKey, groupData, columns,
|
| + for (var i = 0; i < this.sortedGroupKeys_.length; ++i) {
|
| + var groupData = this.groupedData_[this.sortedGroupKeys_[i]];
|
| + drawGroup(parent, groupData, columns,
|
| columnOnClickHandler, this.currentSortKeys_);
|
| }
|
| },
|
|
|
| init_: function() {
|
| - this.allData_ = [];
|
| + // Data goes through the following pipeline:
|
| + // (1) Raw data received from browser, and transformed into our own
|
| + // internal row format (where properties are indexed by KEY_*
|
| + // constants.)
|
| + // (2) We "augment" each row by adding some extra computed columns
|
| + // (like averages).
|
| + // (3) The rows are merged using current merge settings.
|
| + // (4) The rows that don't match current search expression are
|
| + // tossed out.
|
| + // (5) The rows are organized into "groups" based on current settings,
|
| + // and aggregate values are computed for each resulting group.
|
| + // (6) The rows within each group are sorted using current settings.
|
| + // (7) The grouped rows are drawn to the screen.
|
| + this.flatData_ = [];
|
| + this.mergedData_ = [];
|
| + this.filteredData_ = [];
|
| + this.groupedData_ = {};
|
| + this.sortedGroupKeys_ = [];
|
| +
|
| this.fillSelectionCheckboxes_($(COLUMN_TOGGLES_CONTAINER_ID));
|
| this.fillMergeCheckboxes_($(COLUMN_MERGE_TOGGLES_CONTAINER_ID));
|
|
|
| @@ -1385,13 +1422,13 @@
|
| onChangedGrouping_: function(select, i) {
|
| updateKeyListFromDropdown(this.currentGroupingKeys_, i, select);
|
| this.fillGroupingDropdowns_();
|
| - this.redrawData_();
|
| + this.updateGroupedData_();
|
| },
|
|
|
| onChangedSorting_: function(select, i) {
|
| updateKeyListFromDropdown(this.currentSortKeys_, i, select);
|
| this.fillSortingDropdowns_();
|
| - this.redrawData_();
|
| + this.sortGroupedData_();
|
| },
|
|
|
| onSelectCheckboxChanged_: function() {
|
| @@ -1399,15 +1436,15 @@
|
| },
|
|
|
| onMergeCheckboxChanged_: function() {
|
| - this.redrawData_();
|
| + this.updateMergedData_();
|
| },
|
|
|
| onMergeSimilarThreadsCheckboxChanged_: function() {
|
| - this.redrawData_();
|
| + this.updateMergedData_();
|
| },
|
|
|
| onChangedFilter_: function() {
|
| - this.redrawData_();
|
| + this.updateFilteredData_();
|
| },
|
|
|
| /**
|
| @@ -1456,7 +1493,7 @@
|
| }
|
|
|
| this.fillSortingDropdowns_();
|
| - this.redrawData_();
|
| + this.sortGroupedData_();
|
| },
|
|
|
| getSortingFunction_: function() {
|
|
|