blob: 778bdf6273ce3a5cd243f0a01c65b2ba9d5c9024 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2016 The Chromium Authors. All rights reserved.
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/metrics/metric_registry.html">
<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
<link rel="import" href="/tracing/model/helpers/chrome_renderer_helper.html">
<link rel="import" href="/tracing/value/histogram.html">
<script>
'use strict';
tr.exportTo('tr.metrics.sh', function() {
// Use a lower bound of 0.01 for the metric boundaries (when no CPU time
// is consumed) and an upper bound of 50 (fifty cores are all active
// for the entire time). We can't use zero exactly for the lower bound with an
// exponential histogram.
var CPU_TIME_PERCENTAGE_BOUNDARIES =
tr.v.HistogramBinBoundaries.createExponential(0.01, 50, 200);
/**
* This metric measures total CPU time for Chrome processes, per second of
* clock time.
* This metric requires only the 'toplevel' tracing category.
*
* @param {!tr.v.HistogramSet} histograms
* @param {!tr.model.Model} model
* @param {!Object=} opt_options
*/
function cpuTimeMetric(histograms, model, opt_options) {
var rangeOfInterest = model.bounds;
if (opt_options && opt_options.rangeOfInterest) {
rangeOfInterest = opt_options.rangeOfInterest;
} else {
// If no range of interest is provided, limit the relevant range to
// Chrome processes. This prevents us from normalizing against non-Chrome
// related slices in the trace.
var chromeHelper = model.getOrCreateHelper(
tr.model.helpers.ChromeModelHelper);
if (chromeHelper) {
var chromeBounds = chromeHelper.chromeBounds;
if (chromeBounds) {
rangeOfInterest = chromeBounds;
}
}
}
var allProcessCpuTime = 0;
for (var pid in model.processes) {
var process = model.processes[pid];
if (tr.model.helpers.ChromeRendererHelper.isTracingProcess(process)) {
continue;
}
var processCpuTime = 0;
for (var tid in process.threads) {
var thread = process.threads[tid];
var threadCpuTime = 0;
thread.sliceGroup.topLevelSlices.forEach(function(slice) {
if (slice.duration === 0)
return;
if (!slice.cpuDuration)
return;
var sliceRange = tr.b.math.Range.fromExplicitRange(
slice.start, slice.end);
var intersection = rangeOfInterest.findIntersection(sliceRange);
var fractionOfSliceInsideRangeOfInterest =
intersection.duration / slice.duration;
// We assume that if a slice doesn't lie entirely inside the range of
// interest, then the CPU time is evenly distributed inside of the
// slice.
threadCpuTime +=
slice.cpuDuration * fractionOfSliceInsideRangeOfInterest;
});
processCpuTime += threadCpuTime;
}
allProcessCpuTime += processCpuTime;
}
// Normalize cpu time by clock time.
var normalizedAllProcessCpuTime = 0;
if (rangeOfInterest.duration > 0) {
normalizedAllProcessCpuTime =
allProcessCpuTime / rangeOfInterest.duration;
}
var unit = tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;
var cpuTimeHist = new tr.v.Histogram(
'cpu_time_percentage', unit, CPU_TIME_PERCENTAGE_BOUNDARIES);
cpuTimeHist.description =
'Percent CPU utilization, normalized against a single core. Can be ' +
'greater than 100% if machine has multiple cores.';
cpuTimeHist.customizeSummaryOptions({
avg: true,
count: false,
max: false,
min: false,
std: false,
sum: false
});
cpuTimeHist.addSample(normalizedAllProcessCpuTime);
histograms.addHistogram(cpuTimeHist);
}
tr.metrics.MetricRegistry.register(cpuTimeMetric, {
supportsRangeOfInterest: true
});
return {
cpuTimeMetric,
};
});
</script>