| Index: tracing/tracing/metrics/system_health/web_components_metric.html
|
| diff --git a/tracing/tracing/metrics/system_health/web_components_metric.html b/tracing/tracing/metrics/system_health/web_components_metric.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a05123f40661b3535c6496b9b962ce1597fbba75
|
| --- /dev/null
|
| +++ b/tracing/tracing/metrics/system_health/web_components_metric.html
|
| @@ -0,0 +1,207 @@
|
| +<!DOCTYPE html>
|
| +<!--
|
| + Copyright 2017 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/category_util.html">
|
| +<link rel="import" href="/tracing/base/math/statistics.html">
|
| +<link rel="import" href="/tracing/metrics/metric_registry.html">
|
| +<link rel="import" href="/tracing/metrics/system_health/utils.html">
|
| +<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
|
| +<link rel="import" href="/tracing/model/timed_event.html">
|
| +<link rel="import" href="/tracing/value/histogram.html">
|
| +
|
| +<script>
|
| +'use strict';
|
| +
|
| +tr.exportTo('tr.metrics.sh', function() {
|
| + const timeDurationInMs_smallerIsBetter =
|
| + tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;
|
| +
|
| + function createHistogram(name, boundaries) {
|
| + const histogram = new tr.v.Histogram(name,
|
| + timeDurationInMs_smallerIsBetter, boundaries);
|
| + histogram.customizeSummaryOptions({
|
| + avg: true,
|
| + count: true,
|
| + max: true,
|
| + min: true,
|
| + std: true,
|
| + sum: true,
|
| + });
|
| + return histogram;
|
| + }
|
| +
|
| + function candidatesEvents(rendererHelper) {
|
| + const events = [];
|
| + for (const ev of rendererHelper.process.getDescendantEvents()) {
|
| + if (rendererHelper.isTelemetryInternalEvent(ev))
|
| + continue;
|
| + events.push(ev);
|
| + }
|
| + return events;
|
| + }
|
| +
|
| + function collectSamples(events, eventName, condition) {
|
| + const samples = [];
|
| + for (const ev of events) {
|
| + if ((!condition && ev.title === eventName) || (condition && condition(ev))) {
|
| + const timeToEvent = ev.end - ev.start;
|
| + // console.log(ev);
|
| + samples.push({
|
| + value: timeToEvent,
|
| + diagnostics: {}
|
| + });
|
| + }
|
| + }
|
| + return samples;
|
| + }
|
| +
|
| + function addSamplesToHistogram(samples, histogram) {
|
| + for (const sample of samples)
|
| + histogram.addSample(sample.value, sample.diagnostics);
|
| + }
|
| +
|
| + function addHistogram(histogramName, boundaries, eventName) {
|
| + const histogram = createHistogram(histogramName, boundareis);
|
| + histogram.description = histogramName;
|
| + }
|
| +
|
| + const DEFAULT_BOUNDARIES = tr.v.HistogramBinBoundaries
|
| + .createLinear(0, 0.05, 10)
|
| + .addExponentialBins(20e3, 20);
|
| +
|
| + class WebComponentsHistogram {
|
| + constructor({name, eventName,
|
| + boundaries = DEFAULT_BOUNDARIES,
|
| + condition }) {
|
| + this.histogram = createHistogram(name, boundaries);
|
| + // TODO: We do not need eventName if condition is given.
|
| + this.eventName = eventName || name;
|
| + this.histogram.description = name;
|
| + this.condition = condition;
|
| + }
|
| + }
|
| +
|
| + // Memo: ev:
|
| + // ev.args: TRACE_EVENT's args
|
| + // ev.args: { name: 'x-thing' }
|
| + // ev.title: "CustomElementReactionQueue::invokeReactions"
|
| + // ev.ancestorAndSubsequentSlices: Array: [p-ev, pp-ev, ppp-ev, ,,,,,]
|
| + // ev.parentSlice: Ev: p-ev
|
| +
|
| + function isDescendantEventOf(ev, f) {
|
| + if (!ev.ancestorAndSubsequentSlices)
|
| + return false;
|
| + for (const parentEv of ev.ancestorAndSubsequentSlices) {
|
| + if (f(parentEv))
|
| + return true;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + const invokeRectionsEventName = 'CustomElementReactionQueue::InvokeReactions';
|
| + const connectedEventName = 'CustomElementConnectedCallbackReaction::Invoke';
|
| +
|
| + function isXApp(ev) {
|
| + return ev.title === invokeRectionsEventName && ev.args && ev.args['name'] === 'x-app';
|
| + }
|
| +
|
| + function isXItem(ev) {
|
| + return ev.title === invokeRectionsEventName && ev.args && ev.args['name'] === 'x-item';
|
| + }
|
| +
|
| + function isXThing(ev) {
|
| + return ev.title === invokeRectionsEventName && ev.args && ev.args['name'] === 'x-thing';
|
| + }
|
| +
|
| + function isXAppConnected(ev) {
|
| + return ev.title === connectedEventName && ev.args && ev.args['name'] === 'x-app';
|
| + }
|
| +
|
| + function isXItemConnected(ev) {
|
| + return ev.title === connectedEventName && ev.args && ev.args['name'] === 'x-item';
|
| + }
|
| +
|
| + function isXThingConnected(ev) {
|
| + return ev.title === connectedEventName && ev.args && ev.args['name'] === 'x-thing';
|
| + }
|
| +
|
| + function isProcessStylesheetUnderXThing(ev) {
|
| + return ev.title === 'StyleElement::ProcessStyleSheet' && isDescendantEventOf(ev, isXThing)
|
| + }
|
| +
|
| + function webComponentsMetric(values, model) {
|
| + const groups = [
|
| + new WebComponentsHistogram({ name: 'Node::UpdateDistribution' }),
|
| + new WebComponentsHistogram({ name: 'UpdateLayoutTree' }),
|
| + new WebComponentsHistogram({ name: 'Document::UpdateStyle' }),
|
| + new WebComponentsHistogram({ name: 'CustomElementRegistry::define' }),
|
| +
|
| + new WebComponentsHistogram({ name: 'CE::invokeReactions_x-app',
|
| + eventName: invokeRectionsEventName,
|
| + condition: isXApp}),
|
| + new WebComponentsHistogram({ name: 'CE::invokeReactions_x-item',
|
| + eventName: invokeRectionsEventName,
|
| + condition: isXItem}),
|
| + new WebComponentsHistogram({ name: 'CE::invokeReactions_x-thing',
|
| + eventName: invokeRectionsEventName,
|
| + condition: isXThing}),
|
| +
|
| + new WebComponentsHistogram({ name: 'CE::connected_x-xpp',
|
| + eventName: connectedEventName,
|
| + condition: isXAppConnected}),
|
| + new WebComponentsHistogram({ name: 'CE::connected_x-item',
|
| + eventName: connectedEventName,
|
| + condition: isXItemConnected}),
|
| + new WebComponentsHistogram({ name: 'CE::connected_x-thing',
|
| + eventName: connectedEventName,
|
| + condition: isXThingConnected}),
|
| +
|
| + new WebComponentsHistogram({ name: 'StyleElement::ProcessStyleSheet' }),
|
| + new WebComponentsHistogram({ name: 'StyleElement::ProcessStyleSheet_under_x-thing',
|
| + eventName: 'StyleElement::ProcessStyleSheet',
|
| + condition: isProcessStylesheetUnderXThing }),
|
| +
|
| + new WebComponentsHistogram({ name: 'StyleElement::Process' }),
|
| + new WebComponentsHistogram({ name: 'StyleElement::CreateSheet' }),
|
| + new WebComponentsHistogram({ name: 'StyleEngine::CreateSheet' }),
|
| + new WebComponentsHistogram({ name: 'StyleEngine::CreateInline' }),
|
| +
|
| + new WebComponentsHistogram({ name: 'StyleSheetContents::CheckLoaded' }),
|
| +
|
| + new WebComponentsHistogram({ name: 'FrameView::performLayout' }),
|
| +
|
| + // new WebComponentsHistogram({ name: 'EventPath::initialize' }),
|
| + // new WebComponentsHistogram({ name: 'EventPath::calculatePath' }),
|
| + // new WebComponentsHistogram({ name: 'EventPath::calculateTreeOrderAndSetNearestAncestorClosedTree' }),
|
| + // new WebComponentsHistogram({ name: 'EventPath::calculateAdjustedTargets' }),
|
| + // new WebComponentsHistogram({ name: 'EventPath::adjustForRelatedTarget' }),
|
| + ];
|
| + const chromeHelper = model.getOrCreateHelper(
|
| + tr.model.helpers.ChromeModelHelper);
|
| + for (const pid in chromeHelper.rendererHelpers) {
|
| + const rendererHelper = chromeHelper.rendererHelpers[pid];
|
| + if (rendererHelper.isChromeTracingUI)
|
| + continue;
|
| +
|
| + const events = candidatesEvents(rendererHelper);
|
| + for (const group of groups) {
|
| + addSamplesToHistogram(collectSamples(events, group.eventName, group.condition),
|
| + group.histogram);
|
| + }
|
| + }
|
| + for (const group of groups) {
|
| + values.addHistogram(group.histogram);
|
| + }
|
| + }
|
| +
|
| + tr.metrics.MetricRegistry.register(webComponentsMetric);
|
| +
|
| + return {
|
| + webComponentsMetric,
|
| + };
|
| +});
|
| +</script>
|
|
|