Home | History | Annotate | Download | only in timeline
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 
      6 WebInspector.TimelineJSProfileProcessor = { };
      7 
      8 /**
      9  * @param {!WebInspector.TimelineModelImpl} timelineModel
     10  * @param {!ProfilerAgent.CPUProfile} jsProfile
     11  */
     12 WebInspector.TimelineJSProfileProcessor.mergeJSProfileIntoTimeline = function(timelineModel, jsProfile)
     13 {
     14     if (!jsProfile.samples)
     15         return;
     16     var jsProfileModel = new WebInspector.CPUProfileDataModel(jsProfile);
     17     var idleNode = jsProfileModel.idleNode;
     18     var programNode = jsProfileModel.programNode;
     19     var gcNode = jsProfileModel.gcNode;
     20 
     21     /**
     22      * @param {!WebInspector.TimelineModel.Record} record
     23      */
     24     function processRecord(record)
     25     {
     26         if (record.type() !== WebInspector.TimelineModel.RecordType.FunctionCall &&
     27             record.type() !== WebInspector.TimelineModel.RecordType.EvaluateScript)
     28             return;
     29         var recordStartTime = record.startTime();
     30         var recordEndTime = record.endTime();
     31         var originalChildren = record.children().splice(0);
     32         var childIndex = 0;
     33 
     34         /**
     35          * @param {number} depth
     36          * @param {!ProfilerAgent.CPUProfileNode} node
     37          * @param {number} startTime
     38          */
     39         function onOpenFrame(depth, node, startTime)
     40         {
     41             if (node === idleNode || node === programNode || node === gcNode)
     42                 return;
     43             var event = {
     44                 type: "JSFrame",
     45                 data: node,
     46                 startTime: startTime
     47             };
     48             putOriginalChildrenUpToTime(startTime);
     49             record = new WebInspector.TimelineModel.RecordImpl(timelineModel, event, record);
     50         }
     51 
     52         /**
     53          * @param {number} depth
     54          * @param {!ProfilerAgent.CPUProfileNode} node
     55          * @param {number} startTime
     56          * @param {number} totalTime
     57          * @param {number} selfTime
     58          */
     59         function onCloseFrame(depth, node, startTime, totalTime, selfTime)
     60         {
     61             if (node === idleNode || node === programNode || node === gcNode)
     62                 return;
     63             record.setEndTime(Math.min(startTime + totalTime, recordEndTime));
     64             record._selfTime = record.endTime() - record.startTime();
     65             putOriginalChildrenUpToTime(record.endTime());
     66             var deoptReason = node.deoptReason;
     67             if (deoptReason && deoptReason !== "no reason")
     68                 record.addWarning(deoptReason);
     69             record = record.parent;
     70         }
     71 
     72         /**
     73          * @param {number} endTime
     74          */
     75         function putOriginalChildrenUpToTime(endTime)
     76         {
     77             for (; childIndex < originalChildren.length; ++childIndex)  {
     78                 var child = originalChildren[childIndex];
     79                 var midTime = (child.startTime() + child.endTime()) / 2;
     80                 if (midTime >= endTime)
     81                     break;
     82                 child.parent = record;
     83                 record.children().push(child);
     84             }
     85         }
     86 
     87         jsProfileModel.forEachFrame(onOpenFrame, onCloseFrame, recordStartTime, recordEndTime);
     88         putOriginalChildrenUpToTime(recordEndTime);
     89     }
     90 
     91     timelineModel.forAllRecords(processRecord);
     92 }
     93 
     94 /**
     95  * @param {!WebInspector.TracingTimelineModel} timelineModel
     96  * @param {!ProfilerAgent.CPUProfile} jsProfile
     97  * @return {!Array.<!WebInspector.TracingModel.Event>}
     98  */
     99 WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile = function(timelineModel, jsProfile)
    100 {
    101     if (!jsProfile.samples)
    102         return [];
    103     var jsProfileModel = new WebInspector.CPUProfileDataModel(jsProfile);
    104     var idleNode = jsProfileModel.idleNode;
    105     var programNode = jsProfileModel.programNode;
    106     var gcNode = jsProfileModel.gcNode;
    107     var samples = jsProfileModel.samples;
    108     var timestamps = jsProfileModel.timestamps;
    109     var jsEvents = [];
    110     var mainThread = timelineModel.mainThreadEvents()[0].thread;
    111     for (var i = 0; i < samples.length; ++i) {
    112         var node = jsProfileModel.nodeByIndex(i);
    113         if (node === programNode || node === gcNode || node === idleNode)
    114             continue;
    115         var stackTrace = node._stackTraceArray;
    116         if (!stackTrace) {
    117             stackTrace = /** @type {!ConsoleAgent.StackTrace} */ (new Array(node.depth + 1));
    118             node._stackTraceArray = stackTrace;
    119             for (var j = 0; node.parent; node = node.parent)
    120                 stackTrace[j++] = /** @type {!ConsoleAgent.CallFrame} */ (node);
    121         }
    122         var jsEvent = new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsMetadataEventCategory, WebInspector.TracingTimelineModel.RecordType.JSSample,
    123             WebInspector.TracingModel.Phase.Instant, timestamps[i], mainThread);
    124         jsEvent.stackTrace = stackTrace;
    125         jsEvents.push(jsEvent);
    126     }
    127     return jsEvents;
    128 }
    129