Changeset 145727 in webkit


Ignore:
Timestamp:
Mar 13, 2013 11:14:38 AM (11 years ago)
Author:
caseq@chromium.org
Message:

Web Inspector: coalesce repeating timeline records
https://bugs.webkit.org/show_bug.cgi?id=112168

Reviewed by Vsevolod Vlasov.

  • coalesce repeating top-level timeline events;
  • drive-by: only show categories that actually took time in aggregated stats;
  • English.lproj/localizedStrings.js:
  • inspector/front-end/TimelineFrameController.js:

(WebInspector.TimelineFrameController.prototype._innerAddRecord):

  • inspector/front-end/TimelinePanel.js:

(WebInspector.TimelinePanel.prototype._highlightRect):
(WebInspector.TimelineCalculator.prototype.computeBarGraphPercentages):

  • inspector/front-end/TimelinePresentationModel.js:

(WebInspector.TimelinePresentationModel.prototype.reset):
(WebInspector.TimelinePresentationModel.prototype._innerAddRecord):
(WebInspector.TimelinePresentationModel.prototype._updateAncestorStats):
(WebInspector.TimelinePresentationModel.prototype._findCoalescedParent):
(WebInspector.TimelinePresentationModel.prototype._replaceWithCoalescedRecord):
(WebInspector.TimelinePresentationModel.Record):
(WebInspector.TimelinePresentationModel.adoptRecord):
(WebInspector.TimelinePresentationModel.insertRetrospectiveRecord):
(WebInspector.TimelinePresentationModel.Record.prototype.get selfTime):
(WebInspector.TimelinePresentationModel.Record.prototype._generatePopupContentWithImagePreview):
(WebInspector.TimelinePresentationModel.Record.prototype._getRecordDetails):
(WebInspector.TimelinePresentationModel.Record.prototype.calculateAggregatedStats):

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r145726 r145727  
     12013-03-12  Andrey Kosyakov  <caseq@chromium.org>
     2
     3        Web Inspector: coalesce repeating timeline records
     4        https://bugs.webkit.org/show_bug.cgi?id=112168
     5
     6        Reviewed by Vsevolod Vlasov.
     7
     8        - coalesce repeating top-level timeline events;
     9        - drive-by: only show categories that actually took time in aggregated stats;
     10
     11        * English.lproj/localizedStrings.js:
     12        * inspector/front-end/TimelineFrameController.js:
     13        (WebInspector.TimelineFrameController.prototype._innerAddRecord):
     14        * inspector/front-end/TimelinePanel.js:
     15        (WebInspector.TimelinePanel.prototype._highlightRect):
     16        (WebInspector.TimelineCalculator.prototype.computeBarGraphPercentages):
     17        * inspector/front-end/TimelinePresentationModel.js:
     18        (WebInspector.TimelinePresentationModel.prototype.reset):
     19        (WebInspector.TimelinePresentationModel.prototype._innerAddRecord):
     20        (WebInspector.TimelinePresentationModel.prototype._updateAncestorStats):
     21        (WebInspector.TimelinePresentationModel.prototype._findCoalescedParent):
     22        (WebInspector.TimelinePresentationModel.prototype._replaceWithCoalescedRecord):
     23        (WebInspector.TimelinePresentationModel.Record):
     24        (WebInspector.TimelinePresentationModel.adoptRecord):
     25        (WebInspector.TimelinePresentationModel.insertRetrospectiveRecord):
     26        (WebInspector.TimelinePresentationModel.Record.prototype.get selfTime):
     27        (WebInspector.TimelinePresentationModel.Record.prototype._generatePopupContentWithImagePreview):
     28        (WebInspector.TimelinePresentationModel.Record.prototype._getRecordDetails):
     29        (WebInspector.TimelinePresentationModel.Record.prototype.calculateAggregatedStats):
     30
    1312013-03-13  Philip Rogers  <pdr@google.com>
    232
  • trunk/Source/WebCore/English.lproj/localizedStrings.js

    r145076 r145727  
    3737localizedStrings["%d \xd7 %d pixels"] = "%d \xd7 %d pixels";
    3838localizedStrings["%d × %d"] = "%d × %d";
     39localizedStrings["× %d"] = "× %d";
    3940localizedStrings["%s (%s)"] = "%s (%s)";
    4041localizedStrings["%s (at %s)"] = "%s (at %s)";
  • trunk/Source/WebCore/inspector/front-end/TimelineFrameController.js

    r144039 r145727  
    7979            if (!this._lastFrame)
    8080                this._lastFrame = this._createFrame(record);
    81             WebInspector.TimelineModel.aggregateTimeForRecord(this._lastFrame.timeByCategory, record);
     81            if (!record.thread)
     82                WebInspector.TimelineModel.aggregateTimeForRecord(this._lastFrame.timeByCategory, record);
    8283            this._lastFrame.cpuTime += WebInspector.TimelineModel.durationInSeconds(record);
    8384        }
  • trunk/Source/WebCore/inspector/front-end/TimelinePanel.js

    r145548 r145727  
    10791079    _highlightRect: function(record)
    10801080    {
     1081        if (record.coalesced)
     1082            return;
    10811083        if (this._highlightedRect === record.data)
    10821084            return;
     
    12941296        var end = (record.startTime + record.selfTime - this._minimumBoundary) / this.boundarySpan() * 100;
    12951297        var endWithChildren = (record.lastChildEndTime - this._minimumBoundary) / this.boundarySpan() * 100;
    1296         var cpuWidth = record.cpuTime / this.boundarySpan() * 100;
     1298        var cpuWidth = record.coalesced ? endWithChildren - start : record.cpuTime / this.boundarySpan() * 100;
    12971299        return {start: start, end: end, endWithChildren: endWithChildren, cpuWidth: cpuWidth};
    12981300    },
  • trunk/Source/WebCore/inspector/front-end/TimelinePresentationModel.js

    r144759 r145727  
    273273        this._lastScheduleStyleRecalculation = {};
    274274        this._webSocketCreateRecords = {};
     275        this._coalescingBuckets = {};
    275276    },
    276277
     
    303304        var isHiddenRecord = record.type in WebInspector.TimelinePresentationModel._hiddenRecords;
    304305        var origin;
     306        var coalescingBucket;
     307
    305308        if (!isHiddenRecord) {
    306309            var newParentRecord = this._findParentRecord(record);
     
    308311                origin = parentRecord;
    309312                parentRecord = newParentRecord;
     313            }
     314            if (parentRecord === this._rootRecord) {
     315                // On main thread, only coalesce if the last event is of same type.
     316                coalescingBucket = record.thread ? record.type : "mainThread";
     317                var coalescedRecord = this._findCoalescedParent(record, coalescingBucket);
     318                if (coalescedRecord) {
     319                    if (!origin)
     320                        origin = parentRecord;
     321                    parentRecord = coalescedRecord;
     322                }
    310323            }
    311324        }
     
    336349            return formattedRecord;
    337350
    338         formattedRecord.collapsed = (parentRecord === this._rootRecord);
     351        formattedRecord.collapsed = parentRecord === this._rootRecord;
     352        if (coalescingBucket)
     353            this._coalescingBuckets[coalescingBucket] = formattedRecord;
    339354
    340355        var childrenCount = children ? children.length : 0;
     
    342357            this._innerAddRecord(children[i], formattedRecord);
    343358
    344         formattedRecord.calculateAggregatedStats(WebInspector.TimelinePresentationModel.categories());
    345 
    346         if (origin) {
    347             var lastChildEndTime = formattedRecord.lastChildEndTime;
    348             var aggregatedStats = formattedRecord.aggregatedStats;
    349             for (var currentRecord = formattedRecord.parent; !currentRecord.isRoot(); currentRecord = currentRecord.parent) {
    350                 currentRecord._cpuTime += formattedRecord._cpuTime;
    351                 if (currentRecord.lastChildEndTime < lastChildEndTime)
    352                     currentRecord.lastChildEndTime = lastChildEndTime;
    353                 for (var category in aggregatedStats)
    354                     currentRecord.aggregatedStats[category] += aggregatedStats[category];
    355             }
    356         }
     359        formattedRecord.calculateAggregatedStats();
     360
     361        if (origin)
     362            this._updateAncestorStats(formattedRecord);
     363
     364        if (parentRecord.coalesced && parentRecord.startTime > formattedRecord.startTime)
     365            parentRecord._record.startTime = record.startTime;
     366
    357367        origin = formattedRecord.origin();
    358         if (!origin.isRoot()) {
     368        if (!origin.isRoot() && !origin.coalesced)
    359369            origin.selfTime -= formattedRecord.endTime - formattedRecord.startTime;
    360         }
    361370        return formattedRecord;
     371    },
     372
     373    /**
     374     * @param {WebInspector.TimelinePresentationModel.Record} record
     375     */
     376    _updateAncestorStats: function(record)
     377    {
     378        var lastChildEndTime = record.lastChildEndTime;
     379        var aggregatedStats = record.aggregatedStats;
     380        for (var currentRecord = record.parent; currentRecord && !currentRecord.isRoot(); currentRecord = currentRecord.parent) {
     381            currentRecord._cpuTime += record._cpuTime;
     382            if (currentRecord.lastChildEndTime < lastChildEndTime)
     383                currentRecord.lastChildEndTime = lastChildEndTime;
     384            for (var category in aggregatedStats)
     385                currentRecord.aggregatedStats[category] += aggregatedStats[category];
     386        }
     387    },
     388
     389    /**
     390     * @param {Object} record
     391     * @param {String} bucket
     392     * @return {WebInspector.TimelinePresentationModel.Record?}
     393     */
     394    _findCoalescedParent: function(record, bucket)
     395    {
     396        const coalescingThresholdSeconds = 0.001;
     397
     398        var lastRecord = this._coalescingBuckets[bucket];
     399        var startTime = WebInspector.TimelineModel.startTimeInSeconds(record);
     400        var endTime = WebInspector.TimelineModel.endTimeInSeconds(record);
     401        if (!lastRecord || lastRecord.type !== record.type)
     402            return null;
     403        if (lastRecord.endTime + coalescingThresholdSeconds < startTime)
     404            return null;
     405        if (endTime + coalescingThresholdSeconds < lastRecord.startTime)
     406            return null;
     407        if (lastRecord.parent.coalesced)
     408            return lastRecord.parent;
     409        // Do not aggregate records that were reparented.
     410        if (lastRecord.parent !== this._rootRecord)
     411            return null;
     412        return this._replaceWithCoalescedRecord(lastRecord);
     413    },
     414
     415    /**
     416     * @param {WebInspector.TimelinePresentationModel.Record} record
     417     * @return {WebInspector.TimelinePresentationModel.Record}
     418     */
     419    _replaceWithCoalescedRecord: function(record)
     420    {
     421        var rawRecord = {
     422            type: record._record.type,
     423            startTime: record._record.startTime,
     424            endTime: record._record.endTime,
     425            data: { }
     426        };
     427        if (record._record.thread)
     428            rawRecord.thread = "aggregated";
     429        var coalescedRecord = new WebInspector.TimelinePresentationModel.Record(this, rawRecord, null, null, null, false);
     430        var parent = record.parent;
     431
     432        coalescedRecord.coalesced = true;
     433        coalescedRecord.collapsed = true;
     434        coalescedRecord._children.push(record);
     435        record.parent = coalescedRecord;
     436        coalescedRecord.calculateAggregatedStats();
     437
     438        coalescedRecord.parent = parent;
     439        parent._children[parent._children.indexOf(record)] = coalescedRecord;
     440        return coalescedRecord;
    362441    },
    363442
     
    514593{
    515594    this._linkifier = presentationModel._linkifier;
    516     this._aggregatedStats = [];
     595    this._aggregatedStats = {};
    517596    this._record = record;
    518597    this._children = [];
    519598    if (!hidden && parentRecord) {
    520599        this.parent = parentRecord;
    521         if (this.isBackground && parentRecord === presentationModel._rootRecord)
    522             WebInspector.TimelinePresentationModel.insertRetrospecitveRecord(parentRecord, this);
     600        if (this.isBackground)
     601            WebInspector.TimelinePresentationModel.insertRetrospectiveRecord(parentRecord, this);
    523602        else
    524603            parentRecord.children.push(this);
     
    622701                if (openRecord.startTime > timeRecord.startTime)
    623702                    continue;
    624                 timeRecord.parent.children.splice(timeRecord.parent.children.indexOf(timeRecord));
    625                 WebInspector.TimelinePresentationModel.insertRetrospecitveRecord(openRecord, timeRecord);
     703                WebInspector.TimelinePresentationModel.adoptRecord(openRecord, timeRecord);
    626704                break;
    627705            }
     
    684762}
    685763
    686 WebInspector.TimelinePresentationModel.insertRetrospecitveRecord = function(parent, record)
     764WebInspector.TimelinePresentationModel.adoptRecord = function(newParent, record)
     765{
     766    record.parent.children.splice(record.parent.children.indexOf(record));
     767    WebInspector.TimelinePresentationModel.insertRetrospectiveRecord(newParent, record);
     768    record.parent = newParent;
     769}
     770
     771WebInspector.TimelinePresentationModel.insertRetrospectiveRecord = function(parent, record)
    687772{
    688773    function compareStartTime(value, record)
     
    707792    get selfTime()
    708793    {
    709         return this._selfTime;
     794        return this.coalesced ? this._lastChildEndTime - this.startTime : this._selfTime;
    710795    },
    711796
     
    879964
    880965        if (this._children.length) {
    881             contentHelper.appendTextRow(WebInspector.UIString("Self Time"), Number.secondsToString(this._selfTime, true));
     966            if (!this.coalesced)
     967                contentHelper.appendTextRow(WebInspector.UIString("Self Time"), Number.secondsToString(this._selfTime, true));
    882968            contentHelper.appendTextRow(WebInspector.UIString("CPU Time"), Number.secondsToString(this._cpuTime, true));
    883969            contentHelper.appendElementRow(WebInspector.UIString("Aggregated Time"),
    884970                WebInspector.TimelinePresentationModel._generateAggregatedInfo(this._aggregatedStats));
     971        }
     972
     973        if (this.coalesced) {
     974            callback(contentHelper.contentTable());
     975            return;
    885976        }
    886977        const recordTypes = WebInspector.TimelineModel.RecordType;
     
    10231114    {
    10241115        var details;
     1116        if (this.coalesced)
     1117            return this._createSpanWithText(WebInspector.UIString("× %d", this.children.length));
     1118
    10251119        switch (this.type) {
    10261120        case WebInspector.TimelineModel.RecordType.GCEvent:
     
    10851179            return this._createSpanWithText("" + details);
    10861180
    1087         return details ? details : null;
     1181        return details || null;
    10881182    },
    10891183
     
    11291223    },
    11301224
    1131     calculateAggregatedStats: function(categories)
     1225    calculateAggregatedStats: function()
    11321226    {
    11331227        this._aggregatedStats = {};
    1134         for (var category in categories)
    1135             this._aggregatedStats[category] = 0;
    11361228        this._cpuTime = this._selfTime;
    11371229
    11381230        for (var index = this._children.length; index; --index) {
    11391231            var child = this._children[index - 1];
    1140             for (var category in categories)
    1141                 this._aggregatedStats[category] += child._aggregatedStats[category];
     1232            for (var category in child._aggregatedStats)
     1233                this._aggregatedStats[category] = (this._aggregatedStats[category] || 0) + child._aggregatedStats[category];
    11421234        }
    11431235        for (var category in this._aggregatedStats)
    11441236            this._cpuTime += this._aggregatedStats[category];
    1145         this._aggregatedStats[this.category.name] += this._selfTime;
     1237        this._aggregatedStats[this.category.name] = (this._aggregatedStats[this.category.name] || 0) + this._selfTime;
    11461238    },
    11471239
Note: See TracChangeset for help on using the changeset viewer.