blob: 262e06d15a1797f4cd833060ee0ed81c8b3c4cd0 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2015 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/base/base.html">
<link rel="import" href="/tracing/base/statistics.html">
<link rel="import" href="/tracing/core/auditor.html">
<link rel="import" href="/tracing/model/model.html">
<link rel="import" href="/tracing/base/range_utils.html">
<link rel="import" href="/tracing/extras/chrome/chrome_model_helper.html">
<script>
'use strict';
/**
* @fileoverview Base class for trace data Auditors.
*/
tr.exportTo('tr.e.rail', function() {
// We need an up-front list of all IR types in order to keep various groupings
// stable, in presence of only a portion of interactions in a given trace.
var ALL_RAIL_TYPE_NAMES = [
'rail_response',
'rail_animate',
'rail_idle',
'rail_load'
];
var DOES_RAIL_TYPE_NAME_EXIST = {};
ALL_RAIL_TYPE_NAMES.forEach(function(railTypeName) {
DOES_RAIL_TYPE_NAME_EXIST[railTypeName] = true;
});
function RAILInteractionRecord(title, railTypeName, start, duration) {
if (!DOES_RAIL_TYPE_NAME_EXIST[railTypeName])
throw new Error(railTypeName + ' is not listed in ALL_RAIL_TYPE_NAMES');
var colorId = tr.ui.b.getColorIdForReservedName(railTypeName);
this.railTypeName_ = railTypeName;
this.name = '';
tr.model.InteractionRecord.call(this,
title, colorId, start, duration);
}
RAILInteractionRecord.prototype = {
__proto__: tr.model.InteractionRecord.prototype,
updateArgs: function() {
var args = {};
var layoutSlices = this.associatedEvents.filter(function(event) {
return event.title === 'FrameView::layout';
});
var timeInLayout = tr.b.Statistics.sum(layoutSlices, function(event) {
return event.duration;
});
args['layoutInfo'] = {
'timeInLayout': timeInLayout
};
this.args = args;
},
get railTypeName() {
return this.railTypeName_;
},
/**
* Returns the overall rail score, from 0 to 1.
*
* RAILScore for an interaction merges the user's pain with the
* efficiency, in order to create a perception-oriented measure
* of how users percieve speed during this interaction.
*
* 0 means a bad user experience.
* 1 means a perfect user experience.
*/
get railScore() {
var happiness = 1 - this.normalizedUserPain;
var efficiency = this.normalizedEfficiency;
// The lower sub-score is more important than the higher sub-score.
// happiness is more important than efficiency.
var happinessWeight = 2 * Math.exp(1 - happiness);
var efficiencyWeight = Math.exp(1 - efficiency);
// This function is graphed at http://goo.gl/XMWUKA
return ((happiness * happinessWeight + efficiency * efficiencyWeight) /
(happinessWeight + efficiencyWeight));
},
/**
* Measures the pain the user experienced, from 0 to 1.
*
* A user performs an interaction with an expectation in mind.
* When we exceed their expectations, we get zero pain.
* When we meet their expectations, we get zero pain.
* As we exceed their expectations, pain goes up. Maximum pain
* is 1.0, aka "Switch to FireFox".
*/
get normalizedUserPain() {
throw new Error('Not implemented');
},
/**
* Returns the sum of the number of CPU ms spent by this IR.
*/
get rawCpuMs() {
var cpuMs = 0;
this.associatedEvents.forEach(function(event) {
if (event.cpuSelfTime)
cpuMs += event.cpuSelfTime;
});
return cpuMs;
},
/**
* Returns a number between 0 and 1 representing how efficiently this IR
* used CPU resources. 0 is maximally in-efficient, 1 is maximally
* efficient.
*/
get normalizedCpuEfficiency() {
var minCpuMs = this.duration * this.minCpuFraction;
var maxCpuMs = this.duration * this.maxCpuFraction;
var normalizedCpu = tr.b.normalize(this.rawCpuMs, minCpuMs, maxCpuMs);
return 1 - tr.b.clamp(normalizedCpu, 0, 1);
},
/**
* The minimum fraction of a CPU that can be spent on this IR before the
* efficiency score will be impacted.
* If less CPU ms than this is spent on this IR, then
* normalizedCpuEfficiency will be 1.
*/
get minCpuFraction() {
return 0.5;
},
/**
* The maximum fraction of a CPU that can be spent on this IR.
* If more CPU ms than this is spent on this IR, then
* normalizedCpuEfficiency will be 0.
*/
get maxCpuFraction() {
return 1.5;
},
/**
* Measures the efficiency of the interaction from 0 to 1.
*
* Efficiency is a notion of how well we used the machine's limited
* resources in service of this interaction. If we used it perfectly,
* we would get a 1.0. If we used everything that there was to use ---
* power, memory, cpu, then we'd get a zero.
*/
get normalizedEfficiency() {
return this.normalizedCpuEfficiency;
}
};
return {
RAILInteractionRecord: RAILInteractionRecord,
ALL_RAIL_TYPE_NAMES: ALL_RAIL_TYPE_NAMES
};
});
</script>