| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <link rel="import" href="/perf_insights/mappers/thread_grouping.html"> |
| <link rel="import" href="/perf_insights/mre/function_handle.html"> |
| <link rel="import" href="/tracing/model/flow_event.html"> |
| <link rel="import" href="/tracing/model/slice.html"> |
| <link rel="import" href="/tracing/value/numeric.html"> |
| <link rel="import" href="/tracing/value/unit.html"> |
| |
| <script> |
| 'use strict'; |
| |
| tr.exportTo('pi.m', function() { |
| var DURATION_NUMERIC_BUILDER = tr.v.NumericBuilder.createLinear( |
| tr.v.Unit.byName.timeDurationInMs, |
| tr.b.Range.fromExplicitRange(0, 250), 50); |
| |
| function taskInfoMapFunction(result, model) { |
| var canonicalUrl = model.canonicalUrl; |
| var threadGrouping = new pi.m.ThreadGrouping(); |
| threadGrouping.autoInitUsingHelpers(model); |
| addTimeInQueue(result, canonicalUrl, model, threadGrouping); |
| addTopLevelTasksDuration(result, canonicalUrl, model, threadGrouping); |
| } |
| |
| function eatTrailingDigits(str) { |
| return str && str.replace(/[\d/]*$/, ''); |
| } |
| |
| function histogramsToDict(dict) { |
| for (var process in dict) { |
| for (var thread in dict[process]) { |
| dict[process][thread] = dict[process][thread].asDict(); |
| } |
| } |
| } |
| |
| function addTimeInQueue(result, canonicalUrl, model, threadGrouping) { |
| var timeInQueue = {}; |
| model.flowEvents.forEach(function(flowEvent) { |
| if (!flowEvent.endSlice instanceof tr.model.Slice) |
| return; |
| var thread = flowEvent.endSlice && flowEvent.endSlice.parentContainer; |
| if (!thread) |
| return; |
| var process = thread.getProcess(); |
| if (!process) |
| return; |
| var threadName = eatTrailingDigits(thread.name) || 'Unknown'; |
| var processName = threadGrouping.getGroupNameForThread(thread); |
| addToHistogram(timeInQueue, processName, threadName, flowEvent.duration, |
| canonicalUrl); |
| }); |
| histogramsToDict(timeInQueue); |
| result.addPair('time_spent_in_queue', timeInQueue); |
| } |
| |
| function addTopLevelTasksDuration(result, canonicalUrl, model, |
| threadGrouping) { |
| var timeInTask = {}; |
| var cpuTimeInTask = {}; |
| model.getAllThreads().forEach(function(thread) { |
| var process = thread.getProcess(); |
| if (!process) |
| return; |
| var threadName = eatTrailingDigits(thread.name) || thread.tid; |
| var processName = threadGrouping.getGroupNameForThread(thread); |
| if (!thread.sliceGroup.length) |
| return; |
| thread.sliceGroup.slices.forEach(function(slice) { |
| if (!isTopLevelTask(slice)) |
| return; |
| addToHistogram(timeInTask, processName, threadName, slice.duration, |
| canonicalUrl); |
| addToHistogram(cpuTimeInTask, processName, threadName, |
| slice.cpuDuration, canonicalUrl); |
| }); |
| }); |
| histogramsToDict(timeInTask); |
| result.addPair('time_spent_in_top_level_task', timeInTask); |
| histogramsToDict(cpuTimeInTask); |
| result.addPair('cpu_time_spent_in_top_level_task', cpuTimeInTask); |
| } |
| |
| // A slice is top level if it's on the receiving end of a post task and no |
| // slice above it is. |
| function isTopLevelTask(slice) { |
| if (!slice.inFlowEvents.length) |
| return false; |
| return !slice.parentSlice || !isTopLevelTask(slice.parentSlice); |
| } |
| |
| function addToHistogram(dict, processName, threadName, value, url) { |
| dict[processName] = dict[processName] || {}; |
| dict[processName][threadName] = dict[processName][threadName] || |
| DURATION_NUMERIC_BUILDER.build(); |
| dict[processName][threadName].add(value, url); |
| } |
| |
| pi.FunctionRegistry.register(taskInfoMapFunction); |
| |
| // Exporting for tests. |
| return { |
| taskInfoMapFunctionForTest: taskInfoMapFunction |
| }; |
| }); |
| </script> |