TimelineFrameController.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. * @constructor
  32. * @param {WebInspector.TimelineModel} model
  33. * @param {WebInspector.TimelineOverviewPane} overviewPane
  34. * @param {WebInspector.TimelinePresentationModel} presentationModel
  35. */
  36. WebInspector.TimelineFrameController = function(model, overviewPane, presentationModel)
  37. {
  38. this._lastFrame = null;
  39. this._model = model;
  40. this._overviewPane = overviewPane;
  41. this._presentationModel = presentationModel;
  42. this._model.addEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onRecordAdded, this);
  43. this._model.addEventListener(WebInspector.TimelineModel.Events.RecordsCleared, this._onRecordsCleared, this);
  44. var records = model.records;
  45. for (var i = 0; i < records.length; ++i)
  46. this._addRecord(records[i]);
  47. }
  48. WebInspector.TimelineFrameController.prototype = {
  49. _onRecordAdded: function(event)
  50. {
  51. this._addRecord(event.data);
  52. },
  53. _onRecordsCleared: function()
  54. {
  55. this._lastFrame = null;
  56. },
  57. _addRecord: function(record)
  58. {
  59. if (record.isBackground)
  60. return;
  61. var records;
  62. var programRecord;
  63. if (record.type === WebInspector.TimelineModel.RecordType.Program) {
  64. programRecord = record;
  65. if (this._lastFrame)
  66. this._lastFrame.timeByCategory["other"] += WebInspector.TimelineModel.durationInSeconds(programRecord);
  67. records = record["children"] || [];
  68. } else
  69. records = [record];
  70. records.forEach(this._innerAddRecord.bind(this, programRecord));
  71. },
  72. /**
  73. * @param {Object} programRecord
  74. * @param {Object} record
  75. */
  76. _innerAddRecord: function(programRecord, record)
  77. {
  78. var isFrameRecord = record.type === WebInspector.TimelineModel.RecordType.BeginFrame;
  79. var programTimeCarryover = isFrameRecord && programRecord ? WebInspector.TimelineModel.endTimeInSeconds(programRecord) - WebInspector.TimelineModel.startTimeInSeconds(record) : 0;
  80. if (isFrameRecord && this._lastFrame)
  81. this._flushFrame(record, programTimeCarryover);
  82. else {
  83. if (!this._lastFrame)
  84. this._lastFrame = this._createFrame(record, programTimeCarryover);
  85. if (!record.thread)
  86. WebInspector.TimelineModel.aggregateTimeForRecord(this._lastFrame.timeByCategory, record);
  87. var duration = WebInspector.TimelineModel.durationInSeconds(record);
  88. this._lastFrame.cpuTime += duration;
  89. this._lastFrame.timeByCategory["other"] -= duration;
  90. }
  91. },
  92. /**
  93. * @param {Object} record
  94. * @param {number} programTimeCarryover
  95. */
  96. _flushFrame: function(record, programTimeCarryover)
  97. {
  98. this._lastFrame.endTime = WebInspector.TimelineModel.startTimeInSeconds(record);
  99. this._lastFrame.duration = this._lastFrame.endTime - this._lastFrame.startTime;
  100. this._lastFrame.timeByCategory["other"] -= programTimeCarryover;
  101. // Alternatively, we could compute CPU time as sum of all Program events.
  102. // This way it's a bit more flexible, as it works in case there's no program events.
  103. this._lastFrame.cpuTime += this._lastFrame.timeByCategory["other"];
  104. this._overviewPane.addFrame(this._lastFrame);
  105. this._presentationModel.addFrame(this._lastFrame);
  106. this._lastFrame = this._createFrame(record, programTimeCarryover);
  107. },
  108. /**
  109. * @param {Object} record
  110. * @param {number} programTimeCarryover
  111. */
  112. _createFrame: function(record, programTimeCarryover)
  113. {
  114. var frame = new WebInspector.TimelineFrame();
  115. frame.startTime = WebInspector.TimelineModel.startTimeInSeconds(record);
  116. frame.startTimeOffset = this._model.recordOffsetInSeconds(record);
  117. frame.timeByCategory["other"] = programTimeCarryover;
  118. return frame;
  119. },
  120. dispose: function()
  121. {
  122. this._model.removeEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onRecordAdded, this);
  123. this._model.removeEventListener(WebInspector.TimelineModel.Events.RecordsCleared, this._onRecordsCleared, this);
  124. }
  125. }
  126. /**
  127. * @constructor
  128. * @param {Array.<WebInspector.TimelineFrame>} frames
  129. */
  130. WebInspector.FrameStatistics = function(frames)
  131. {
  132. this.frameCount = frames.length;
  133. this.minDuration = Infinity;
  134. this.maxDuration = 0;
  135. this.timeByCategory = {};
  136. this.startOffset = frames[0].startTimeOffset;
  137. var lastFrame = frames[this.frameCount - 1];
  138. this.endOffset = lastFrame.startTimeOffset + lastFrame.duration;
  139. var totalDuration = 0;
  140. var sumOfSquares = 0;
  141. for (var i = 0; i < this.frameCount; ++i) {
  142. var duration = frames[i].duration;
  143. totalDuration += duration;
  144. sumOfSquares += duration * duration;
  145. this.minDuration = Math.min(this.minDuration, duration);
  146. this.maxDuration = Math.max(this.maxDuration, duration);
  147. WebInspector.TimelineModel.aggregateTimeByCategory(this.timeByCategory, frames[i].timeByCategory);
  148. }
  149. this.average = totalDuration / this.frameCount;
  150. var variance = sumOfSquares / this.frameCount - this.average * this.average;
  151. this.stddev = Math.sqrt(variance);
  152. }
  153. /**
  154. * @constructor
  155. */
  156. WebInspector.TimelineFrame = function()
  157. {
  158. this.timeByCategory = {};
  159. this.cpuTime = 0;
  160. }