diff options
Diffstat (limited to 'chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html')
-rw-r--r-- | chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html new file mode 100644 index 00000000000..33743f757a5 --- /dev/null +++ b/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html @@ -0,0 +1,195 @@ +<!DOCTYPE html> +<!-- +Copyright 2020 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="/tracing/base/math/range.html"> +<link rel="import" href="/tracing/base/unit.html"> +<link rel="import" href="/tracing/extras/chrome/chrome_processes.html"> +<link rel="import" href="/tracing/metrics/metric_registry.html"> +<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html"> +<link rel="import" href="/tracing/value/histogram.html"> + +<script> +'use strict'; + +/** + * @fileoverview This file contains implementations of PCScan metrics. PCScan + * is the algorithm that eliminates use-after-free bugs by verifying that there + * are no pointers in memory which point to explicitly freed objects before + * actually releasing their memory. + * + * pa:pcscan:<process_name>:<scanner|mutator> + * ======================== + * The overall time spent on scanning the partition alloc heap for a specific + * process either in the scanner or mutator thread (process_name can be either 'browser_process' or 'renderer_processes'). + * + * pa:pcscan:<process_name>:<scanner|mutator>:<phase> + * ======================== + * Time spent on a certain PCScan phase ('clear', 'scan' or 'sweep'). + */ +tr.exportTo('tr.metrics.pa', function() { + function pcscanMetric(histograms, model) { + function createTimeNumericForProcess(name, processName, context, desc) { + function createNumeric(name, desc) { + const n = new tr.v.Histogram(name, + tr.b.Unit.byName.timeDurationInMs_smallerIsBetter); + n.description = desc; + n.customizeSummaryOptions({ + avg: true, + count: true, + max: true, + min: true, + std: true, + sum: true}); + return n; + } + const scheme = ['pa', 'pcscan', processName, context]; + if (name) scheme.push(name); + return createNumeric(scheme.join(':'), desc); + } + + function createSizeNumericForProcess(name, processName, desc) { + function createNumeric(name, desc) { + const n = new tr.v.Histogram(name, + tr.b.Unit.byName.sizeInBytes_smallerIsBetter); + n.description = desc; + n.customizeSummaryOptions({ + avg: true, + count: true, + max: true, + min: true, + std: true, + sum: true}); + return n; + } + const scheme = ['pa', 'pcscan', processName, name]; + return createNumeric(scheme.join(':'), desc); + } + + function createPercentNumericForProcess(name, processName, desc) { + function createNumeric(name, desc) { + const n = new tr.v.Histogram(name, + tr.b.Unit.byName.normalizedPercentage_smallerIsBetter); + n.description = desc; + n.customizeSummaryOptions({ + avg: true, + count: true, + max: true, + min: true, + std: true, + sum: true}); + return n; + } + const scheme = ['pa', 'pcscan', processName, name]; + return createNumeric(scheme.join(':'), desc); + } + + + function createHistsForProcess(processName) { + return { + scanner_scan: createTimeNumericForProcess('scan', processName, 'scanner', + 'Time for scanning heap for quarantine pointers on concurrent threads'), + scanner_sweep: createTimeNumericForProcess('sweep', processName, 'scanner', + 'Time for sweeping quarantine'), + scanner_clear: createTimeNumericForProcess('clear', processName, 'scanner', + 'Time for clearing quarantine entries'), + scanner_total: createTimeNumericForProcess('', processName, 'scanner', + 'Total time for PCScan execution on concurrent threads'), + mutator_scan_stack: createTimeNumericForProcess('scan_stack', processName, 'mutator', + 'Time for scanning stack for quarantine pointers on mutator threads'), + mutator_scan: createTimeNumericForProcess('scan', processName, 'mutator', + 'Time for scanning heap for quarantine pointers on mutator threads'), + mutator_clear: createTimeNumericForProcess('clear', processName, 'mutator', + 'Time for clearing heap quarantine entries on mutator threads'), + mutator_total: createTimeNumericForProcess('', processName, 'mutator', + 'Total time for PCScan execution on mutator threads (inside safepoints)'), + survived_quarantine_size: createSizeNumericForProcess( + 'survived_quarantine_size', processName, + 'Size in bytes of survived quarantined objects after each *Scan cycle'), + survived_quarantine_percent: createPercentNumericForProcess( + 'survived_quarantine_percent', processName, + 'Percent of survived quarantined objects after a *Scan cycle relative ' + + 'to the size of quarantined objects before the cycle'), + }; + } + + function addSliceSample(hists, slice) { + if (slice.category !== 'partition_alloc') return; + if (!(slice instanceof tr.model.ThreadSlice)) return; + + if (slice.title === 'PCScan.Scanner.Scan') { + hists.scanner_scan.addSample(slice.duration); + } else if (slice.title === 'PCScan.Scanner.Sweep') { + hists.scanner_sweep.addSample(slice.duration); + } else if (slice.title === 'PCScan.Scanner.Clear') { + hists.scanner_clear.addSample(slice.duration); + } else if (slice.title === 'PCScan.Scanner') { + hists.scanner_total.addSample(slice.duration); + } else if (slice.title === 'PCScan.Mutator.ScanStack') { + hists.mutator_scan_stack.addSample(slice.duration); + } else if (slice.title === 'PCScan.Mutator.Scan') { + hists.mutator_scan.addSample(slice.duration); + } else if (slice.title === 'PCScan.Mutator.Clear') { + hists.mutator_clear.addSample(slice.duration); + } else if (slice.title === 'PCScan.Mutator') { + hists.mutator_total.addSample(slice.duration); + } + } + + function addCounterSample(hists, counter) { + if (counter.category !== 'partition_alloc') return; + if (!(counter instanceof tr.model.Counter)) return; + + for (const series of counter.series) { + for (const sample of series.samples) { + if (counter.name === 'PCScan.SurvivedQuarantineSize') { + hists.survived_quarantine_size.addSample(sample.value); + } else if (counter.name === 'PCScan.SurvivedQuarantinePercent') { + // Divide by 1000, since StatsCollector multiplies it by 1000. + hists.survived_quarantine_percent.addSample(sample.value / 1000); + } + } + } + } + + function addHistsForProcess(processHists, processHelpers) { + for (const helper of Object.values(processHelpers)) { + const processName = tr.e.chrome.chrome_processes. + canonicalizeProcessName(helper.process.name); + if (!processHists.has(processName)) { + processHists.set(processName, createHistsForProcess(processName)); + } + for (const slice of helper.process.getDescendantEvents()) { + addSliceSample(processHists.get(processName), slice); + } + for (const tid in helper.process.counters) { + addCounterSample(processHists.get(processName), helper.process.counters[tid]); + } + } + } + + const helper = + model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper); + + const processHists = new Map(); + addHistsForProcess(processHists, helper.browserHelpers); + addHistsForProcess(processHists, helper.rendererHelpers); + + for (const hists of processHists.values()) { + for (const hist of Object.values(hists)) { + histograms.addHistogram(hist); + } + } + } + + tr.metrics.MetricRegistry.register(pcscanMetric); + + return { + pcscanMetric, + }; +}); + +</script> |