OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <!-- | |
3 Copyright 2015 The Chromium Authors. All rights reserved. | |
4 Use of this source code is governed by a BSD-style license that can be | |
5 found in the LICENSE file. | |
6 --> | |
7 | |
8 <link rel="import" href="/perf_insights/mre/function_handle.html"> | |
9 <link rel="import" href="/tracing/base/range.html"> | |
10 | |
11 <script> | |
12 'use strict'; | |
13 | |
14 tr.exportTo('pie', function() { | |
15 // Conservative estimate: if we hadn't been doing anything for 1ms, we | |
16 // probably needed to wake up the CPU for this. | |
17 // TODO(skyostil): Augment this with CPU power management states. | |
18 var IDLE_THRESHOLD_MILLISECONDS = 1; | |
19 | |
20 function sanitizeReason(reason) { | |
21 // Remove any path name components (e.g., '/foo/bar/baz' or 'c:\foo\bar\baz' | |
22 // are both reduced to 'baz'). | |
23 return reason.replace(/^.*[\/\\]/, ''); | |
24 } | |
25 | |
26 function findWakeUpReason(event) { | |
27 var tqmRunTask = event.findDescendentSlice('TaskQueueManager::RunTask'); | |
28 if (tqmRunTask && tqmRunTask.subSlices.length > 0) | |
29 return tqmRunTask.subSlices[0].title; | |
30 var processTask = | |
31 event.findDescendentSlice('TaskQueueManager::ProcessTaskFromWorkQueue'); | |
32 if (processTask && | |
33 processTask.args.src_file && | |
34 processTask.args.src_func) { | |
35 return processTask.args.src_file + ':' + processTask.args.src_func; | |
36 } | |
37 if (event.title === 'MessageLoop::RunTask' && | |
38 event.args.src_file && | |
39 event.args.src_func) { | |
40 return event.args.src_file + ':' + event.args.src_func; | |
41 } | |
42 return event.title; | |
43 } | |
44 | |
45 // Estimate number of times the CPU was woken up from idle to execute | |
46 // different types of work (e.g., timer work) and the time the CPU had been | |
47 // idle before that. | |
48 // See https://goo.gl/l7V5xg. | |
49 function findWakeUpsOnThread(thread) { | |
50 var wakeUps = {}; | |
51 var foundWakeUps = false; | |
52 var lastTaskEnd = undefined; | |
53 thread.iterateAllEvents(function(event) { | |
54 if (!event.isTopLevel) | |
55 return; | |
56 var taskEnd = event.start + event.duration; | |
57 if (lastTaskEnd === undefined) { | |
58 lastTaskEnd = taskEnd; | |
59 return; | |
60 } | |
61 var sleepTime = event.start - lastTaskEnd; | |
62 var isWakeUp = sleepTime >= IDLE_THRESHOLD_MILLISECONDS; | |
63 lastTaskEnd = taskEnd; | |
64 if (!isWakeUp) | |
65 return; | |
66 var reason = sanitizeReason(findWakeUpReason(event)); | |
67 if (wakeUps[reason] === undefined) | |
68 wakeUps[reason] = {frequency: 0, sleepTimes: []}; | |
69 wakeUps[reason].frequency++; | |
70 wakeUps[reason].sleepTimes.push(sleepTime); | |
71 foundWakeUps = true; | |
72 }); | |
73 return foundWakeUps ? wakeUps : undefined; | |
74 } | |
75 | |
76 function updateThreadWakeUps(existingWakeUps, newWakeUps) { | |
77 for (var reason in newWakeUps) { | |
78 if (!(reason in existingWakeUps)) { | |
79 existingWakeUps[reason] = newWakeUps[reason]; | |
80 continue; | |
81 } | |
82 existingWakeUps[reason].frequency += newWakeUps[reason].frequency; | |
83 existingWakeUps[reason].sleepTimes = | |
84 existingWakeUps[reason].sleepTimes.concat( | |
85 newWakeUps[reason].sleepTimes); | |
86 } | |
87 } | |
88 | |
89 function mapWakeUps(result, model) { | |
90 var allWakeUps = {}; | |
91 for (var pid in model.processes) { | |
92 var process = model.processes[pid]; | |
93 for (var tid in process.threads) { | |
94 var thread = process.threads[tid]; | |
95 var wakeUps = findWakeUpsOnThread(thread); | |
96 if (!wakeUps === undefined) | |
97 continue; | |
98 if (!(thread.name in allWakeUps)) | |
99 allWakeUps[thread.name] = {}; | |
100 updateThreadWakeUps(allWakeUps[thread.name], wakeUps); | |
101 } | |
102 } | |
103 | |
104 // Normalize frequency to wake-ups/second. | |
105 // Note: if we found any wake-ups, the total duration of the trace is | |
106 // guaranteed to be positive. | |
107 var totalDurationSeconds = model.bounds.duration / 1000; | |
108 var foundAnyWakeUps = false; | |
109 for (var thread in allWakeUps) { | |
110 var threadWakeUps = allWakeUps[thread]; | |
111 for (var reason in threadWakeUps) { | |
112 threadWakeUps[reason].frequency /= totalDurationSeconds; | |
113 foundAnyWakeUps = true; | |
114 } | |
115 } | |
116 | |
117 if (!foundAnyWakeUps) { | |
118 result.addPair('wakeUps', null); | |
119 return; | |
120 } | |
121 | |
122 result.addPair('wakeUps', allWakeUps); | |
123 } | |
124 | |
125 pi.FunctionRegistry.register(mapWakeUps); | |
126 | |
127 return { | |
128 mapWakeUpsForTest: mapWakeUps | |
129 }; | |
130 }); | |
131 </script> | |
OLD | NEW |