OLD | NEW |
---|---|
(Empty) | |
1 <!DOCTYPE html> | |
2 <!-- | |
3 Copyright 2017 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="/tracing/base/unit.html"> | |
9 <link rel="import" href="/tracing/metrics/metric_registry.html"> | |
10 <link rel="import" href="/tracing/value/histogram.html"> | |
11 | |
12 <script> | |
13 'use strict'; | |
14 | |
15 tr.exportTo('tr.metrics.blink', function() { | |
16 function leakDetectionMetric(histograms, model) { | |
17 const pids = extractRendererPids(model); | |
18 if (pids.length === 0) { | |
19 // We couldn't find any renderer processes. | |
20 return; | |
21 } | |
22 | |
23 const chromeDumps = splitGlobalDumpsByBrowserName(model).get('chrome'); | |
24 | |
25 let sumCounter = {}; | |
26 // Add up counters for all the renderer processes. | |
27 pids.forEach(function(pid) { | |
28 if (Object.keys(sumCounter).length === 0) { | |
29 sumCounter = countLeakedBlinkObjects(chromeDumps, pid); | |
30 } else { | |
31 const counterForAnotherRenderer = | |
32 countLeakedBlinkObjects(chromeDumps, pid); | |
33 for (const key in counters) { | |
34 sumCounter[key] += counterForAnotherRenderer[key]; | |
35 } | |
36 } | |
37 }); | |
38 | |
39 for (const key in sumCounter) { | |
40 const histogram = createNumericForBlinkObjectCounts(key); | |
41 histogram.addSample(sumCounter[key]); | |
keishi
2017/09/11 07:34:16
I think we should skip adding a sample if chromeDu
yuzuchan
2017/09/13 04:48:57
Added an error logic here. Thanks.
| |
42 histograms.addHistogram(histogram); | |
43 } | |
44 } | |
45 | |
46 tr.metrics.MetricRegistry.register(leakDetectionMetric); | |
47 | |
48 const timeDurationInMs_smallerIsBetter = | |
keishi
2017/09/11 07:34:16
unused?
yuzuchan
2017/09/13 04:48:57
True! Done.
| |
49 tr.b.Unit.byName.timeDurationInMs_smallerIsBetter; | |
50 | |
51 function extractRendererPids(model) { | |
52 const modelHelper = model.getOrCreateHelper( | |
53 tr.model.helpers.ChromeModelHelper); | |
54 if (!modelHelper) { | |
55 // Chrome isn't present. | |
56 return; | |
57 } | |
58 const rendererHelpers = modelHelper.rendererHelpers; | |
59 if (!rendererHelpers) { | |
60 // We couldn't find any renderer processes. | |
61 return; | |
62 } | |
63 return Object.keys(rendererHelpers); | |
64 } | |
65 | |
66 const count_smallerIsBetter = tr.b.Unit.byName.count_smallerIsBetter; | |
67 | |
68 function createNumericForBlinkObjectCounts(name) { | |
keishi
2017/09/11 07:34:16
nit: Existing similar functions seem to use use si
yuzuchan
2017/09/13 04:48:57
Done.
| |
69 const n = new tr.v.Histogram(name, count_smallerIsBetter); | |
70 n.customizeSummaryOptions({ | |
71 avg: false, | |
72 count: true, | |
73 max: false, | |
74 min: false, | |
75 std: false, | |
76 sum: true, | |
77 percentile: [] | |
78 }); | |
79 return n; | |
80 } | |
81 | |
82 function splitGlobalDumpsByBrowserName(model) { | |
keishi
2017/09/11 07:34:16
I think we shouldn't have duplicate code so maybe
yuzuchan
2017/09/13 04:48:57
Done.
| |
83 const chromeModelHelper = | |
84 model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper); | |
85 const browserNameToGlobalDumps = new Map(); | |
86 const globalDumpToBrowserHelper = new WeakMap(); | |
87 | |
88 if (chromeModelHelper) { | |
89 chromeModelHelper.browserHelpers.forEach(function(helper) { | |
90 const globalDumps = | |
91 helper.process.memoryDumps.map(d => d.globalMemoryDump); | |
92 | |
93 globalDumps.forEach(function(globalDump) { | |
94 const existingHelper = globalDumpToBrowserHelper.get(globalDump); | |
95 if (existingHelper !== undefined) { | |
96 throw new Error('Memory dump ID clash across multiple browsers ' + | |
97 'with PIDs: ' + existingHelper.pid + ' and ' + helper.pid); | |
98 } | |
99 globalDumpToBrowserHelper.set(globalDump, helper); | |
100 }); | |
101 | |
102 makeKeyUniqueAndSet(browserNameToGlobalDumps, | |
103 tr.e.chrome.chrome_processes.canonicalizeName(helper.browserName), | |
104 globalDumps); | |
105 }); | |
106 } | |
107 return browserNameToGlobalDumps; | |
108 } | |
109 | |
110 function makeKeyUniqueAndSet(map, key, value) { | |
111 let uniqueKey = key; | |
112 let nextIndex = 2; | |
113 while (map.has(uniqueKey)) { | |
114 uniqueKey = key + nextIndex; | |
115 nextIndex++; | |
116 } | |
117 map.set(uniqueKey, value); | |
118 } | |
119 | |
120 function countLeakedBlinkObjects(dumps, pid) { | |
121 const firstCounter = countBlinkObjects(dumps[0], pid); | |
122 const lastCounter = countBlinkObjects(dumps[dumps.length - 1], pid); | |
123 const diffCounter = {}; | |
124 for (const key in lastCounter) { | |
125 diffCounter[key] = lastCounter[key] - firstCounter[key]; | |
126 } | |
127 return diffCounter; | |
128 } | |
129 | |
130 function countBlinkObjects(dump, pid) { | |
131 const counter = {}; | |
132 const processesMemoryDumps = dump.processMemoryDumps; | |
133 if (pid in processesMemoryDumps) { | |
134 const blinkObjectsDump = processesMemoryDumps[pid].memoryAllocatorDumps | |
135 .find(isBlinkObjects); | |
136 blinkObjectsDump.children.forEach(function(v) { | |
137 counter[v.name] = v.numerics.object_count.value; | |
138 }); | |
139 } | |
140 return counter; | |
141 } | |
142 | |
143 function isBlinkObjects(memoryDump) { | |
144 return memoryDump.fullName === 'blink_objects'; | |
145 } | |
146 | |
147 return { | |
148 leakDetectionMetric, | |
149 }; | |
150 }); | |
151 </script> | |
OLD | NEW |