Home | History | Annotate | Download | only in mappers
      1 <!DOCTYPE html>
      2 <!--
      3 Copyright (c) 2015 The Chromium Authors. All rights reserved.
      4 Use of this source code is governed by a BSD-style license that can be
      5 found in the LICENSE file.
      6 -->
      7 <link rel="import" href="/experimental/mappers/reduce.html">
      8 <link rel="import" href="/tracing/extras/ads/domain_category.html">
      9 <link rel="import" href="/tracing/extras/chrome/slice_title_fixer.html">
     10 <link rel="import" href="/tracing/model/source_info/js_source_info.html">
     11 
     12 <script>
     13 'use strict';
     14 
     15 tr.exportTo('pi.m', function() {
     16   var JSSourceState = tr.model.source_info.JSSourceState;
     17 
     18   function SliceCostInfo() {
     19     this.threadGroup = undefined;
     20     this.railTypeName = undefined;
     21     this.title = undefined;
     22     this.domainCategory = undefined;
     23     this.domain = undefined;
     24     this.userFriendlyCategory = undefined;
     25 
     26     this.selfTime = 0;
     27     this.cpuSelfTime = 0;
     28 
     29     this.jsTime = 0;
     30     this.jsTimeByState = {};
     31     for (var state in JSSourceState) {
     32       this.jsTimeByState[JSSourceState[state]] = 0;
     33     }
     34     this.data = {};
     35   }
     36 
     37   SliceCostInfo.asReduceTarget = function(key, firstValue) {
     38     var sliceCostInfo = new SliceCostInfo();
     39     sliceCostInfo.threadGroup = firstValue.threadGroup;
     40     sliceCostInfo.railTypeName = firstValue.railTypeName;
     41     sliceCostInfo.title = firstValue.title;
     42     sliceCostInfo.domainCategory = firstValue.domainCategory;
     43     sliceCostInfo.domain = firstValue.domain;
     44     sliceCostInfo.userFriendlyCategory = firstValue.userFriendlyCategory;
     45     sliceCostInfo.data = firstValue.data;
     46     return sliceCostInfo;
     47   };
     48 
     49   SliceCostInfo.fromDict = function(d) {
     50     var sliceCostInfo = new SliceCostInfo();
     51     sliceCostInfo.threadGroup = d.threadGroup;
     52     sliceCostInfo.railTypeName = d.railTypeName;
     53     sliceCostInfo.title = d.title;
     54     sliceCostInfo.domainCategory = d.domainCategory;
     55     sliceCostInfo.domain = d.domain;
     56     sliceCostInfo.userFriendlyCategory = d.userFriendlyCategory;
     57     sliceCostInfo.selfTime = d.selfTime;
     58     sliceCostInfo.cpuSelfTime = d.cpuSelfTime;
     59     sliceCostInfo.jsTime = d.jsTime || 0;
     60     for (var state in JSSourceState) {
     61       if (d.jsTimeByState === undefined) {
     62         sliceCostInfo.jsTimeByState[state] = 0;
     63       } else {
     64         sliceCostInfo.jsTimeByState[JSSourceState[state]] =
     65             d.jsTimeByState[JSSourceState[state]] || 0;
     66       }
     67     }
     68     sliceCostInfo.data = d.data;
     69     return sliceCostInfo;
     70   };
     71 
     72   SliceCostInfo.prototype = {
     73     push: function(sliceCostKey, threadSlice) {
     74       if (threadSlice.selfTime !== undefined)
     75         this.selfTime += threadSlice.selfTime;
     76       if (threadSlice.cpuSelfTime !== undefined)
     77         this.cpuSelfTime += threadSlice.cpuSelfTime;
     78       if (threadSlice.jsTime !== undefined)
     79         this.jsTime += threadSlice.jsTime;
     80       if (threadSlice.jsTimeByState !== undefined) {
     81         for (var state in JSSourceState) {
     82           this.jsTimeByState[JSSourceState[state]] +=
     83               threadSlice.jsTimeByState[JSSourceState[state]];
     84         }
     85       }
     86     },
     87 
     88     finalizeAndGetResult: function() {
     89       return this;
     90     }
     91   };
     92 
     93 
     94   function getSliceCostReport(model, threadGrouping, railTypeNameByGUID,
     95       filterFunction, dataCB) {
     96     var reduce = new pi.m.StreamingReducer(SliceCostInfo.asReduceTarget);
     97 
     98     function generateDomainCosts(slice) {
     99       // V8.Execute events may generate several sliceCostInfo, based on the
    100       // origin of the JS being executed.
    101       var range = new tr.b.Range();
    102       slice.addBoundsToRange(range);
    103       var filtered = range.filterArray(
    104           slice.parentContainer.samples,
    105           function(sample) {return sample.start;});
    106       filtered.forEach(function(sample) {
    107         var sliceCostInfo = new SliceCostInfo();
    108         sliceCostInfo.threadGroup = threadGrouping.getGroupNameForEvent(slice);
    109         sliceCostInfo.railTypeName = railTypeNameByGUID[slice.guid];
    110 
    111         var ufc = model.getUserFriendlyCategoryFromEvent(slice);
    112         sliceCostInfo.userFriendlyCategory = ufc || 'other';
    113         sliceCostInfo.title = tr.e.chrome.SliceTitleFixer.fromEvent(slice);
    114         sliceCostInfo.domain = sample.leafStackFrame.domain;
    115         sliceCostInfo.domainCategory =
    116             tr.e.ads.DomainCategory.fromDomain(sliceCostInfo.domain);
    117         sliceCostInfo.selfTime = sample.weight;
    118         sliceCostInfo.cpuSelfTime = sample.weight;
    119         if (dataCB !== undefined)
    120           sliceCostInfo.data = dataCB(slice);
    121         // Let's use the state of the leaf frame. TODO(chiniforooshan):
    122         // understand what it means if frames of a sample stack are in different
    123         // states (BUG #1542).
    124         var sourceInfo = sample.leafStackFrame.sourceInfo;
    125         if (sourceInfo === undefined ||
    126             !(sourceInfo instanceof tr.model.source_info.JSSourceInfo)) {
    127           sliceCostInfo.jsTime = sample.weight;
    128           sliceCostInfo.jsTimeByState[JSSourceState.UNKNOWN] = sample.weight;
    129         } else {
    130           sliceCostInfo.jsTimeByState[sourceInfo.state] = sample.weight;
    131         }
    132         var key = sliceCostInfo.threadGroup + '/' +
    133                   sliceCostInfo.railTypeName + '/' +
    134                   sliceCostInfo.title + '/' +
    135                   sliceCostInfo.domain;
    136         reduce.push(key, sliceCostInfo);
    137       });
    138     }
    139 
    140     for (var event of model.descendentEvents()) {
    141       if (!(event instanceof tr.model.ThreadSlice))
    142         continue;
    143       if (filterFunction && !filterFunction(event))
    144         continue;
    145 
    146       var threadSlice = event;
    147       if (threadSlice.title === 'V8.Execute') {
    148         generateDomainCosts(threadSlice);
    149         continue;
    150       }
    151 
    152       var sliceCostInfo = new SliceCostInfo();
    153       sliceCostInfo.threadGroup = threadGrouping.getGroupNameForEvent(
    154           threadSlice);
    155       sliceCostInfo.railTypeName = railTypeNameByGUID[threadSlice.guid];
    156       var ufc = model.getUserFriendlyCategoryFromEvent(threadSlice);
    157       sliceCostInfo.userFriendlyCategory = ufc || 'other';
    158       sliceCostInfo.title = tr.e.chrome.SliceTitleFixer.fromEvent(threadSlice);
    159       // For all other events, just generate one sliceCostInfo.
    160       sliceCostInfo.selfTime = threadSlice.selfTime;
    161       sliceCostInfo.cpuSelfTime = threadSlice.cpuSelfTime;
    162       if (dataCB !== undefined)
    163         sliceCostInfo.data = dataCB(event);
    164 
    165       var key = sliceCostInfo.threadGroup + '/' +
    166                 sliceCostInfo.railTypeName + '/' +
    167                 sliceCostInfo.title;
    168       reduce.push(key, sliceCostInfo);
    169     }
    170 
    171     var sliceCostInfos = [];
    172     reduce.finalizeAndIterResults(function(key, sliceCostInfo) {
    173       sliceCostInfos.push(sliceCostInfo);
    174     });
    175     return sliceCostInfos;
    176   }
    177 
    178   tr.mre.FunctionRegistry.register(getSliceCostReport);
    179 
    180   return {
    181     SliceCostInfo: SliceCostInfo,
    182 
    183     getSliceCostReport: getSliceCostReport
    184   };
    185 });
    186 </script>
    187