| Index: tracing/tracing/metrics/system_health/hazard_metric.html
|
| diff --git a/tracing/tracing/metrics/system_health/hazard_metric.html b/tracing/tracing/metrics/system_health/hazard_metric.html
|
| index 9ee9103b73ab37b3aa6015f1e6a8959e03baca1d..9696177978227c8a810640ed231fec345f1834a1 100644
|
| --- a/tracing/tracing/metrics/system_health/hazard_metric.html
|
| +++ b/tracing/tracing/metrics/system_health/hazard_metric.html
|
| @@ -6,9 +6,7 @@ found in the LICENSE file.
|
| -->
|
|
|
| <link rel="import" href="/tracing/metrics/metric_registry.html">
|
| -<link rel="import"
|
| - href="/tracing/metrics/system_health/responsiveness_metric.html">
|
| -<link rel="import" href="/tracing/model/user_model/idle_expectation.html">
|
| +<link rel="import" href="/tracing/metrics/system_health/long_tasks_metric.html">
|
| <link rel="import" href="/tracing/value/numeric.html">
|
| <link rel="import" href="/tracing/value/value.html">
|
|
|
| @@ -16,67 +14,41 @@ found in the LICENSE file.
|
| 'use strict';
|
|
|
| tr.exportTo('tr.metrics.sh', function() {
|
| - var LONG_TASK_MS = 50;
|
| -
|
| var normalizedPercentage_smallerIsBetter =
|
| tr.v.Unit.byName.normalizedPercentage_smallerIsBetter;
|
| - var timeDurationInMs_smallerIsBetter =
|
| - tr.v.Unit.byName.timeDurationInMs_smallerIsBetter;
|
| -
|
| - var FAST_RESPONSE_HISTOGRAM = tr.v.Numeric.fromDict({
|
| - unit: 'unitless',
|
| - min: 66,
|
| - max: 2200,
|
| - centralBinWidth: 214,
|
| - underflowBin: {min: -Number.MAX_VALUE, max: 66, count: 1000},
|
| - centralBins: [
|
| - {min: 66, max: 280, count: 708},
|
| - {min: 280, max: 493, count: 223},
|
| - {min: 493, max: 706, count: 50},
|
| - {min: 706, max: 920, count: 33},
|
| - {min: 920, max: 1133, count: 23},
|
| - {min: 1133, max: 1346, count: 17},
|
| - {min: 1346, max: 1560, count: 12},
|
| - {min: 1560, max: 1773, count: 8},
|
| - {min: 1773, max: 1987, count: 4},
|
| - {min: 1987, max: 2200, count: 1}
|
| - ],
|
| - overflowBin: {min: 2200, max: Number.MAX_VALUE, count: 0}
|
| - });
|
| -
|
| - function computeDurationResponsiveness(histogram, duration) {
|
| - return histogram.getInterpolatedCountAt(duration) / histogram.maxCount;
|
| - }
|
| -
|
| - function findLongTasks(ue) {
|
| - var longTasks = [];
|
| - // NB: This misses tasks that were associated with another UE,
|
| - // since only unassociated events are vacuumed up into IdleExpectations.
|
| - ue.associatedEvents.forEach(function(event) {
|
| - if ((event instanceof tr.model.ThreadSlice) &&
|
| - (event.duration > LONG_TASK_MS) &&
|
| - event.isTopLevel)
|
| - longTasks.push(event);
|
| - });
|
| - return longTasks;
|
| - }
|
|
|
| + // The following math is easier if the units are seconds rather than ms,
|
| + // so durations will be converted from ms to s.
|
| + var MS_PER_S = 1000;
|
| +
|
| + // https://www.desmos.com/calculator/ysabhcc42g
|
| + var RESPONSE_RISK =
|
| + tr.b.Statistics.LogNormalDistribution.fromMedianAndDiminishingReturns(
|
| + 100 / MS_PER_S, 50 / MS_PER_S);
|
| +
|
| + /**
|
| + * This helper function computes the risk that a task of the given duration
|
| + * would impact the responsiveness of a speculative input.
|
| + *
|
| + * @param {number} durationMs
|
| + * @return {number} task hazard
|
| + */
|
| function computeResponsivenessRisk(durationMs) {
|
| // Returns 0 when the risk of impacting responsiveness is minimal.
|
| // Returns 1 when it is maximal.
|
| - // durationMs is the duration of a long idle task.
|
| - // It is at least DEFAULT_LONG_TASK_MS.
|
| - // The FAST_RESPONSE_HISTOGRAM was designed to permit both a 50ms idle task
|
| - // when a Scroll Response begins, plus 16ms latency between the idle task
|
| + // durationMs is the duration of a long task.
|
| + // It is at least LONG_TASK_MS.
|
| + // The FAST_RESPONSE_HISTOGRAM was designed to permit both a 50ms task
|
| + // when a Scroll Response begins, plus 16ms latency between the task
|
| // and the first frame of the scroll, without impacting the responsiveness
|
| // score.
|
| // Add 16ms to durationMs to simulate the standard (maximum ideal) scroll
|
| // response latency, and use the FAST_RESPONSE_HISTOGRAM to punish every ms
|
| - // that the long idle task exceeds DEFAULT_LONG_TASK_MS.
|
| + // that the long task exceeds LONG_TASK_MS.
|
|
|
| durationMs += 16;
|
|
|
| - // computeDurationResponsiveness returns a normalized percentage that
|
| + // This returns a normalized percentage that
|
| // represents the fraction of users that would be satisfied with a
|
| // Scroll Response that takes durationMs to respond.
|
| // The risk of impacting responsiveness is approximated as the long task's
|
| @@ -89,79 +61,85 @@ tr.exportTo('tr.metrics.sh', function() {
|
| // that would be *un*satisifed with the responsiveness of that hypothetical
|
| // Scroll Response. The fraction of users who are unsatisfied with something
|
| // is equal to 1 - the fraction of users who are satisfied with it.
|
| - return 1 - computeDurationResponsiveness(
|
| - FAST_RESPONSE_HISTOGRAM, durationMs);
|
| + return RESPONSE_RISK.computePercentile(durationMs / MS_PER_S);
|
| }
|
|
|
| - // This weighting function is similar to tr.metrics.sh.perceptualBlend,
|
| - // but this version is appropriate for SmallerIsBetter metrics, whereas
|
| - // that version is for BiggerIsBetter metrics.
|
| - // (This would not be necessary if hazard were reframed as a BiggerIsBetter
|
| - // metric such as "stability".)
|
| - // Also, that version assumes that the 'ary' will be UserExpectations, whereas
|
| - // this version assumes that the 'ary' will be scores.
|
| + /**
|
| + * This weighting function is similar to tr.metrics.sh.perceptualBlend,
|
| + * but this version is appropriate for SmallerIsBetter metrics, whereas
|
| + * that version is for BiggerIsBetter metrics.
|
| + * (This would not be necessary if hazard were reframed as a BiggerIsBetter
|
| + * metric such as "input readiness".)
|
| + * Also, that version assumes that the 'ary' will be UserExpectations, whereas
|
| + * this version assumes that the 'ary' will be scores.
|
| + *
|
| + * @param {number} hazardScore
|
| + * @return {number} weight
|
| + */
|
| function perceptualBlendSmallerIsBetter(hazardScore) {
|
| return Math.exp(hazardScore);
|
| }
|
|
|
| - // This metric requires only the 'toplevel' tracing category,
|
| - // in addition to whatever categories are required to compute the
|
| - // IdleExpectations (or rather the R/A/Ls that delineate the Idles).
|
| - // This metric computes a hazard score for each Idle independently (instead of
|
| - // grouping all long idle tasks together) because each Idle is different:
|
| - // the Idle before a Load is usually very empty, whereas the Idle immediately
|
| - // after a Load is usually still very active, since Loads end at a very early
|
| - // end point (the first contentful paint) while many parts of the page are
|
| - // still loading. (There may not necessarily be an Idle after a Load in
|
| - // real-world traces, but there almost always is in telemetry.)
|
| - function computeLongIdleTaskHazard(hazardScores, ue) {
|
| - var longTaskScores = [];
|
| -
|
| - findLongTasks(ue).forEach(function(longTask) {
|
| - longTaskScores.push(computeResponsivenessRisk(longTask.duration));
|
| + /**
|
| + * Compute and return the normalized score for the risk that a speculative
|
| + * input's responsiveness would have been impacted by long tasks on the given
|
| + * thread in the given range.
|
| + *
|
| + * @param {tr.model.Thread} thread
|
| + * @param {tr.b.Range=} opt_range
|
| + * @return {number} hazard
|
| + */
|
| + function computeHazardForLongTasksInRangeOnThread(thread, opt_range) {
|
| + var taskHazardScores = [];
|
| + tr.metrics.sh.iterateLongTopLevelTasksOnThreadInRange(
|
| + thread, opt_range, function(task) {
|
| + taskHazardScores.push(computeResponsivenessRisk(task.duration));
|
| });
|
| -
|
| - var options = {description: 'Risk of impacting responsiveness'};
|
| -
|
| - var hazardScore = tr.b.Statistics.weightedMean(
|
| - longTaskScores, perceptualBlendSmallerIsBetter);
|
| -
|
| - if (hazardScore === undefined)
|
| - hazardScore = 0;
|
| -
|
| - hazardScores.push(hazardScore);
|
| + return tr.b.Statistics.weightedMean(
|
| + taskHazardScores, perceptualBlendSmallerIsBetter);
|
| }
|
|
|
| - function hazardMetric(values, model) {
|
| - var hazardScores = [];
|
| -
|
| - model.userModel.expectations.forEach(function(ue) {
|
| - // Add normalized metrics to diagnostics.values.
|
| - // TODO(memory): Add memory here.
|
| -
|
| - if (ue instanceof tr.model.um.IdleExpectation)
|
| - computeLongIdleTaskHazard(hazardScores, ue);
|
| + /**
|
| + * Compute and return the normalized score for the risk that a speculative
|
| + * input's responsiveness would have been impacted by long tasks.
|
| + *
|
| + * @param {tr.model.Model} model The model.
|
| + * @return {number} hazard
|
| + */
|
| + function computeHazardForLongTasks(model) {
|
| + var threadHazardScores = [];
|
| + tr.metrics.sh.iterateRendererMainThreads(model, function(thread) {
|
| + threadHazardScores.push(computeHazardForLongTasksInRangeOnThread(
|
| + thread));
|
| });
|
| + return tr.b.Statistics.weightedMean(
|
| + threadHazardScores, perceptualBlendSmallerIsBetter);
|
| + }
|
|
|
| - var options = {description: 'Risk of impacting responsiveness'};
|
| -
|
| - var overallHazard = tr.b.Statistics.weightedMean(
|
| - hazardScores, perceptualBlendSmallerIsBetter);
|
| -
|
| + /**
|
| + * This EXPERIMENTAL metric computes a scalar normalized score that
|
| + * represents the risk that a speculative input's responsiveness would have
|
| + * been impacted by long tasks.
|
| + * This metric requires only the 'toplevel' tracing category.
|
| + */
|
| + function hazardMetric(values, model) {
|
| + var overallHazard = computeHazardForLongTasks(model);
|
| if (overallHazard === undefined)
|
| overallHazard = 0;
|
|
|
| values.addValue(new tr.v.NumericValue(
|
| 'hazard', new tr.v.ScalarNumeric(
|
| - normalizedPercentage_smallerIsBetter, overallHazard),
|
| - options));
|
| + normalizedPercentage_smallerIsBetter, overallHazard)));
|
| }
|
|
|
| tr.metrics.MetricRegistry.register(hazardMetric);
|
|
|
| return {
|
| hazardMetric: hazardMetric,
|
| - computeLongIdleTaskHazard: computeLongIdleTaskHazard
|
| + computeHazardForLongTasksInRangeOnThread:
|
| + computeHazardForLongTasksInRangeOnThread,
|
| + computeHazardForLongTasks: computeHazardForLongTasks,
|
| + computeResponsivenessRisk: computeResponsivenessRisk
|
| };
|
| });
|
| </script>
|
|
|