| Index: tracing/tracing/metrics/system_health/power_metric.html
|
| diff --git a/tracing/tracing/metrics/system_health/power_metric.html b/tracing/tracing/metrics/system_health/power_metric.html
|
| index e61a491f30c6d25c880e30ff4eb6af1a80771dde..da9b4c2af0b11fdd416e6a38176b7089c417e68a 100644
|
| --- a/tracing/tracing/metrics/system_health/power_metric.html
|
| +++ b/tracing/tracing/metrics/system_health/power_metric.html
|
| @@ -5,6 +5,7 @@ Use of this source code is governed by a BSD-style license that can be
|
| found in the LICENSE file.
|
| -->
|
|
|
| +<link rel="import" href="/tracing/base/range.html">
|
| <link rel="import" href="/tracing/base/statistics.html">
|
| <link rel="import" href="/tracing/importer/find_input_expectations.html">
|
| <link rel="import" href="/tracing/metrics/metric_registry.html">
|
| @@ -134,12 +135,9 @@ tr.exportTo('tr.metrics.sh', function() {
|
| * @param {tr.v.Histogram} powerHist - Histogram to store power data.
|
| */
|
| function storePowerData_(data, timeHist, energyHist, powerHist) {
|
| - if (timeHist !== undefined)
|
| - timeHist.addSample(data.duration);
|
| - if (energyHist !== undefined)
|
| - energyHist.addSample(data.energy);
|
| - if (powerHist !== undefined)
|
| - powerHist.addSample(data.power);
|
| + if (timeHist !== undefined) timeHist.addSample(data.duration);
|
| + if (energyHist !== undefined) energyHist.addSample(data.energy);
|
| + if (powerHist !== undefined) powerHist.addSample(data.power);
|
| }
|
|
|
| function createHistograms_(model, values) {
|
| @@ -212,9 +210,11 @@ tr.exportTo('tr.metrics.sh', function() {
|
| * purposes. This function only keeps track of metrics that are based
|
| * on the start and end time of the RAIL stages.
|
| */
|
| - function processInteractionRecord_(exp, model, hists) {
|
| + function processInteractionRecord_(exp, model, hists, chromeBounds) {
|
| var currTitle = exp.title.toLowerCase().replace(' ', '_');
|
| - var data = getPowerData_(model, exp.start, exp.end);
|
| + var interval = tr.b.Range.fromExplicitRange(exp.start, exp.end)
|
| + .findIntersection(chromeBounds);
|
| + var data = getPowerData_(model, interval.min, interval.max);
|
|
|
| // Add the samples for the "generic" RAIL stage metrics.
|
| storePowerData_(data, hists.railStageToTimeHist.get(currTitle),
|
| @@ -230,8 +230,9 @@ tr.exportTo('tr.metrics.sh', function() {
|
| }
|
|
|
| // If this is a video stage, add the sample for the video metrics.
|
| - if (exp.initiatorType === tr.importer.INITIATOR_TYPE.VIDEO)
|
| + if (exp.initiatorType === tr.importer.INITIATOR_TYPE.VIDEO) {
|
| storePowerData_(data, undefined, undefined, hists.videoPowerHist)
|
| + }
|
| }
|
|
|
| /**
|
| @@ -239,10 +240,11 @@ tr.exportTo('tr.metrics.sh', function() {
|
| * in |hists|. Note that this is not in processInteractionRecord_ because
|
| * the loading metric intervals don't correspond exactly to the RAIL stages.
|
| */
|
| - function computeLoadingMetric_(model, hists) {
|
| - var intervals = getNavigationTTIIntervals_(model);
|
| + function computeLoadingMetric_(model, hists, chromeBounds) {
|
| + var ttiIntervals = getNavigationTTIIntervals_(model);
|
| var lastLoadTime = undefined;
|
| - for (var interval of intervals) {
|
| + for (var ttiInterval of ttiIntervals) {
|
| + var interval = ttiInterval.findIntersection(chromeBounds);
|
| var loadData = getPowerData_(model, interval.min, interval.max);
|
| storePowerData_(loadData, hists.loadTimeHist, hists.loadEnergyHist,
|
| undefined);
|
| @@ -250,7 +252,7 @@ tr.exportTo('tr.metrics.sh', function() {
|
| Math.max(lastLoadTime, interval.max));
|
| }
|
| if (lastLoadTime !== undefined) {
|
| - var afterLoadData = getPowerData_(model, lastLoadTime, model.bounds.max);
|
| + var afterLoadData = getPowerData_(model, lastLoadTime, chromeBounds.max);
|
| storePowerData_(afterLoadData, hists.afterLoadTimeHist,
|
| undefined, hists.afterLoadPowerHist);
|
| }
|
| @@ -259,29 +261,79 @@ tr.exportTo('tr.metrics.sh', function() {
|
| /**
|
| * Compute the per-frame power metrics and put the results in |hists|.
|
| */
|
| - function computeFrameBasedPowerMetric_(model, hists) {
|
| - model.device.powerSeries.updateBounds();
|
| - var currentTime = model.device.powerSeries.bounds.min;
|
| - while (currentTime < model.device.powerSeries.bounds.max) {
|
| + function computeFrameBasedPowerMetric_(model, hists, chromeBounds) {
|
| + var currentTime = chromeBounds.min;
|
| + while (currentTime < chromeBounds.max) {
|
| var frameData = getPowerData_(model, currentTime, currentTime + FRAME_MS);
|
| hists.frameEnergyHist.addSample(frameData.energy);
|
| currentTime += FRAME_MS;
|
| }
|
| }
|
|
|
| + function computeChromeBounds(model) {
|
| + var chromeBounds = new tr.b.Range();
|
| + var chromeHelper = model.getOrCreateHelper(
|
| + tr.model.helpers.ChromeModelHelper);
|
| + for (var pid in chromeHelper.browserHelpers) {
|
| + if (chromeHelper.browserHelpers[pid].mainThread) {
|
| + chromeBounds.addRange(
|
| + chromeHelper.browserHelpers[pid].mainThread.bounds);
|
| + }
|
| + }
|
| + for (var pid in chromeHelper.rendererHelpers) {
|
| + if (chromeHelper.rendererHelpers[pid].mainThread) {
|
| + chromeBounds.addRange(
|
| + chromeHelper.rendererHelpers[pid].mainThread.bounds);
|
| + }
|
| + }
|
| + return chromeBounds;
|
| + }
|
|
|
| function powerMetric(values, model) {
|
| - if (!model.device.powerSeries)
|
| - return;
|
| + // Fail gracefully if there's no Chrome trace available.
|
| + var chromeHelper = model.getOrCreateHelper(
|
| + tr.model.helpers.ChromeModelHelper);
|
| + var powerSeries = model.device.powerSeries;
|
| + if (chromeHelper === undefined) {
|
| + throw new Error('Cannot calculate power metric: No Chrome trace');
|
| + }
|
| +
|
| + // Fail gracefully if there's no power series available.
|
| + if (powerSeries === undefined) {
|
| + throw new Error('Cannot calculate power metric: ' +
|
| + 'No power series available');
|
| + }
|
| +
|
| + if (powerSeries.samples.length === 0) {
|
| + throw new Error('Cannot calculate power metric: ' +
|
| + 'Power series has no samples');
|
| + }
|
| +
|
| + // Fail gracefully if the power series doesn't cover the entire trace.
|
| + // (add 1 ms grace period at each end)
|
| + var chromeBounds = computeChromeBounds(model);
|
| + if (chromeBounds.isEmpty) {
|
| + throw new Error('Cannot calculate power metric: ' +
|
| + 'No events in Chrome trace');
|
| + }
|
| +
|
| + var powerSeriesBoundsWithGracePeriod = tr.b.Range.fromExplicitRange(
|
| + powerSeries.bounds.min - 1, powerSeries.bounds.max + 1);
|
| + if (!powerSeriesBoundsWithGracePeriod.containsRangeExclusive(
|
| + chromeBounds)) {
|
| + throw new Error('Cannot calculate power metric: ' +
|
| + 'Power series does not cover entire Chrome trace');
|
| + }
|
|
|
| var hists = createHistograms_(model, values);
|
| - for (var exp of model.userModel.expectations)
|
| - processInteractionRecord_(exp, model, hists);
|
| + for (var exp of model.userModel.expectations) {
|
| + processInteractionRecord_(exp, model, hists, chromeBounds);
|
| + }
|
|
|
| // The following two metrics aren't based directly on the IR intervals,
|
| // and so need to be computed outside the processInteractionRecord_ loop.
|
| - computeLoadingMetric_(model, hists);
|
| - computeFrameBasedPowerMetric_(model, hists);
|
| + computeLoadingMetric_(model, hists, chromeBounds);
|
| + computeFrameBasedPowerMetric_(model, hists, chromeBounds);
|
| }
|
|
|
| tr.metrics.MetricRegistry.register(powerMetric);
|
|
|