Chromium Code Reviews| 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 |