Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(502)

Side by Side Diff: tracing/tracing/metrics/system_health/hazard_metric.html

Issue 1992303003: Refactor hazardMetric (Closed) Base URL: https://github.com/catapult-project/catapult.git@master
Patch Set: fixing Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <!-- 2 <!--
3 Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 Copyright (c) 2015 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be 4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file. 5 found in the LICENSE file.
6 --> 6 -->
7 7
8 <link rel="import" href="/tracing/metrics/metric_registry.html"> 8 <link rel="import" href="/tracing/metrics/metric_registry.html">
9 <link rel="import" 9 <link rel="import" href="/tracing/metrics/system_health/long_tasks_metric.html">
10 href="/tracing/metrics/system_health/responsiveness_metric.html">
11 <link rel="import" href="/tracing/model/user_model/idle_expectation.html">
12 <link rel="import" href="/tracing/value/numeric.html"> 10 <link rel="import" href="/tracing/value/numeric.html">
13 <link rel="import" href="/tracing/value/value.html"> 11 <link rel="import" href="/tracing/value/value.html">
14 12
15 <script> 13 <script>
16 'use strict'; 14 'use strict';
17 15
18 tr.exportTo('tr.metrics.sh', function() { 16 tr.exportTo('tr.metrics.sh', function() {
19 var LONG_TASK_MS = 50;
20
21 var normalizedPercentage_smallerIsBetter = 17 var normalizedPercentage_smallerIsBetter =
22 tr.v.Unit.byName.normalizedPercentage_smallerIsBetter; 18 tr.v.Unit.byName.normalizedPercentage_smallerIsBetter;
23 var timeDurationInMs_smallerIsBetter =
24 tr.v.Unit.byName.timeDurationInMs_smallerIsBetter;
25 19
26 var FAST_RESPONSE_HISTOGRAM = tr.v.Numeric.fromDict({ 20 // The following math is easier if the units are seconds rather than ms,
27 unit: 'unitless', 21 // so durations will be converted from ms to s.
28 min: 66, 22 var MS_PER_S = 1000;
29 max: 2200,
30 centralBinWidth: 214,
31 underflowBin: {min: -Number.MAX_VALUE, max: 66, count: 1000},
32 centralBins: [
33 {min: 66, max: 280, count: 708},
34 {min: 280, max: 493, count: 223},
35 {min: 493, max: 706, count: 50},
36 {min: 706, max: 920, count: 33},
37 {min: 920, max: 1133, count: 23},
38 {min: 1133, max: 1346, count: 17},
39 {min: 1346, max: 1560, count: 12},
40 {min: 1560, max: 1773, count: 8},
41 {min: 1773, max: 1987, count: 4},
42 {min: 1987, max: 2200, count: 1}
43 ],
44 overflowBin: {min: 2200, max: Number.MAX_VALUE, count: 0}
45 });
46 23
47 function computeDurationResponsiveness(histogram, duration) { 24 // https://www.desmos.com/calculator/ysabhcc42g
48 return histogram.getInterpolatedCountAt(duration) / histogram.maxCount; 25 var RESPONSE_RISK =
49 } 26 tr.b.Statistics.LogNormalDistribution.fromMedianAndDiminishingReturns(
27 100 / MS_PER_S, 50 / MS_PER_S);
50 28
51 function findLongTasks(ue) { 29 /**
52 var longTasks = []; 30 * This helper function computes the risk that a task of the given duration
53 // NB: This misses tasks that were associated with another UE, 31 * would impact the responsiveness of a speculative input.
54 // since only unassociated events are vacuumed up into IdleExpectations. 32 *
55 ue.associatedEvents.forEach(function(event) { 33 * @param {number} durationMs
56 if ((event instanceof tr.model.ThreadSlice) && 34 * @return {number} task hazard
57 (event.duration > LONG_TASK_MS) && 35 */
58 event.isTopLevel)
59 longTasks.push(event);
60 });
61 return longTasks;
62 }
63
64 function computeResponsivenessRisk(durationMs) { 36 function computeResponsivenessRisk(durationMs) {
65 // Returns 0 when the risk of impacting responsiveness is minimal. 37 // Returns 0 when the risk of impacting responsiveness is minimal.
66 // Returns 1 when it is maximal. 38 // Returns 1 when it is maximal.
67 // durationMs is the duration of a long idle task. 39 // durationMs is the duration of a long task.
68 // It is at least DEFAULT_LONG_TASK_MS. 40 // It is at least LONG_TASK_MS.
69 // The FAST_RESPONSE_HISTOGRAM was designed to permit both a 50ms idle task 41 // The FAST_RESPONSE_HISTOGRAM was designed to permit both a 50ms task
70 // when a Scroll Response begins, plus 16ms latency between the idle task 42 // when a Scroll Response begins, plus 16ms latency between the task
71 // and the first frame of the scroll, without impacting the responsiveness 43 // and the first frame of the scroll, without impacting the responsiveness
72 // score. 44 // score.
73 // Add 16ms to durationMs to simulate the standard (maximum ideal) scroll 45 // Add 16ms to durationMs to simulate the standard (maximum ideal) scroll
74 // response latency, and use the FAST_RESPONSE_HISTOGRAM to punish every ms 46 // response latency, and use the FAST_RESPONSE_HISTOGRAM to punish every ms
75 // that the long idle task exceeds DEFAULT_LONG_TASK_MS. 47 // that the long task exceeds LONG_TASK_MS.
76 48
77 durationMs += 16; 49 durationMs += 16;
78 50
79 // computeDurationResponsiveness returns a normalized percentage that 51 // This returns a normalized percentage that
80 // represents the fraction of users that would be satisfied with a 52 // represents the fraction of users that would be satisfied with a
81 // Scroll Response that takes durationMs to respond. 53 // Scroll Response that takes durationMs to respond.
82 // The risk of impacting responsiveness is approximated as the long task's 54 // The risk of impacting responsiveness is approximated as the long task's
83 // impact on a hypothetical Scroll Response that starts when the long task 55 // impact on a hypothetical Scroll Response that starts when the long task
84 // starts, and then takes the standard 16ms to respond after the long task 56 // starts, and then takes the standard 16ms to respond after the long task
85 // finishes. 57 // finishes.
86 // We imagine a Scroll Response instead of a Load or another type of 58 // We imagine a Scroll Response instead of a Load or another type of
87 // Response because the Scroll Response carries the strictest expectation. 59 // Response because the Scroll Response carries the strictest expectation.
88 // The risk of impacting responsiveness is framed as the fraction of users 60 // The risk of impacting responsiveness is framed as the fraction of users
89 // that would be *un*satisifed with the responsiveness of that hypothetical 61 // that would be *un*satisifed with the responsiveness of that hypothetical
90 // Scroll Response. The fraction of users who are unsatisfied with something 62 // Scroll Response. The fraction of users who are unsatisfied with something
91 // is equal to 1 - the fraction of users who are satisfied with it. 63 // is equal to 1 - the fraction of users who are satisfied with it.
92 return 1 - computeDurationResponsiveness( 64 return RESPONSE_RISK.computePercentile(durationMs / MS_PER_S);
93 FAST_RESPONSE_HISTOGRAM, durationMs);
94 } 65 }
95 66
96 // This weighting function is similar to tr.metrics.sh.perceptualBlend, 67 /**
97 // but this version is appropriate for SmallerIsBetter metrics, whereas 68 * This weighting function is similar to tr.metrics.sh.perceptualBlend,
98 // that version is for BiggerIsBetter metrics. 69 * but this version is appropriate for SmallerIsBetter metrics, whereas
99 // (This would not be necessary if hazard were reframed as a BiggerIsBetter 70 * that version is for BiggerIsBetter metrics.
100 // metric such as "stability".) 71 * (This would not be necessary if hazard were reframed as a BiggerIsBetter
101 // Also, that version assumes that the 'ary' will be UserExpectations, whereas 72 * metric such as "input readiness".)
102 // this version assumes that the 'ary' will be scores. 73 * Also, that version assumes that the 'ary' will be UserExpectations, whereas
74 * this version assumes that the 'ary' will be scores.
75 *
76 * @param {number} hazardScore
77 * @return {number} weight
78 */
103 function perceptualBlendSmallerIsBetter(hazardScore) { 79 function perceptualBlendSmallerIsBetter(hazardScore) {
104 return Math.exp(hazardScore); 80 return Math.exp(hazardScore);
105 } 81 }
106 82
107 // This metric requires only the 'toplevel' tracing category, 83 /**
108 // in addition to whatever categories are required to compute the 84 * Compute and return the normalized score for the risk that a speculative
109 // IdleExpectations (or rather the R/A/Ls that delineate the Idles). 85 * input's responsiveness would have been impacted by long tasks on the given
110 // This metric computes a hazard score for each Idle independently (instead of 86 * thread in the given range.
111 // grouping all long idle tasks together) because each Idle is different: 87 *
112 // the Idle before a Load is usually very empty, whereas the Idle immediately 88 * @param {tr.model.Thread} thread
113 // after a Load is usually still very active, since Loads end at a very early 89 * @param {tr.b.Range=} opt_range
114 // end point (the first contentful paint) while many parts of the page are 90 * @return {number} hazard
115 // still loading. (There may not necessarily be an Idle after a Load in 91 */
116 // real-world traces, but there almost always is in telemetry.) 92 function computeHazardForLongTasksInRangeOnThread(thread, opt_range) {
117 function computeLongIdleTaskHazard(hazardScores, ue) { 93 var taskHazardScores = [];
118 var longTaskScores = []; 94 tr.metrics.sh.iterateLongTopLevelTasksOnThreadInRange(
119 95 thread, opt_range, function(task) {
120 findLongTasks(ue).forEach(function(longTask) { 96 taskHazardScores.push(computeResponsivenessRisk(task.duration));
121 longTaskScores.push(computeResponsivenessRisk(longTask.duration));
122 }); 97 });
123 98 return tr.b.Statistics.weightedMean(
124 var options = {description: 'Risk of impacting responsiveness'}; 99 taskHazardScores, perceptualBlendSmallerIsBetter);
125
126 var hazardScore = tr.b.Statistics.weightedMean(
127 longTaskScores, perceptualBlendSmallerIsBetter);
128
129 if (hazardScore === undefined)
130 hazardScore = 0;
131
132 hazardScores.push(hazardScore);
133 } 100 }
134 101
102 /**
103 * Compute and return the normalized score for the risk that a speculative
104 * input's responsiveness would have been impacted by long tasks.
105 *
106 * @param {tr.model.Model} model The model.
107 * @return {number} hazard
108 */
109 function computeHazardForLongTasks(model) {
110 var threadHazardScores = [];
111 tr.metrics.sh.iterateRendererMainThreads(model, function(thread) {
112 threadHazardScores.push(computeHazardForLongTasksInRangeOnThread(
113 thread));
114 });
115 return tr.b.Statistics.weightedMean(
116 threadHazardScores, perceptualBlendSmallerIsBetter);
117 }
118
119 /**
120 * This EXPERIMENTAL metric computes a scalar normalized score that
121 * represents the risk that a speculative input's responsiveness would have
122 * been impacted by long tasks.
123 * This metric requires only the 'toplevel' tracing category.
124 */
135 function hazardMetric(values, model) { 125 function hazardMetric(values, model) {
136 var hazardScores = []; 126 var overallHazard = computeHazardForLongTasks(model);
137
138 model.userModel.expectations.forEach(function(ue) {
139 // Add normalized metrics to diagnostics.values.
140 // TODO(memory): Add memory here.
141
142 if (ue instanceof tr.model.um.IdleExpectation)
143 computeLongIdleTaskHazard(hazardScores, ue);
144 });
145
146 var options = {description: 'Risk of impacting responsiveness'};
147
148 var overallHazard = tr.b.Statistics.weightedMean(
149 hazardScores, perceptualBlendSmallerIsBetter);
150
151 if (overallHazard === undefined) 127 if (overallHazard === undefined)
152 overallHazard = 0; 128 overallHazard = 0;
153 129
154 values.addValue(new tr.v.NumericValue( 130 values.addValue(new tr.v.NumericValue(
155 'hazard', new tr.v.ScalarNumeric( 131 'hazard', new tr.v.ScalarNumeric(
156 normalizedPercentage_smallerIsBetter, overallHazard), 132 normalizedPercentage_smallerIsBetter, overallHazard)));
157 options));
158 } 133 }
159 134
160 tr.metrics.MetricRegistry.register(hazardMetric); 135 tr.metrics.MetricRegistry.register(hazardMetric);
161 136
162 return { 137 return {
163 hazardMetric: hazardMetric, 138 hazardMetric: hazardMetric,
164 computeLongIdleTaskHazard: computeLongIdleTaskHazard 139 computeHazardForLongTasksInRangeOnThread:
140 computeHazardForLongTasksInRangeOnThread,
141 computeHazardForLongTasks: computeHazardForLongTasks,
142 computeResponsivenessRisk: computeResponsivenessRisk
165 }; 143 };
166 }); 144 });
167 </script> 145 </script>
OLDNEW
« no previous file with comments | « tracing/tracing/base/statistics.html ('k') | tracing/tracing/metrics/system_health/hazard_metric_test.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698