| Index: chrome/browser/resources/profiler.js
|
| ===================================================================
|
| --- chrome/browser/resources/profiler.js (revision 113249)
|
| +++ chrome/browser/resources/profiler.js (working copy)
|
| @@ -866,8 +866,13 @@
|
| * If |mergeSimilarThreads| is true, then threads with a similar name will be
|
| * considered equivalent. For instance, "WorkerThread-1" and "WorkerThread-2"
|
| * will be remapped to "WorkerThread-*".
|
| + *
|
| + * If |outputAsDictionary| is false then the merged rows will be returned as a
|
| + * flat list. Otherwise the result will be a dictionary, where each row
|
| + * has a unique key.
|
| */
|
| - function mergeRows(origRows, mergeKeys, mergeSimilarThreads) {
|
| + function mergeRows(origRows, mergeKeys, mergeSimilarThreads,
|
| + outputAsDictionary) {
|
| // Define a translation function for each property. Normally we copy over
|
| // properties as-is, but if we have been asked to "merge similar threads" we
|
| // we will remap the thread names that end in a numeric suffix.
|
| @@ -897,12 +902,13 @@
|
| // their value as part of the merge.
|
| var aggregateKeys = ALL_KEYS.slice(0);
|
| deleteValuesFromArray(aggregateKeys, IDENTITY_KEYS);
|
| + deleteValuesFromArray(aggregateKeys, mergeKeys);
|
|
|
| // Group all the identical rows together, bucketed into |identicalRows|.
|
| var identicalRows =
|
| bucketIdenticalRows(origRows, identityKeys, propertyGetterFunc);
|
|
|
| - var mergedRows = [];
|
| + var mergedRows = outputAsDictionary ? {} : [];
|
|
|
| // Merge the rows and save the results to |mergedRows|.
|
| for (var k in identicalRows) {
|
| @@ -910,8 +916,13 @@
|
| var l = identicalRows[k];
|
|
|
| var newRow = [];
|
| - mergedRows.push(newRow);
|
|
|
| + if (outputAsDictionary) {
|
| + mergedRows[k] = newRow;
|
| + } else {
|
| + mergedRows.push(newRow);
|
| + }
|
| +
|
| // Copy over all the identity columns to the new row (since they
|
| // were the same for each row matched).
|
| for (var i = 0; i < identityKeys.length; ++i)
|
| @@ -933,14 +944,15 @@
|
| }
|
|
|
| /**
|
| - * Takes two flat lists data1 and data2, and returns a new flat list which
|
| + * Takes two dictionaries data1 and data2, and returns a new flat list which
|
| * represents the difference between them. The exact meaning of "difference"
|
| * is column specific, but for most numeric fields (like the count, or total
|
| * time), it is found by subtracting.
|
| *
|
| - * TODO(eroman): Some of this code is duplicated from mergeRows().
|
| + * Rows in data1 and data2 are expected to use the same scheme for the keys.
|
| + * In other words, data1[k] is considered the analagous row to data2[k].
|
| */
|
| - function subtractSnapshots(data1, data2) {
|
| + function subtractSnapshots(data1, data2, columnsToExclude) {
|
| // These columns are computed from the other columns. We won't bother
|
| // diffing/aggregating these, but rather will derive them again from the
|
| // final row.
|
| @@ -949,51 +961,45 @@
|
| // These are the keys which determine row equality. Since we are not doing
|
| // any merging yet at this point, it is simply the list of all identity
|
| // columns.
|
| - var identityKeys = IDENTITY_KEYS;
|
| + var identityKeys = IDENTITY_KEYS.slice(0);
|
| + deleteValuesFromArray(identityKeys, columnsToExclude);
|
|
|
| // The columns to compute via aggregation is everything else.
|
| var aggregateKeys = ALL_KEYS.slice(0);
|
| deleteValuesFromArray(aggregateKeys, IDENTITY_KEYS);
|
| deleteValuesFromArray(aggregateKeys, COMPUTED_AGGREGATE_KEYS);
|
| + deleteValuesFromArray(aggregateKeys, columnsToExclude);
|
|
|
| - // Group all the identical rows for each list together.
|
| - var propertyGetterFunc = function(row, key) { return row[key]; };
|
| - var identicalRows1 =
|
| - bucketIdenticalRows(data1, identityKeys, propertyGetterFunc);
|
| - var identicalRows2 =
|
| - bucketIdenticalRows(data2, identityKeys, propertyGetterFunc);
|
| -
|
| var diffedRows = [];
|
|
|
| - for (var k in identicalRows2) {
|
| - var rows2 = identicalRows2[k];
|
| - var rows1 = identicalRows1[k];
|
| - if (rows1 == undefined)
|
| - rows1 = [];
|
| + for (var rowId in data2) {
|
| + var row1 = data1[rowId];
|
| + var row2 = data2[rowId];
|
|
|
| var newRow = [];
|
|
|
| // Copy over all the identity columns to the new row (since they
|
| // were the same for each row matched).
|
| for (var i = 0; i < identityKeys.length; ++i)
|
| - newRow[identityKeys[i]] = propertyGetterFunc(rows2[0], identityKeys[i]);
|
| + newRow[identityKeys[i]] = row2[identityKeys[i]];
|
|
|
| - // The raw data for each snapshot *may* have contained duplicate rows, so
|
| - // smash them down into a single row using our aggregation functions.
|
| - var aggregates1 = initializeAggregates(aggregateKeys);
|
| - var aggregates2 = initializeAggregates(aggregateKeys);
|
| - for (var i = 0; i < rows1.length; ++i)
|
| - consumeAggregates(aggregates1, rows1[i]);
|
| - for (var i = 0; i < rows2.length; ++i)
|
| - consumeAggregates(aggregates2, rows2[i]);
|
| + // Diff the two rows.
|
| + if (row1) {
|
| + for (var i = 0; i < aggregateKeys.length; ++i) {
|
| + var aggregateKey = aggregateKeys[i];
|
| + var a = row1[aggregateKey];
|
| + var b = row2[aggregateKey];
|
|
|
| - // Finally, diff the two merged rows.
|
| - for (var aggregateKey in aggregates2) {
|
| - var a = aggregates1[aggregateKey].getValue();
|
| - var b = aggregates2[aggregateKey].getValue();
|
| -
|
| - var diffFunc = KEY_PROPERTIES[aggregateKey].diff;
|
| - newRow[aggregateKey] = diffFunc(a, b);
|
| + var diffFunc = KEY_PROPERTIES[aggregateKey].diff;
|
| + newRow[aggregateKey] = diffFunc(a, b);
|
| + }
|
| + } else {
|
| + // If the the row doesn't appear in snapshot1, then there is nothing to
|
| + // diff, so just copy row2 as is.
|
| + for (var i = 0; i < aggregateKeys.length; ++i) {
|
| + var aggregateKey = aggregateKeys[i];
|
| + newRow[aggregateKey] = row2[aggregateKey];
|
| + }
|
| }
|
|
|
| if (newRow[KEY_COUNT] == 0) {
|
| @@ -1002,8 +1008,8 @@
|
| continue;
|
| }
|
|
|
| - // Since we excluded the averages during diffing phase, re-compute them
|
| - // using the diffed totals.
|
| + // Since we excluded the averages during the diffing phase, re-compute
|
| + // them using the diffed totals.
|
| computeDataRowAverages(newRow);
|
| diffedRows.push(newRow);
|
| }
|
| @@ -1239,34 +1245,35 @@
|
| // We may end up calling addDataToSnapshot_() repeatedly (once for each
|
| // process). To avoid this from slowing us down we do bulk updates on a
|
| // timer.
|
| - this.updateFlatDataSoon_();
|
| + this.updateMergedDataSoon_();
|
| },
|
|
|
| - updateFlatDataSoon_: function() {
|
| - if (this.updateFlatDataPending_) {
|
| + updateMergedDataSoon_: function() {
|
| + if (this.updateMergedDataPending_) {
|
| // If a delayed task has already been posted to re-merge the data,
|
| // then we don't need to do anything extra.
|
| return;
|
| }
|
|
|
| - // Otherwise schedule updateFlatData_() to be called later. We want it to
|
| - // be called no more than once every PROCESS_DATA_DELAY_MS milliseconds.
|
| + // Otherwise schedule updateMergedData_() to be called later. We want it
|
| + // to be called no more than once every PROCESS_DATA_DELAY_MS
|
| + // milliseconds.
|
|
|
| - if (this.lastUpdateFlatDataTime_ == undefined)
|
| - this.lastUpdateFlatDataTime_ = 0;
|
| + if (this.lastUpdateMergedDataTime_ == undefined)
|
| + this.lastUpdateMergedDataTime_ = 0;
|
|
|
| - var timeSinceLastMerge = getTimeMillis() - this.lastUpdateFlatDataTime_;
|
| + var timeSinceLastMerge = getTimeMillis() - this.lastUpdateMergedDataTime_;
|
| var timeToWait = Math.max(0, PROCESS_DATA_DELAY_MS - timeSinceLastMerge);
|
|
|
| var functionToRun = function() {
|
| // Do the actual update.
|
| - this.updateFlatData_();
|
| + this.updateMergedData_();
|
| // Keep track of when we last ran.
|
| - this.lastUpdateFlatDataTime_ = getTimeMillis();
|
| - this.updateFlatDataPending_ = false;
|
| + this.lastUpdateMergedDataTime_ = getTimeMillis();
|
| + this.updateMergedDataPending_ = false;
|
| }.bind(this);
|
|
|
| - this.updateFlatDataPending_ = true;
|
| + this.updateMergedDataPending_ = true;
|
| window.setTimeout(functionToRun, timeToWait);
|
| },
|
|
|
| @@ -1297,19 +1304,15 @@
|
| },
|
|
|
| /**
|
| - * This function should be called any time a snapshot dependency for what is
|
| - * being displayed on the screen has changed. It will re-calculate the
|
| - * difference between the two snapshots and update flatData_.
|
| + * Re-draw the description which explains which snapshots are currently
|
| + * selected (if two snapshots were selected we explain that the *difference*
|
| + * between them is being displayed).
|
| */
|
| - updateFlatData_: function() {
|
| + updateSnapshotSelectionSummaryDiv_: function() {
|
| var summaryDiv = $(SNAPSHOT_SELECTION_SUMMARY_ID);
|
|
|
| var selectedSnapshots = this.getSelectedSnapshotIndexes_();
|
| if (selectedSnapshots.length == 1) {
|
| - // If only one snapshot is chosen then we will display that snapshot's
|
| - // data in its entirety.
|
| - this.flatData_ = this.snapshots_[selectedSnapshots[0]].flatData;
|
| -
|
| // Don't bother displaying any text when just 1 snapshot is selected,
|
| // since it is obvious what this should do.
|
| summaryDiv.innerText = '';
|
| @@ -1319,9 +1322,6 @@
|
| var snapshot1 = this.snapshots_[selectedSnapshots[0]];
|
| var snapshot2 = this.snapshots_[selectedSnapshots[1]];
|
|
|
| - this.flatData_ =
|
| - subtractSnapshots(snapshot1.flatData, snapshot2.flatData);
|
| -
|
| var timeDeltaInSeconds =
|
| ((snapshot2.time - snapshot1.time) / 1000).toFixed(0);
|
|
|
| @@ -1336,17 +1336,48 @@
|
| // This shouldn't be possible...
|
| throw 'Unexpected number of selected snapshots';
|
| }
|
| -
|
| - // Recompute mergedData_ (since it is derived from flatData_)
|
| - this.updateMergedData_();
|
| },
|
|
|
| updateMergedData_: function() {
|
| - // Recompute mergedData_.
|
| - this.mergedData_ = mergeRows(this.flatData_,
|
| - this.getMergeColumns_(),
|
| - this.shouldMergeSimilarThreads_());
|
| + // Retrieve the merge options.
|
| + var mergeColumns = this.getMergeColumns_();
|
| + var shouldMergeSimilarThreads = this.shouldMergeSimilarThreads_();
|
|
|
| + var selectedSnapshots = this.getSelectedSnapshotIndexes_();
|
| +
|
| + // We do merges a bit differently depending if we are displaying the diffs
|
| + // between two snapshots, or just displaying a single snapshot.
|
| + if (selectedSnapshots.length == 1) {
|
| + var snapshot = this.snapshots_[selectedSnapshots[0]];
|
| + this.mergedData_ = mergeRows(snapshot.flatData,
|
| + mergeColumns,
|
| + shouldMergeSimilarThreads,
|
| + false);
|
| +
|
| + } else if (selectedSnapshots.length == 2) {
|
| + var snapshot1 = this.snapshots_[selectedSnapshots[0]];
|
| + var snapshot2 = this.snapshots_[selectedSnapshots[1]];
|
| +
|
| + // Merge the data for snapshot1.
|
| + var mergedRows1 = mergeRows(snapshot1.flatData,
|
| + mergeColumns,
|
| + shouldMergeSimilarThreads,
|
| + true);
|
| +
|
| + // Merge the data for snapshot2.
|
| + var mergedRows2 = mergeRows(snapshot2.flatData,
|
| + mergeColumns,
|
| + shouldMergeSimilarThreads,
|
| + true);
|
| +
|
| + // Do a diff between the two snapshots.
|
| + this.mergedData_ = subtractSnapshots(mergedRows1,
|
| + mergedRows2,
|
| + mergeColumns);
|
| + } else {
|
| + throw 'Unexpected number of selected snapshots';
|
| + }
|
| +
|
| // Recompute filteredData_ (since it is derived from mergedData_)
|
| this.updateFilteredData_();
|
| },
|
| @@ -1677,7 +1708,6 @@
|
| // 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_ = {};
|
| @@ -1793,9 +1823,10 @@
|
| event.target.checked = true;
|
|
|
| this.updateSnapshotCheckboxStyling_();
|
| + this.updateSnapshotSelectionSummaryDiv_();
|
|
|
| - // Recompute flatData_ (since it is derived from selected snapshots).
|
| - this.updateFlatData_();
|
| + // Recompute mergedData_ (since it is derived from selected snapshots).
|
| + this.updateMergedData_();
|
| },
|
|
|
| fillSelectionCheckboxes_: function(parent) {
|
|
|