| 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 |