/**
* @param {!Array.<*>} recordsArray
- * @param {?function(*)} preOrderCallback
- * @param {function(*)=} postOrderCallback
+ * @param {?function(*)|?function(*,number)} preOrderCallback
+ * @param {function(*)|function(*,number)=} postOrderCallback
*/
WebInspector.TimelinePresentationModel.forAllRecords = function(recordsArray, preOrderCallback, postOrderCallback)
{
var records = entry.array;
if (entry.index < records.length) {
var record = records[entry.index];
- if (preOrderCallback && preOrderCallback(record))
+ if (preOrderCallback && preOrderCallback(record, stack.length))
return;
if (record.children)
stack.push({array: record.children, index: 0, record: record});
- else if (postOrderCallback && postOrderCallback(record))
+ else if (postOrderCallback && postOrderCallback(record, stack.length))
return;
++entry.index;
} else {
- if (entry.record && postOrderCallback && postOrderCallback(entry.record))
+ if (entry.record && postOrderCallback && postOrderCallback(entry.record, stack.length))
return;
stack.pop();
}
WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.MarkDOMContent] = 1;
WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.MarkLoad] = 1;
WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.MarkFirstPaint] = 1;
+WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.GPUTask] = 1;
WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.ScheduleStyleRecalculation] = 1;
WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.InvalidateLayout] = 1;
-WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.GPUTask] = 1;
+WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.RequestMainThreadFrame] = 1;
WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.ActivateLayerTree] = 1;
+WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.DrawFrame] = 1;
+WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel.RecordType.BeginFrame] = 1;
WebInspector.TimelinePresentationModel.prototype = {
/**
return this._rootRecord;
},
- /**
- * @return {!Array.<!WebInspector.TimelinePresentationModel.Record>}
- */
- frames: function()
- {
- return this._frames;
- },
-
reset: function()
{
this._linkifier.reset();
this._eventDividerRecords = [];
this._timeRecords = {};
this._timeRecordStack = [];
- this._frames = [];
this._minimumRecordTime = -1;
this._layoutInvalidateStack = {};
this._lastScheduleStyleRecalculation = {};
this._webSocketCreateRecords = {};
this._coalescingBuckets = {};
- },
-
- /**
- * @param {!WebInspector.TimelineFrame} frame
- */
- addFrame: function(frame)
- {
- if (!frame.isBackground)
- this._frames.push(frame);
+ this._mergingBuffer = new WebInspector.TimelineMergingRecordBuffer();
},
/**
{
if (this._minimumRecordTime === -1 || record.startTime < this._minimumRecordTime)
this._minimumRecordTime = WebInspector.TimelineModel.startTimeInSeconds(record);
-
var records;
if (record.type === WebInspector.TimelineModel.RecordType.Program)
records = this._foldSyncTimeRecords(record.children || []);
else
records = [record];
- var result = Array(records.length);
- for (var i = 0; i < records.length; ++i)
- result[i] = this._innerAddRecord(this._rootRecord, records[i]);
+ var mergedRecords = this._mergingBuffer.process(record.thread, records);
+ var result = new Array(mergedRecords.length);
+ for (var i = 0; i < mergedRecords.length; ++i)
+ result[i] = this._innerAddRecord(this._rootRecord, mergedRecords[i]);
return result;
},
},
/**
- * @param {number} startTime
- * @param {number} endTime
- * @return {!Array.<!WebInspector.TimelinePresentationModel.Record>}
- */
- filteredFrames: function(startTime, endTime)
- {
- function compareStartTime(value, object)
- {
- return value - object.startTime;
- }
- function compareEndTime(value, object)
- {
- return value - object.endTime;
- }
- var firstFrame = insertionIndexForObjectInListSortedByFunction(startTime, this._frames, compareStartTime);
- var lastFrame = insertionIndexForObjectInListSortedByFunction(endTime, this._frames, compareEndTime);
- while (lastFrame < this._frames.length && this._frames[lastFrame].endTime <= endTime)
- ++lastFrame;
- return this._frames.slice(firstFrame, lastFrame);
- },
-
- /**
* @return {!Array.<!WebInspector.TimelinePresentationModel.Record>}
*/
eventDividerRecords: function()
this._children = [];
if (!hidden && parentRecord) {
this.parent = parentRecord;
- if (this.isBackground)
- WebInspector.TimelinePresentationModel.insertRetrospectiveRecord(parentRecord, this);
- else
- parentRecord.children.push(this);
+ parentRecord.children.push(this);
}
if (origin)
this._origin = origin;
/**
* @return {boolean}
*/
- get isBackground()
+ isBackground: function()
{
return !!this._record.thread;
},
_generatePopupContentSynchronously: function()
{
var fragment = document.createDocumentFragment();
- var pie = WebInspector.TimelinePresentationModel.generatePieChart(this._aggregatedStats, this.category.name);
- // Insert self time.
- if (!this.coalesced && this._children.length) {
- pie.pieChart.addSlice(this._selfTime, this.category.fillColorStop1);
- var rowElement = document.createElement("div");
- pie.footerElement.insertBefore(rowElement, pie.footerElement.firstChild);
- rowElement.createChild("div", "timeline-aggregated-category timeline-" + this.category.name);
- rowElement.createTextChild(WebInspector.UIString("%s %s (Self)", Number.secondsToString(this._selfTime, true), this.category.title));
- }
- fragment.appendChild(pie.element);
-
- var contentHelper = new WebInspector.TimelineDetailsContentHelper(true);
- contentHelper.appendTextRow(WebInspector.UIString("Started at"), Number.secondsToString(this._startTimeOffset));
+ if (!this.coalesced && this._children.length)
+ fragment.appendChild(WebInspector.TimelinePresentationModel.generatePieChart(this._aggregatedStats, this.category, this._selfTime));
+ else
+ fragment.appendChild(WebInspector.TimelinePresentationModel.generatePieChart(this._aggregatedStats));
if (this.coalesced)
return fragment;
var callStackLabel;
var relatedNodeLabel;
+ var contentHelper = new WebInspector.TimelineDetailsContentHelper(true);
+ contentHelper.appendTextRow(WebInspector.UIString("Self Time"), Number.secondsToString(this._selfTime, true));
+ contentHelper.appendTextRow(WebInspector.UIString("Start Time"), Number.secondsToString(this._startTimeOffset));
+
switch (this.type) {
case recordTypes.GCEvent:
contentHelper.appendTextRow(WebInspector.UIString("Collected"), Number.bytesToString(this.data["usedHeapSizeDelta"]));
{
var span = document.createElement("span");
span.classList.add("node-link");
- span.addEventListener("click", node.reveal.bind(node), false);
+ span.addEventListener("click", WebInspector.Revealer.reveal.bind(WebInspector.Revealer, node, undefined), false);
WebInspector.DOMPresentationUtils.decorateNodeLabel(node, span);
return span;
},
/**
* @param {!Object} aggregatedStats
- * @param {string=} firstCategoryName
- * @return {!{pieChart: !WebInspector.PieChart, element: !Element, footerElement: !Element}}
+ * @param {!WebInspector.TimelineCategory=} selfCategory
+ * @param {number=} selfTime
+ * @return {!Element}
*/
-WebInspector.TimelinePresentationModel.generatePieChart = function(aggregatedStats, firstCategoryName)
+WebInspector.TimelinePresentationModel.generatePieChart = function(aggregatedStats, selfCategory, selfTime)
{
var element = document.createElement("div");
element.className = "timeline-aggregated-info";
var total = 0;
- var categoryNames = [];
- if (firstCategoryName)
- categoryNames.push(firstCategoryName);
- for (var categoryName in WebInspector.TimelinePresentationModel.categories()) {
- if (aggregatedStats[categoryName]) {
- total += aggregatedStats[categoryName];
- if (firstCategoryName !== categoryName)
- categoryNames.push(categoryName);
- }
- }
+ for (var categoryName in aggregatedStats)
+ total += aggregatedStats[categoryName];
var pieChart = new WebInspector.PieChart(total);
element.appendChild(pieChart.element);
var footerElement = element.createChild("div", "timeline-aggregated-info-legend");
- for (var i = 0; i < categoryNames.length; ++i) {
- var category = WebInspector.TimelinePresentationModel.categories()[categoryNames[i]];
- pieChart.addSlice(aggregatedStats[category.name], category.fillColorStop0);
+ // In case of self time, first add self, then children of the same category.
+ if (selfCategory && selfTime) {
+ // Self.
+ pieChart.addSlice(selfTime, selfCategory.fillColorStop1);
var rowElement = footerElement.createChild("div");
- rowElement.createChild("div", "timeline-aggregated-category timeline-" + category.name);
- rowElement.createTextChild(WebInspector.UIString("%s %s", Number.secondsToString(aggregatedStats[category.name], true), category.title));
+ rowElement.createChild("div", "timeline-aggregated-category timeline-" + selfCategory.name);
+ rowElement.createTextChild(WebInspector.UIString("%s %s (Self)", Number.secondsToString(selfTime, true), selfCategory.title));
+
+ // Children of the same category.
+ var categoryTime = aggregatedStats[selfCategory.name];
+ var value = categoryTime - selfTime;
+ if (value > 0) {
+ pieChart.addSlice(value, selfCategory.fillColorStop0);
+ rowElement = footerElement.createChild("div");
+ rowElement.createChild("div", "timeline-aggregated-category timeline-" + selfCategory.name);
+ rowElement.createTextChild(WebInspector.UIString("%s %s (Children)", Number.secondsToString(value, true), selfCategory.title));
+ }
+ }
+
+ // Add other categories.
+ for (var categoryName in WebInspector.TimelinePresentationModel.categories()) {
+ var category = WebInspector.TimelinePresentationModel.categories()[categoryName];
+ if (category === selfCategory)
+ continue;
+ var value = aggregatedStats[category.name];
+ if (!value)
+ continue;
+ pieChart.addSlice(value, category.fillColorStop0);
+ var rowElement = footerElement.createChild("div");
+ rowElement.createChild("div", "timeline-aggregated-category timeline-" + category.name);
+ rowElement.createTextChild(WebInspector.UIString("%s %s", Number.secondsToString(value, true), category.title));
}
- return { pieChart: pieChart, element: element, footerElement: footerElement };
+ return element;
}
WebInspector.TimelinePresentationModel.generatePopupContentForFrame = function(frame)
contentHelper.appendTextRow(WebInspector.UIString("Duration"), durationText);
contentHelper.appendTextRow(WebInspector.UIString("FPS"), Math.floor(1 / durationInSeconds));
contentHelper.appendTextRow(WebInspector.UIString("CPU time"), Number.secondsToString(frame.cpuTime, true));
- contentHelper.appendTextRow(WebInspector.UIString("Thread"), frame.isBackground ? WebInspector.UIString("background") : WebInspector.UIString("main"));
contentHelper.appendElementRow(WebInspector.UIString("Aggregated Time"),
WebInspector.TimelinePresentationModel._generateAggregatedInfo(frame.timeByCategory));
return contentHelper.contentTable();
".timeline-details-view .timeline-" + category.name + ", " +
".timeline-category-" + category.name + " .timeline-tree-icon"
- return selector + " { background-image: -webkit-linear-gradient(" +
+ return selector + " { background-image: linear-gradient(" +
category.fillColorStop0 + ", " + category.fillColorStop1 + " 25%, " + category.fillColorStop1 + " 25%, " + category.fillColorStop1 + ");" +
" border-color: " + category.borderColor +
"}";