summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html
diff options
context:
space:
mode:
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.html195
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>