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

Side by Side Diff: tracing/tracing/metrics/v8/utils.html

Issue 1908513002: Add mutator utilization metric. (Closed) Base URL: https://github.com/catapult-project/catapult.git@master
Patch Set: More fixes Created 4 years, 8 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 2016 The Chromium Authors. All rights reserved. 3 Copyright 2016 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 <link rel="import" href="/tracing/base/piecewise_linear_function.html">
7 <link rel="import" href="/tracing/base/range.html"> 8 <link rel="import" href="/tracing/base/range.html">
9 <link rel="import" href="/tracing/base/range_utils.html">
8 <link rel="import" href="/tracing/metrics/metric_registry.html"> 10 <link rel="import" href="/tracing/metrics/metric_registry.html">
9 <link rel="import" href="/tracing/value/numeric.html"> 11 <link rel="import" href="/tracing/value/numeric.html">
10 <link rel="import" href="/tracing/value/unit.html"> 12 <link rel="import" href="/tracing/value/unit.html">
11 <link rel="import" href="/tracing/value/value.html"> 13 <link rel="import" href="/tracing/value/value.html">
12 14
13 <script> 15 <script>
14 'use strict'; 16 'use strict';
15 17
16 tr.exportTo('tr.metrics.v8.utils', function() { 18 tr.exportTo('tr.metrics.v8.utils', function() {
17 // The title of the idle task event. 19 // The title of the idle task event.
18 var IDLE_TASK_EVENT = 'SingleThreadIdleTaskRunner::RunTask'; 20 var IDLE_TASK_EVENT = 'SingleThreadIdleTaskRunner::RunTask';
19 21
22 // V8 execution event.
23 var V8_EXECUTE = 'V8.Execute';
24
20 // GC events start with this prefix. 25 // GC events start with this prefix.
21 var GC_EVENT_PREFIX = 'V8.GC'; 26 var GC_EVENT_PREFIX = 'V8.GC';
22 27
23 // Special handling is required for full GCs inside low memory notification. 28 // Special handling is required for full GCs inside low memory notification.
24 var FULL_GC_EVENT = 'V8.GCCompactor'; 29 var FULL_GC_EVENT = 'V8.GCCompactor';
25 30
26 var LOW_MEMORY_EVENT = 'V8.GCLowMemoryNotification'; 31 var LOW_MEMORY_EVENT = 'V8.GCLowMemoryNotification';
27 32
28 // Maps the top-level GC events in timeline to telemetry friendly names. 33 // Maps the top-level GC events in timeline to telemetry friendly names.
29 var TOP_GC_EVENTS = { 34 var TOP_GC_EVENTS = {
30 'V8.GCCompactor': 'v8.gc.full_mark_compactor', 35 'V8.GCCompactor': 'v8.gc.full_mark_compactor',
31 'V8.GCFinalizeMC': 'v8.gc.latency_mark_compactor', 36 'V8.GCFinalizeMC': 'v8.gc.latency_mark_compactor',
32 'V8.GCFinalizeMCReduceMemory': 'v8.gc.memory_mark_compactor', 37 'V8.GCFinalizeMCReduceMemory': 'v8.gc.memory_mark_compactor',
33 'V8.GCIncrementalMarking': 'v8.gc.incremental_step', 38 'V8.GCIncrementalMarking': 'v8.gc.incremental_step',
34 'V8.GCIncrementalMarkingFinalize': 'v8.gc.incremental_finalize', 39 'V8.GCIncrementalMarkingFinalize': 'v8.gc.incremental_finalize',
35 'V8.GCIncrementalMarkingStart': 'v8.gc.incremental_start', 40 'V8.GCIncrementalMarkingStart': 'v8.gc.incremental_start',
36 'V8.GCLowMemoryNotification': 'v8.gc.low_memory_mark_compactor', 41 'V8.GCLowMemoryNotification': 'v8.gc.low_memory_mark_compactor',
37 'V8.GCScavenger': 'v8.gc.scavenger' 42 'V8.GCScavenger': 'v8.gc.scavenger'
38 }; 43 };
39 44
40 /** 45 /**
41 * Finds the first parent of the |event| for which the |predicate| holds. 46 * Finds the first parent of the |event| for which the |predicate| holds.
42 */ 47 */
43 function findParent(event, predicate) { 48 function findParent(event, predicate) {
44 var parent = event.parentSlice; 49 var parent = event.parentSlice;
45 while (parent) { 50 while (parent) {
46 if (predicate(parent)) { 51 if (predicate(parent)) {
47 return parent; 52 return parent;
48 } 53 }
49 parent = parent.parentSlice; 54 parent = parent.parentSlice;
50 } 55 }
51 return null; 56 return null;
52 } 57 }
53 58
54 function isIdleTask(event) { 59 function isIdleTask(event) {
55 return event.title === IDLE_TASK_EVENT; 60 return event.title === IDLE_TASK_EVENT;
56 } 61 }
57 62
58 function isLowMemoryEvent(event) { 63 function isLowMemoryEvent(event) {
59 return event.title === LOW_MEMORY_EVENT; 64 return event.title === LOW_MEMORY_EVENT;
60 } 65 }
61 66
67 function isV8ExecuteEvent(event) {
68 return event.title === V8_EXECUTE;
69 }
70
71 function isTopV8ExecuteEvent(event) {
72 return isV8ExecuteEvent(event) && findParent(isV8ExecuteEvent) === null;
73 }
74
62 function isGarbageCollectionEvent(event) { 75 function isGarbageCollectionEvent(event) {
63 // Low memory notification is handled specially because it contains 76 // Low memory notification is handled specially because it contains
64 // several full mark compact events. 77 // several full mark compact events.
65 return event.title && event.title.startsWith(GC_EVENT_PREFIX) && 78 return event.title && event.title.startsWith(GC_EVENT_PREFIX) &&
66 event.title != LOW_MEMORY_EVENT; 79 event.title != LOW_MEMORY_EVENT;
67 } 80 }
68 81
69 function isTopGarbageCollectionEvent(event) { 82 function isTopGarbageCollectionEvent(event) {
70 return event.title in TOP_GC_EVENTS; 83 return event.title in TOP_GC_EVENTS;
71 } 84 }
(...skipping 17 matching lines...) Expand all
89 function subGarbageCollectionEventName(event) { 102 function subGarbageCollectionEventName(event) {
90 var topEvent = findParent(event, isTopGarbageCollectionEvent); 103 var topEvent = findParent(event, isTopGarbageCollectionEvent);
91 var prefix = topEvent ? topGarbageCollectionEventName(topEvent) : 'unknown'; 104 var prefix = topEvent ? topGarbageCollectionEventName(topEvent) : 'unknown';
92 // Remove redundant prefixes and convert to lower case. 105 // Remove redundant prefixes and convert to lower case.
93 var name = event.title.replace('V8.GC_MC_', '') 106 var name = event.title.replace('V8.GC_MC_', '')
94 .replace('V8.GC_SCAVENGER_', '') 107 .replace('V8.GC_SCAVENGER_', '')
95 .replace('V8.GC_', '').toLowerCase(); 108 .replace('V8.GC_', '').toLowerCase();
96 return prefix + '.' + name; 109 return prefix + '.' + name;
97 } 110 }
98 111
112 /**
113 * Given a list of intervals, returns a new list with all overalapping
114 * intervals merged into a single interval.
115 */
116 function unionOfIntervals(intervals) {
117 if (intervals.length === 0)
118 return [];
119 return tr.b.mergeRanges(
120 intervals.map(x => ({min: x.start, max: x.end})), 1e-6,
121 function(ranges) {
122 return {
123 start: ranges.reduce((acc, x) => Math.min(acc, x.min), ranges[0].min),
124 end: ranges.reduce((acc, x) => Math.max(acc, x.max), ranges[0].max)
125 };
126 }
127 );
128 }
129
130 /**
131 * An end-point of a window that is sliding from left to right
132 * over the |points| in the time interval defined by the |start| and |end|.
petrcermak 2016/04/22 11:40:02 nit: s/the |points|/|points|/ and s/the |start|/|s
ulan 2016/04/22 12:32:27 Done.
133 * It is intended to be used only by the |mutatorUtilization| function.
134 * @constructor
135 */
136 function WindowEndpoint(start, end, points) {
petrcermak 2016/04/22 11:40:01 Why do you pass in |end| when you don't use it???
ulan 2016/04/22 12:32:27 Leftover, removed.
137 this.points = points;
138 // The index of the last passed point.
139 this.index = -1;
petrcermak 2016/04/22 11:40:01 lastIndex?
ulan 2016/04/22 12:32:27 Done.
140 // The position of the limit.
petrcermak 2016/04/22 11:40:02 limit of what?
ulan 2016/04/22 12:32:27 Fixed the comment.
141 this.position = start;
petrcermak 2016/04/22 11:40:02 limitPosition?
ulan 2016/04/22 12:32:27 I removed limit from the comment.
142 // The distance until the next point.
143 this.remainder = points[0].position - start;
petrcermak 2016/04/22 11:40:02 distanceUntilNextPoint?
ulan 2016/04/22 12:32:27 Done.
144 // The cumulative duration of GC pauses until this position.
145 this.pause = 0;
petrcermak 2016/04/22 11:40:02 cumulativePause?
ulan 2016/04/22 12:32:27 Done.
146 // The number of entered GC intervals.
147 this.stack = 0;
petrcermak 2016/04/22 11:40:02 stackDepth?
ulan 2016/04/22 12:32:27 Done.
148 };
149
150 WindowEndpoint.prototype = {
151 // Advance the end-point by the given |delta|.
152 advance: function(delta) {
153 var points = this.points;
154 if (delta < this.remainder) {
155 this.position += delta;
156 this.pause += this.stack > 0 ? delta : 0;
157 this.remainder = points[this.index + 1].position - this.position;
158 } else {
159 this.position += this.remainder;
160 this.pause += this.stack > 0 ? this.remainder : 0;
161 this.remainder = 0;
162 this.index += 1;
petrcermak 2016/04/22 11:40:02 this.index++
ulan 2016/04/22 12:32:27 Done.
163 if (this.index < points.length) {
164 this.stack += points[this.index].delta;
165 if (this.index + 1 < points.length)
166 this.remainder = points[this.index + 1].position - this.position;
167 }
168 }
169 }
170 };
171
172 /**
173 * Returns mutator utilization as a piecewise linear function.
174 * Mutator utilization for a window size w is a function of time mu_w(t)
175 * that shows how much time in [t, t+w] is left for the mutator.
176 * More formally:
177 * mu_w(t) = (w - total_time_spent_in_gc_in(t, t + w)) / w.
178 * See "A Parallel, Real-Time Garbage Collector" by Cheng et. al. for
179 * more info [https://www.cs.cmu.edu/~guyb/papers/gc2001.pdf].
180 *
181 * @param {number} start The start time of execution.
182 * @param {number} end The end time of execution.
183 * @param {number} timeWindow The size of the time window.
184 * @param {!Array<!{start: number, end: number}>} intervals The list of
185 * GC pauses.
186 */
187 function mutatorUtilization(start, end, timeWindow, intervals) {
188 var mu = new tr.b.PiecewiseLinearFunction();
189 // If the interval is smaller than the time windows, then the function is
petrcermak 2016/04/22 11:40:02 nit: s/windows/window/
ulan 2016/04/22 12:32:27 Done.
190 // empty.
191 if (end - start <= timeWindow)
192 return mu;
193 // If there are GC pauses then the mutator utilization is 1.0.
194 if (intervals.length === 0) {
195 mu.push(start, 1.0, end - timeWindow, 1.0);
196 return mu;
197 }
198 intervals = unionOfIntervals(intervals);
199 // Create a point for the start and the end of each interval.
200 var points = [];
201 intervals.forEach(function(interval) {
202 points.push({position: interval.start, delta: 1});
203 points.push({position: interval.end, delta: -1});
204 });
205 points.sort((a, b) => a.position - b.position);
206 points.push({position: end, delta: 0});
207 // The left and the right limit of the sliding window.
208 var left = new WindowEndpoint(start, end, points);
209 var right = new WindowEndpoint(start, end, points);
210 // Advance the right end-point until we get the correct window size.
211 while (right.position - left.position < timeWindow)
212 right.advance(timeWindow - (right.position - left.position));
213 while (right.index < points.length) {
214 // Advance the window end-points by the largest possible amount
215 // without jumping over a point.
216 var remainder = Math.min(left.remainder, right.remainder);
217 var position1 = left.position;
218 var value1 = right.pause - left.pause;
219 left.advance(remainder);
220 right.advance(remainder);
221 // Add a new mutator utilization segment only if it is non-trivial.
222 if (remainder > 0) {
223 var position2 = left.position;
224 var value2 = right.pause - left.pause;
225 mu.push(position1, 1.0 - value1 / timeWindow,
226 position2, 1.0 - value2 / timeWindow);
227 }
228 }
229 return mu;
230 }
231
99 return { 232 return {
100 findParent: findParent, 233 findParent: findParent,
101 isIdleTask: isIdleTask, 234 isIdleTask: isIdleTask,
102 isLowMemoryEvent: isLowMemoryEvent, 235 isLowMemoryEvent: isLowMemoryEvent,
236 isV8ExecuteEvent: isV8ExecuteEvent,
237 isTopV8ExecuteEvent: isTopV8ExecuteEvent,
103 isGarbageCollectionEvent: isGarbageCollectionEvent, 238 isGarbageCollectionEvent: isGarbageCollectionEvent,
104 isTopGarbageCollectionEvent: isTopGarbageCollectionEvent, 239 isTopGarbageCollectionEvent: isTopGarbageCollectionEvent,
105 isSubGarbageCollectionEvent: isSubGarbageCollectionEvent, 240 isSubGarbageCollectionEvent: isSubGarbageCollectionEvent,
106 topGarbageCollectionEventName: topGarbageCollectionEventName, 241 topGarbageCollectionEventName: topGarbageCollectionEventName,
107 subGarbageCollectionEventName: subGarbageCollectionEventName 242 subGarbageCollectionEventName: subGarbageCollectionEventName,
243 unionOfIntervals: unionOfIntervals,
244 mutatorUtilization: mutatorUtilization
108 }; 245 };
109 }); 246 });
110 </script> 247 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698