Home | History | Annotate | Download | only in analysis
      1 // Copyright (c) 2013 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 'use strict';
      6 
      7 base.requireStylesheet('tracing.analysis.analyze_slices');
      8 
      9 base.require('tracing.analysis.util');
     10 base.require('ui');
     11 base.exportTo('tracing.analysis', function() {
     12 
     13   function analyzeSingleSliceHit(results, sliceHit) {
     14     var slice = sliceHit.slice;
     15     var table = results.appendTable('analysis-slice-table', 2);
     16 
     17     results.appendTableHeader(table, 'Selected slice:');
     18     results.appendSummaryRow(table, 'Title', slice.title);
     19 
     20     if (slice.category)
     21       results.appendSummaryRow(table, 'Category', slice.category);
     22 
     23     results.appendSummaryRowTime(table, 'Start', slice.start);
     24     results.appendSummaryRowTime(table, 'Duration', slice.duration);
     25 
     26     if (slice.durationInUserTime) {
     27       results.appendSummaryRowTime(
     28           table, 'Duration (U)', slice.durationInUserTime);
     29     }
     30 
     31     var n = 0;
     32     for (var argName in slice.args) {
     33       n += 1;
     34     }
     35     if (n > 0) {
     36       results.appendSummaryRow(table, 'Args');
     37       for (var argName in slice.args) {
     38         var argVal = slice.args[argName];
     39         // TODO(sleffler) use span instead?
     40         results.appendSummaryRow(table, ' ' + argName, argVal);
     41       }
     42     }
     43   }
     44 
     45   function analyzeMultipleSliceHits(results, sliceHits) {
     46     var tsLo = sliceHits.bounds.min;
     47     var tsHi = sliceHits.bounds.max;
     48 
     49     // compute total sliceHits duration
     50     var titles = sliceHits.map(function(i) { return i.slice.title; });
     51 
     52     var numTitles = 0;
     53     var sliceHitsByTitle = {};
     54     for (var i = 0; i < sliceHits.length; i++) {
     55       var slice = sliceHits[i].slice;
     56       if (!sliceHitsByTitle[slice.title]) {
     57         sliceHitsByTitle[slice.title] = {
     58           hits: []
     59         };
     60         numTitles++;
     61       }
     62       var sliceGroup = sliceHitsByTitle[slice.title];
     63       sliceGroup.hits.push(sliceHits[i]);
     64     }
     65 
     66     var table;
     67     table = results.appendTable('analysis-slices-table', 3);
     68     results.appendTableHeader(table, 'Slices:');
     69 
     70     var totalDuration = 0;
     71     base.iterItems(sliceHitsByTitle,
     72         function(sliceHitGroupTitle, sliceHitGroup) {
     73           var duration = 0;
     74           var avg = 0;
     75           var startOfFirstOccurrence = Number.MAX_VALUE;
     76           var startOfLastOccurrence = -Number.MAX_VALUE;
     77           var frequencyDetails = undefined;
     78           var min = Number.MAX_VALUE;
     79           var max = -Number.MAX_VALUE;
     80           for (var i = 0; i < sliceHitGroup.hits.length; i++) {
     81             var slice = sliceHitGroup.hits[i].slice;
     82             duration += slice.duration;
     83             startOfFirstOccurrence = Math.min(slice.start,
     84                 startOfFirstOccurrence);
     85             startOfLastOccurrence = Math.max(slice.start,
     86                 startOfLastOccurrence);
     87             min = Math.min(slice.duration, min);
     88             max = Math.max(slice.duration, max);
     89           }
     90 
     91           totalDuration += duration;
     92 
     93           if (sliceHitGroup.hits.length == 0)
     94             avg = 0;
     95           avg = duration / sliceHitGroup.hits.length;
     96 
     97           var statistics = {min: min,
     98             max: max,
     99             avg: avg,
    100             avg_stddev: undefined,
    101             frequency: undefined,
    102             frequency_stddev: undefined};
    103 
    104           // Compute the stddev of the slice durations.
    105           var sumOfSquaredDistancesToMean = 0;
    106           for (var i = 0; i < sliceHitGroup.hits.length; i++) {
    107             var signedDistance =
    108                 statistics.avg - sliceHitGroup.hits[i].slice.duration;
    109             sumOfSquaredDistancesToMean += signedDistance * signedDistance;
    110           }
    111 
    112           statistics.avg_stddev = Math.sqrt(
    113               sumOfSquaredDistancesToMean / (sliceHitGroup.hits.length - 1));
    114 
    115           // We require at least 3 samples to compute the stddev.
    116           var elapsed = startOfLastOccurrence - startOfFirstOccurrence;
    117           if (sliceHitGroup.hits.length > 2 && elapsed > 0) {
    118             var numDistances = sliceHitGroup.hits.length - 1;
    119             statistics.frequency = (1000 * numDistances) / elapsed;
    120 
    121             // Compute the stddev.
    122             sumOfSquaredDistancesToMean = 0;
    123             for (var i = 1; i < sliceHitGroup.hits.length; i++) {
    124               var currentFrequency = 1000 /
    125                   (sliceHitGroup.hits[i].slice.start -
    126                   sliceHitGroup.hits[i - 1].slice.start);
    127               var signedDistance = statistics.frequency - currentFrequency;
    128               sumOfSquaredDistancesToMean += signedDistance * signedDistance;
    129             }
    130 
    131             statistics.frequency_stddev = Math.sqrt(
    132                 sumOfSquaredDistancesToMean / (numDistances - 1));
    133           }
    134           results.appendDataRow(
    135               table, sliceHitGroupTitle, duration, sliceHitGroup.hits.length,
    136               statistics,
    137               function() {
    138                 return new tracing.Selection(sliceHitGroup.hits);
    139               });
    140 
    141           // The whole selection is a single type so list out the information
    142           // for each sub slice.
    143           if (numTitles === 1) {
    144             for (var i = 0; i < sliceHitGroup.hits.length; i++) {
    145               analyzeSingleSliceHit(results, sliceHitGroup.hits[i]);
    146             }
    147           }
    148         });
    149 
    150     // Only one row so we already know the totals.
    151     if (numTitles !== 1) {
    152       results.appendDataRow(table, '*Totals', totalDuration, sliceHits.length);
    153       results.appendSpacingRow(table);
    154     }
    155 
    156     results.appendSummaryRowTime(table, 'Selection start', tsLo);
    157     results.appendSummaryRowTime(table, 'Selection extent', tsHi - tsLo);
    158   }
    159 
    160   return {
    161     analyzeSingleSliceHit: analyzeSingleSliceHit,
    162     analyzeMultipleSliceHits: analyzeMultipleSliceHits
    163   };
    164 });
    165