Home | History | Annotate | Download | only in front_end
      1 /*
      2  * Copyright (C) 2012 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /**
     32  * @constructor
     33  * @param {WebInspector.TimelineModel} model
     34  * @param {WebInspector.TimelineOverviewPane} overviewPane
     35  * @param {WebInspector.TimelinePresentationModel} presentationModel
     36  */
     37 WebInspector.TimelineFrameController = function(model, overviewPane, presentationModel)
     38 {
     39     this._lastFrame = null;
     40     this._model = model;
     41     this._overviewPane = overviewPane;
     42     this._presentationModel = presentationModel;
     43     this._model.addEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onRecordAdded, this);
     44     this._model.addEventListener(WebInspector.TimelineModel.Events.RecordsCleared, this._onRecordsCleared, this);
     45 
     46     var records = model.records;
     47     for (var i = 0; i < records.length; ++i)
     48         this._addRecord(records[i]);
     49 }
     50 
     51 WebInspector.TimelineFrameController.prototype = {
     52     _onRecordAdded: function(event)
     53     {
     54         this._addRecord(event.data);
     55     },
     56 
     57     _onRecordsCleared: function()
     58     {
     59         this._lastFrame = null;
     60     },
     61 
     62     _addRecord: function(record)
     63     {
     64         if (record.isBackground)
     65             return;
     66         var records;
     67         var programRecord;
     68         if (record.type === WebInspector.TimelineModel.RecordType.Program) {
     69             programRecord = record;
     70             if (this._lastFrame)
     71                 this._lastFrame.timeByCategory["other"] += WebInspector.TimelineModel.durationInSeconds(programRecord);
     72             records = record["children"] || [];
     73         } else
     74             records = [record];
     75         records.forEach(this._innerAddRecord.bind(this, programRecord));
     76     },
     77 
     78     /**
     79      * @param {Object} programRecord
     80      * @param {Object} record
     81      */
     82     _innerAddRecord: function(programRecord, record)
     83     {
     84         var isFrameRecord = record.type === WebInspector.TimelineModel.RecordType.BeginFrame;
     85         var programTimeCarryover = isFrameRecord && programRecord ? WebInspector.TimelineModel.endTimeInSeconds(programRecord) - WebInspector.TimelineModel.startTimeInSeconds(record) : 0;
     86         if (isFrameRecord && this._lastFrame)
     87             this._flushFrame(record, programTimeCarryover);
     88         else {
     89             if (!this._lastFrame)
     90                 this._lastFrame = this._createFrame(record, programTimeCarryover);
     91             if (!record.thread)
     92                 WebInspector.TimelineModel.aggregateTimeForRecord(this._lastFrame.timeByCategory, record);
     93             var duration = WebInspector.TimelineModel.durationInSeconds(record);
     94             this._lastFrame.cpuTime += duration;
     95             this._lastFrame.timeByCategory["other"] -= duration;
     96         }
     97     },
     98 
     99     /**
    100      * @param {Object} record
    101      * @param {number} programTimeCarryover
    102      */
    103     _flushFrame: function(record, programTimeCarryover)
    104     {
    105         this._lastFrame.endTime = WebInspector.TimelineModel.startTimeInSeconds(record);
    106         this._lastFrame.duration = this._lastFrame.endTime - this._lastFrame.startTime;
    107         this._lastFrame.timeByCategory["other"] -= programTimeCarryover;
    108         // Alternatively, we could compute CPU time as sum of all Program events.
    109         // This way it's a bit more flexible, as it works in case there's no program events.
    110         this._lastFrame.cpuTime += this._lastFrame.timeByCategory["other"];
    111         this._overviewPane.addFrame(this._lastFrame);
    112         this._presentationModel.addFrame(this._lastFrame);
    113         this._lastFrame = this._createFrame(record, programTimeCarryover);
    114     },
    115 
    116     /**
    117      * @param {Object} record
    118      * @param {number} programTimeCarryover
    119      */
    120     _createFrame: function(record, programTimeCarryover)
    121     {
    122         var frame = new WebInspector.TimelineFrame();
    123         frame.startTime = WebInspector.TimelineModel.startTimeInSeconds(record);
    124         frame.startTimeOffset = this._model.recordOffsetInSeconds(record);
    125         frame.timeByCategory["other"] = programTimeCarryover;
    126         return frame;
    127     },
    128 
    129     dispose: function()
    130     {
    131         this._model.removeEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onRecordAdded, this);
    132         this._model.removeEventListener(WebInspector.TimelineModel.Events.RecordsCleared, this._onRecordsCleared, this);
    133     }
    134 }
    135 
    136 /**
    137  * @constructor
    138  * @param {Array.<WebInspector.TimelineFrame>} frames
    139  */
    140 WebInspector.FrameStatistics = function(frames)
    141 {
    142     this.frameCount = frames.length;
    143     this.minDuration = Infinity;
    144     this.maxDuration = 0;
    145     this.timeByCategory = {};
    146     this.startOffset = frames[0].startTimeOffset;
    147     var lastFrame = frames[this.frameCount - 1];
    148     this.endOffset = lastFrame.startTimeOffset + lastFrame.duration;
    149 
    150     var totalDuration = 0;
    151     var sumOfSquares = 0;
    152     for (var i = 0; i < this.frameCount; ++i) {
    153         var duration = frames[i].duration;
    154         totalDuration += duration;
    155         sumOfSquares += duration * duration;
    156         this.minDuration = Math.min(this.minDuration, duration);
    157         this.maxDuration = Math.max(this.maxDuration, duration);
    158         WebInspector.TimelineModel.aggregateTimeByCategory(this.timeByCategory, frames[i].timeByCategory);
    159     }
    160     this.average = totalDuration / this.frameCount;
    161     var variance = sumOfSquares / this.frameCount - this.average * this.average;
    162     this.stddev = Math.sqrt(variance);
    163 }
    164 
    165 /**
    166  * @constructor
    167  */
    168 WebInspector.TimelineFrame = function()
    169 {
    170     this.timeByCategory = {};
    171     this.cpuTime = 0;
    172 }
    173