aboutsummaryrefslogtreecommitdiff
path: root/catapult/systrace
diff options
context:
space:
mode:
authorIsabelle Taylor <taylori@google.com>2019-08-07 11:33:08 +0100
committerIsabelle Taylor <taylori@google.com>2019-08-07 14:55:45 +0000
commitc0de1d982ab4d1b375226ce8eaaba33d1d2c13b2 (patch)
treed00862cb1a1556c28c10469e6156b9d26ca1b51b /catapult/systrace
parenta52622800007a447105f938c99a027cc8908a09b (diff)
downloadchromium-trace-c0de1d982ab4d1b375226ce8eaaba33d1d2c13b2.tar.gz
Update catapult to latest version (76a241669)
git log --oneline --no-merges 625dca847..76a241669 tracing systrace 76a241669 Update to use traceconv 1e6b12d6c merge SDP data into a trace b92719d94 [LCP] Support LargestContentfulPaint for Telemetry 1703718a7 Record traces as artifacts 6d47875c4 systrace: Update traceconv version 2b0f630c6 Clarify the error message for Trace View picture debugging 8a9aee74a Tracing: factor out serializing code 566ad9545 rendering: Add diagnostic data for janks. 24b441ff9 Implement Visually Complete at 2s Metric 0c9a952c8 Fixed symbolize of win traces with breakpad syms performed on linux f550dbf1f [catapult] Remove unit-info.json ef2cd5094 rendering: Include 'benchmark' for 'Rendering' and 'UI Rendering'. 0852b11fa interaction records: Use segments from user-model. 9398b3687 Fix media video playback metrics -- take 2 1750292dc Override traceUrl from telemetry by the one from command arg 0fa679da5 Support Cast trace symbolization 5343c596b Adding a min limit of frame segments to calulate frame_times 93cd912aa [metrics] Optimize V8 and Blink GC metrics c68abdbb8 Revert "Fix media video playback metrics." 3344e16e5 Fix media video playback metrics. f8aef9991 Update metrics for Blink GC e80772c3e Add a new total_rendering metric f239adeee Add layout shift score to loading metric. a948316f5 systrace: bump trace to text version 63ab0c82e [FCP++] Filter loading image and text candidate dad31e0cc systrace: update trace_to_text sha c9cf972dc rendering: Fix handling unsual traces. fd64d5d2d rendering: Fix running the metric on non-renderer stories. 0aa89afda Remove unused chrome_v8.json testdata file 578d0b904 rendering: Process presentation-timestamp if available. ff395373a Pass Blink image decode TRACE_EVENT timing to rendering_metrics. 4dd0e5d36 removed summary_options from metrics which are reporting only one value 7ec38a401 [ftrace importer] Improve dma-fence parser 79cc5111e [ftrace importer] Rename fence parser f164714b5 [tracing] Add a timeout to metrics calculations 876651e18 [tracing] Fix up OWNERS files. 4f15e5774 [tracing] Separate trace data writing and reading 2dd550aaf Respect enabled by default categories in "manually select settings" 5b26b374b [Telemetry/Metrics] Skip complexity of map_runner.py when only running a single trace. 8c4839fee Reland "[trace_data] Add AddTraceFileFor method" 2e2998717 Revert "[trace_data] Add AddTraceFileFor method" b00da16c3 [trace_data] Add AddTraceFileFor method 7b3e75637 [FCP++] Report FCP++ as Telemetry metric a9c4beb56 Add tracing:convert_chart_json gn target. a606a564b Avoid spread operator in findToplevelSchedulerTasks 7f8529c21 Display median and 90th% in multi-event-sub-view 072a6f14b Add a metric that tracks native code memory footprint. 7b04f5a1f [Tracing] Fix flow arrows for large traces 9c13a9911 Add grouping for Maps and DescriptorArrays. c8ea4478e Fixing values for timeToFirstViewportReady and aboveTheFoldLoadedToVisible 57a7c38dd rendering: Remove breakdowns for thread-time metrics. db7629d5b [PerSecond] Implement Per-second breakdown metrics 5193bcc10 Refactor duplicate getNetworkEventsInRange() 139441f05 [tracing] Add trace_data_builder.OpenTraceHandleFor 2d11abbb3 [systrace] Replace generate_random_filename_for_test with tempfile_ext bc2a48ba8 [tracing] Restrict writing unstructured trace data 1b12fa2c0 Protect add_reserved_diagnostics against empty HistogramSets. 71c6104a1 [tracing] Delete some dead code in trace_data 18f984114 [tracing] Prepare new API for TraceDataBuilder 45510bdf4 [tracing] Remove active_parts from trace data object 7b71bd28a Create chrome tracing alerts for missed frames 869dc82af Rendering Metrics: step 3 of removing redundant metrics 4f8e8775d tracing: Terminate work-queue if all tasks are done. 0039d0daf tracing: Do not start unnecessary threads. bf564e0be tracing: Handle error running vinn. 0513e38b9 Append ImageFrameGenerator::decodeToYUV to imageDecode tracing category 9d76caaa2 Add WebXR metric d297d566a Add testGotClockSyncMarkers() test 6ee619e4f Remove duplicate code from bad merge. 520d06f41 Deserialize a new HistogramSet JSON format. ca6432e20 HistogramSets: Validate loop index 0d1d8c12e Serialize a new HistogramSet JSON format. f6100576b Include category and name as part of flow ids 5c1c31e62 Add generateColors() for spa a4323c9b8 Split Histogram.statistics_scalars into statistics_names, GetStatisticScalar. fc67ab6f7 Serialize DiagnosticMap 285988459 Remove old VR aliases c4408e882 Deserialize DiagnosticMap. e4d7378b5 speed: Use gzip compression for trace data. 6fc8962f1 android_startup_metric: Add more diagnostic measurements e8ab7db4d Tracing: handle empty list of ranges 34d4c3e64 Short unit improvement direction suffixes 29b3f3626 Fix VR frameCycleDurationMetric 770b18b65 [tracing] Remove _TraceData.__getitem__ method 084703e4e Add Diagnostic.serialize(). 9f11b438f Add Diagnostic.deserialize() 04e1b2eeb Add stableId to memory dumps. b3d62293b Add HistogramSet OWNERS 0d71048a2 Revert "Rename add_reserved_diagnostics to prepare_upload, keep alias." 2e19f1c11 Add stableId to instant events. 6d35d61a1 Rename add_reserved_diagnostics to prepare_upload, keep alias. cb6a56815 [Telemetry] Change tb.StopTracing() to return just trace data 1a351b413 Chrome Tracing: Add jank_count for tracing 31798d055 Add HistogramSerializer 82959c838 Add HistogramDeserializer 700a8b6c1 Metrics: parse UMA histograms from traces 75a89f272 Updated brushing states for tracing UI. Events highlighted from Find Matches or from Analysis Views will be brightened instead of dimmed. Orginally, they were dimmed while all other events were also dimmed to grey, making it hard to spot the highlighted events (it seems this was introduced here: https://codereview.chromium.org/1429863004/patch/1/10007). c276258fd Reland add_reserved_diagnostics --max_size 610e624a4 [tracing] Make Python's _TraceData object private 64102c084 Revert "Output some debug info when getTraceCategories fails" cbea2ee3d Revert "Fix debug string for validateTraceCategories error." 38769c1f9 Remove spurious "o" added in crrev.com/c/1455628. Sorry! 130074321 Fix ftrace clock sync errors on CrOS 4e2870c4b Add a 'UI Rendering' option for recording. fb5956e43 Use start address provided by metadata for symbolizer 78b1c61ff [Telemetry] Remove inspector_importer b486e0449 Revert "add_reserved_diagnostics --max_size" fd97b5ad5 Fix debug string for validateTraceCategories error. adcf2fcf3 add_reserved_diagnostics --max_size da7318dd0 Output some debug info when getTraceCategories fails 828e54e90 Add python Histogram.Create(). 2f6aedbe4 adb_profile_chrome_startup: Enable Perfetto tracing back-end 514fe3e70 95% Confidence Intervals for mean statistic: cf13e722c Port legacy unit info to Python 25d49af2e Fix sum field in gtest_json_converter 348883443 Reland Remove TagMap. b98ec701f Revert "Ignore zeros in Breakdowns." c329a12f2 [ftrace importer] Add ion heap parser 78448d900 Plumb the trace buffer size for atrace 464917736 Fix handling of perfetto protobuf on mac 50be11941 Revert "Remove TagMap." df10be749 Fix gtest conversion multiplier 8eb35ff49 Adding timeToFirstViewportReady metric b89908927 Remove TagMap. 8dc09eb07 Truncate serialized floats in HistogramSet JSON. 6eeb1d2fc Remove support for legacy json formats from render_histograms_viewer. 222f2c0b2 Use the HTMLImports polyfill 9bfcc696e Relax an assertion in heap_profiler_unittest. 79517a0b0 Clean up a comment in generic_set.py. 3ad33e96e Ignore zeros in Breakdowns. 4ec170a7b Remove shortName from Histogram. 3511bed44 Remove RelatedHistograms from tbmv2. 550c3d05d Display link tuples in generic-set-span. 089fbe2fa Add a script to add a label to Histograms. 40737696f Assert that shared diagnostic types are valid. ebf0d23ee Add gtest perf test conversion script 16717a6dd Reland the safe parts of "Syntax updates for Polymer 2.0." d1cc7e545 Fix to show visualizations for multiple benchmarks in one results file 7c1d51b16 Histogram-based heap profiler f396a42a9 Add a way to visualize when raster tasks are performed. e90aa2a4b Fixes for Metrics Visualization 9310cd73f Replace RelatedHistogramMap with RelatedNameMap+Breakdown in EQT metric. 7d95d86a6 Replace RelatedHistogramMap with RelateNameMap+Breakdown in runtimeStatsMetric. 8964ef5af Changed average raster task times metric a382be45b Allow the caller to specify tracing categories for adb_profile_chrome_startup 296353761 Split metrics_visualization into two files 277cdb9bc Tab_Switching results calculation includes unwanted data b4581eb21 [ftrace importer] Add rss stat parser 8435aca79 [tracing] Check for both type and value presence d18d6c7c7 Remove precision check from the EQT metric calculation 4415dc697 Add more debug info for an EQT failure check 4f870714b Remove myself from Catapult OWNERS files ee85992c5 Fix atrace_agent on pre-M devices 3dc39538b Create method to add shared diagnostics to histograms not created through tbmv2 417678103 Added new pipeline metrics 82f5c3a6c Show hover text for transparent values and fixed hide Y Axis 27e047e04 Fix crashes on performance.measure name parsing. 5913160a7 Refactoring remaining diagnostics in histogram.py to diagnostics dir. b81a9c76c [soundwave] Run soundwave scripts using vpython 35d4c6c88 Fix merging single-bin Histograms with multi-bin Histograms. b0c06d4b4 rendering: Fix tasks_per_frame_ unit. 415cd78ad Telemetry: Fix a bug in sorting latency events c14a383e6 androidStartupMetric: skip FCP events when startup is missing a1878a947 Update computation of load bias to handle CrOS edge cases. d1eeca86a compare_samples: trivial fix in Main cdd16e094 Support uploading to dev_appserver.py 7ec848b2b Permit lack of value.name in convertChartJson. 44b1d78c3 androidStartupMetric: workarund for missing main entry point marker 03ce64d28 Telemetry: tasks_per_frame in TBMv2 468ff3e5a Ensure that the mutator utilization metric always makes progress. a8f088180 Telemetry: migrate thread_*_cpu_time_per_frame f92910970 Basic Python3 compatibility for catapult tracing a65a6b400 Fix summary options for the MMU metric histogram. Bug: 137786880 Test: manual run of ./systrace.py Merged-In: I2c1fbbefae7a751de17bf7e38da8a8fd2f4bd32f (cherry picked from commit eba0701e9764b55be4bb397184efc5c3f0e9c9ce) Change-Id: I2c1fbbefae7a751de17bf7e38da8a8fd2f4bd32f
Diffstat (limited to 'catapult/systrace')
-rwxr-xr-xcatapult/systrace/bin/adb_profile_chrome_startup7
-rw-r--r--catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py2
-rw-r--r--catapult/systrace/profile_chrome/perf_tracing_agent.py1
-rw-r--r--catapult/systrace/profile_chrome/profiler_unittest.py2
-rw-r--r--catapult/systrace/systrace/output_generator.py13
-rw-r--r--catapult/systrace/systrace/output_generator_unittest.py103
-rwxr-xr-xcatapult/systrace/systrace/run_systrace.py1
-rw-r--r--catapult/systrace/systrace/systrace_trace_viewer.html1333
-rw-r--r--catapult/systrace/systrace/tracing_agents/atrace_agent.py33
-rwxr-xr-xcatapult/systrace/systrace/tracing_agents/atrace_agent_unittest.py12
-rw-r--r--catapult/systrace/systrace/tracing_agents/atrace_from_file_agent.py45
-rwxr-xr-xcatapult/systrace/systrace/tracing_agents/atrace_from_file_agent_unittest.py34
-rw-r--r--catapult/systrace/systrace/tracing_controller.py8
-rw-r--r--catapult/systrace/systrace/util.py14
14 files changed, 1010 insertions, 598 deletions
diff --git a/catapult/systrace/bin/adb_profile_chrome_startup b/catapult/systrace/bin/adb_profile_chrome_startup
index 6bd3270c..42b37dfc 100755
--- a/catapult/systrace/bin/adb_profile_chrome_startup
+++ b/catapult/systrace/bin/adb_profile_chrome_startup
@@ -53,6 +53,12 @@ def _CreateOptionParser():
parser.add_option('-t', '--time', help='Stops tracing after N seconds, 0 to '
'manually stop (startup trace ends after at most 5s).',
default=5, metavar='N', type='int', dest='trace_time')
+ parser.add_option('-c', '--chrome_categories', help='Chrome tracing '
+ 'categories to record.', default=_DEFAULT_CHROME_CATEGORIES,
+ type='string')
+ parser.add_option('-u', '--atrace-buffer-size', help='Number of bytes to'
+ ' be used for capturing atrace data', type='int',
+ default=None, dest='trace_buf_size')
parser.add_option_group(chrome_startup_tracing_agent.add_options(parser))
parser.add_option_group(atrace_agent.add_options(parser))
@@ -91,7 +97,6 @@ def main():
# removed.
options.ring_buffer = False
options.trace_memory = False
- options.chrome_categories = _DEFAULT_CHROME_CATEGORIES
if options.atrace_categories in ['list', 'help']:
atrace_agent.list_categories(atrace_agent.get_config(options))
diff --git a/catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py b/catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py
index c1456c11..53be30ce 100644
--- a/catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py
+++ b/catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py
@@ -40,7 +40,7 @@ class ChromeStartupTracingAgent(tracing_agents.TracingAgent):
def _SetupTracing(self):
# TODO(lizeb): Figure out how to clean up the command-line file when
# _TearDownTracing() is not executed in StopTracing().
- flags = ['--trace-startup']
+ flags = ['--trace-startup', '--enable-perfetto']
if self._trace_time is not None:
flags.append('--trace-startup-duration={}'.format(self._trace_time))
self._flag_changer.AddFlags(flags)
diff --git a/catapult/systrace/profile_chrome/perf_tracing_agent.py b/catapult/systrace/profile_chrome/perf_tracing_agent.py
index c7ad9468..1414905e 100644
--- a/catapult/systrace/profile_chrome/perf_tracing_agent.py
+++ b/catapult/systrace/profile_chrome/perf_tracing_agent.py
@@ -26,7 +26,6 @@ try:
# pylint: disable=F0401,no-name-in-module,wrong-import-position
from telemetry.internal.platform.profiler import android_profiling_helper
from telemetry.internal.util import binary_manager
- # pylint: enable=wrong-import-position
except ImportError:
android_profiling_helper = None
binary_manager = None
diff --git a/catapult/systrace/profile_chrome/profiler_unittest.py b/catapult/systrace/profile_chrome/profiler_unittest.py
index 9b35753d..cd7af956 100644
--- a/catapult/systrace/profile_chrome/profiler_unittest.py
+++ b/catapult/systrace/profile_chrome/profiler_unittest.py
@@ -18,7 +18,7 @@ class ProfilerTest(unittest.TestCase):
def setUp(self):
ui.EnableTestMode()
self._tracing_options = tracing_controller.TracingControllerConfig(None,
- None, None, None, None, None, None, None, None)
+ None, None, None, None, None, None, None, None, None)
@decorators.ClientOnlyTest
def testCaptureBasicProfile(self):
diff --git a/catapult/systrace/systrace/output_generator.py b/catapult/systrace/systrace/output_generator.py
index 9b2666e1..b1dc2759 100644
--- a/catapult/systrace/systrace/output_generator.py
+++ b/catapult/systrace/systrace/output_generator.py
@@ -33,12 +33,13 @@ _SYSTRACE_HEADER = 'Systrace'
def NewGenerateHTMLOutput(trace_results, output_file_name):
- trace_data_builder = trace_data.TraceDataBuilder()
- for trace in trace_results:
- trace_data_part = _SYSTRACE_TO_TRACE_DATA_NAME_MAPPING.get(
- trace.source_name)
- trace_data_builder.AddTraceFor(trace_data_part, trace.raw_data)
- trace_data_builder.AsData().Serialize(output_file_name, _SYSTRACE_HEADER)
+ with trace_data.TraceDataBuilder() as builder:
+ for trace in trace_results:
+ trace_data_part = _SYSTRACE_TO_TRACE_DATA_NAME_MAPPING.get(
+ trace.source_name)
+ builder.AddTraceFor(
+ trace_data_part, trace.raw_data, allow_unstructured=True)
+ builder.Serialize(output_file_name, _SYSTRACE_HEADER)
def GenerateHTMLOutput(trace_results, output_file_name):
diff --git a/catapult/systrace/systrace/output_generator_unittest.py b/catapult/systrace/systrace/output_generator_unittest.py
index dba47712..23473169 100644
--- a/catapult/systrace/systrace/output_generator_unittest.py
+++ b/catapult/systrace/systrace/output_generator_unittest.py
@@ -9,11 +9,11 @@ import json
import os
import unittest
+from py_utils import tempfile_ext
from systrace import decorators
from systrace import output_generator
from systrace import trace_result
from systrace import update_systrace_trace_viewer
-from systrace import util
from tracing.trace_data import trace_data as trace_data_module
@@ -52,18 +52,14 @@ class OutputGeneratorTest(unittest.TestCase):
update_systrace_trace_viewer.SYSTRACE_TRACE_VIEWER_HTML_FILE))
with open(ATRACE_DATA) as f:
atrace_data = f.read().replace(" ", "").strip()
- trace_results = [trace_result.TraceResult('systemTraceEvents',
- atrace_data)]
- output_file_name = util.generate_random_filename_for_test()
- final_path = output_generator.GenerateHTMLOutput(trace_results,
- output_file_name)
+ trace_results = [trace_result.TraceResult('systemTraceEvents', atrace_data)]
+ with tempfile_ext.TemporaryFileName() as output_file_name:
+ output_generator.GenerateHTMLOutput(trace_results, output_file_name)
with open(output_file_name, 'r') as f:
- output_generator.GenerateHTMLOutput(trace_results, f.name)
html_output = f.read()
- trace_data = (html_output.split(
- '<script class="trace-data" type="application/text">')[1].split(
- '</script>'))[0].replace(" ", "").strip()
- os.remove(final_path)
+ trace_data = (html_output.split(
+ '<script class="trace-data" type="application/text">')[1].split(
+ '</script>'))[0].replace(" ", "").strip()
# Ensure the trace data written in HTML is located within the
# correct place in the HTML document and that the data is not
@@ -74,49 +70,42 @@ class OutputGeneratorTest(unittest.TestCase):
@decorators.HostOnlyTest
def testHtmlOutputGenerationFormatsMultipleTraces(self):
trace_results = []
- trace_data_builder = trace_data_module.TraceDataBuilder()
-
- with open(ATRACE_DATA) as fp:
- atrace_data = fp.read()
- trace_results.append(
- trace_result.TraceResult('systemTraceEvents', atrace_data))
- trace_data_builder.AddTraceFor(trace_data_module.ATRACE_PART, atrace_data)
-
- with open(ATRACE_PROCESS_DUMP_DATA) as fp:
- atrace_process_dump_data = fp.read()
- trace_results.append(
- trace_result.TraceResult('atraceProcessDump', atrace_process_dump_data))
- trace_data_builder.AddTraceFor(trace_data_module.ATRACE_PROCESS_DUMP_PART,
- atrace_process_dump_data)
-
- with open(COMBINED_PROFILE_CHROME_DATA) as fp:
- chrome_data = fp.read()
- trace_results.append(
- trace_result.TraceResult('traceEvents', json.loads(chrome_data)))
- trace_data_builder.AddTraceFor(
- trace_data_module.CHROME_TRACE_PART, json.loads(chrome_data))
-
- trace_results.append(
- trace_result.TraceResult('systraceController', str({})))
- trace_data_builder.AddTraceFor(trace_data_module.TELEMETRY_PART, {})
-
- try:
- data_builder_out = util.generate_random_filename_for_test()
- output_generator_out = util.generate_random_filename_for_test()
- output_generator.GenerateHTMLOutput(trace_results, output_generator_out)
- trace_data_builder.AsData().Serialize(data_builder_out, 'Systrace')
-
- output_generator_md5sum = hashlib.md5(
- open(output_generator_out, 'rb').read()).hexdigest()
- data_builder_md5sum = hashlib.md5(
- open(data_builder_out, 'rb').read()).hexdigest()
-
- self.assertEqual(output_generator_md5sum, data_builder_md5sum)
- finally:
- def del_if_exist(path):
- try:
- os.remove(path)
- except IOError:
- pass
- del_if_exist(output_generator_out)
- del_if_exist(data_builder_out)
+ with trace_data_module.TraceDataBuilder() as trace_data_builder:
+ with open(ATRACE_DATA) as fp:
+ atrace_data = fp.read()
+ trace_results.append(
+ trace_result.TraceResult('systemTraceEvents', atrace_data))
+ trace_data_builder.AddTraceFor(trace_data_module.ATRACE_PART, atrace_data,
+ allow_unstructured=True)
+
+ with open(ATRACE_PROCESS_DUMP_DATA) as fp:
+ atrace_process_dump_data = fp.read()
+ trace_results.append(trace_result.TraceResult(
+ 'atraceProcessDump', atrace_process_dump_data))
+ trace_data_builder.AddTraceFor(trace_data_module.ATRACE_PROCESS_DUMP_PART,
+ atrace_process_dump_data,
+ allow_unstructured=True)
+
+ with open(COMBINED_PROFILE_CHROME_DATA) as fp:
+ chrome_data = json.load(fp)
+ trace_results.append(
+ trace_result.TraceResult('traceEvents', chrome_data))
+ trace_data_builder.AddTraceFor(
+ trace_data_module.CHROME_TRACE_PART, chrome_data)
+
+ trace_results.append(
+ trace_result.TraceResult('systraceController', str({})))
+ trace_data_builder.AddTraceFor(trace_data_module.TELEMETRY_PART, {})
+
+ with tempfile_ext.NamedTemporaryDirectory() as temp_dir:
+ data_builder_out = os.path.join(temp_dir, 'data_builder.html')
+ output_generator_out = os.path.join(temp_dir, 'output_generator.html')
+ output_generator.GenerateHTMLOutput(trace_results, output_generator_out)
+ trace_data_builder.Serialize(data_builder_out, 'Systrace')
+
+ output_generator_md5sum = hashlib.md5(
+ open(output_generator_out, 'rb').read()).hexdigest()
+ data_builder_md5sum = hashlib.md5(
+ open(data_builder_out, 'rb').read()).hexdigest()
+
+ self.assertEqual(output_generator_md5sum, data_builder_md5sum)
diff --git a/catapult/systrace/systrace/run_systrace.py b/catapult/systrace/systrace/run_systrace.py
index 2ca85046..15a39a38 100755
--- a/catapult/systrace/systrace/run_systrace.py
+++ b/catapult/systrace/systrace/run_systrace.py
@@ -47,7 +47,6 @@ from systrace.tracing_agents import atrace_from_file_agent
from systrace.tracing_agents import atrace_process_dump
from systrace.tracing_agents import ftrace_agent
from systrace.tracing_agents import walt_agent
-# pylint: enable=wrong-import-position
ALL_MODULES = [atrace_agent, atrace_from_file_agent, atrace_process_dump,
diff --git a/catapult/systrace/systrace/systrace_trace_viewer.html b/catapult/systrace/systrace/systrace_trace_viewer.html
index bdb0cd93..ad9472e1 100644
--- a/catapult/systrace/systrace/systrace_trace_viewer.html
+++ b/catapult/systrace/systrace/systrace_trace_viewer.html
@@ -108,7 +108,7 @@
text-decoration: underline;
}
</style>
- <a href="{{href}}" on-click="onClicked_" on-mouseenter="onMouseEnter_" on-mouseleave="onMouseLeave_"><content></content></a>
+ <a href="{{href}}" on-click="onClicked_" on-mouseenter="onMouseEnter_" on-mouseleave="onMouseLeave_"><slot></slot></a>
</template>
</dom-module><dom-module id="tr-ui-b-table">
@@ -956,6 +956,7 @@
</style>
<div style="padding-right: 200px">
<div style="float:right; border-style: solid; border-width: 1px; padding:20px">
+ X no feedback<br/>
0 uninitialized<br/>
. premonomorphic<br/>
1 monomorphic<br/>
@@ -1113,8 +1114,8 @@
</template>
</div>
<div id="subView"></div>
- <content>
- </content>
+ <slot>
+ </slot>
</template>
</dom-module><dom-module id="tr-ui-a-memory-dump-heap-details-breakdown-view">
<template>
@@ -1552,25 +1553,10 @@
<div id="links"></div>
</template>
</dom-module><dom-module id="tr-v-ui-related-event-set-span">
-</dom-module><dom-module id="tr-v-ui-related-histogram-map-span">
- <template>
- <tr-ui-b-table id="table"></tr-ui-b-table>
- </template>
</dom-module><dom-module id="tr-v-ui-scalar-diagnostic-span">
<template>
<tr-v-ui-scalar-span id="scalar"></tr-v-ui-scalar-span>
</template>
-</dom-module><dom-module id="tr-v-ui-tag-map-span">
- <template>
- <style>
- #hide, #generic {
- display: none;
- }
- </style>
- <button id="show" on-click="onShow_">Show</button>
- <button id="hide" on-click="onHide_">Hide</button>
- <tr-ui-a-generic-object-view id="generic"></tr-ui-a-generic-object-view>
- </template>
</dom-module><dom-module id="tr-v-ui-unmergeable-diagnostic-set-span">
</dom-module><dom-module id="tr-v-ui-diagnostic-map-table">
<template>
@@ -2052,7 +2038,7 @@
vertical-align: top;
}
</style>
- <content></content>
+ <slot></slot>
</template>
</dom-module><dom-module id="tr-ui-a-power-sample-table">
<template>
@@ -2204,30 +2190,30 @@
height: 525px;
}
</style>
- <content></content>
+ <slot></slot>
</template>
</dom-module><dom-module id="tr-ui-b-dropdown">
<template>
<style>
button {
- @apply(--dropdown-button);
+ @apply --dropdown-button;
}
button.open {
- @apply(--dropdown-button-open);
+ @apply --dropdown-button-open;
}
dialog {
position: absolute;
margin: 0;
padding: 1em;
border: 1px solid darkgrey;
- @apply(--dropdown-dialog);
+ @apply --dropdown-dialog;
}
</style>
<button id="button" on-tap="open">[[label]]</button>
<dialog id="dialog" on-cancel="close" on-tap="onDialogTap_">
- <content></content>
+ <slot></slot>
</dialog>
</template>
</dom-module><dom-module id="tr-ui-b-info-bar-group">
@@ -2268,7 +2254,7 @@
}
</style>
<div id="aligner">
- <content></content>
+ <slot></slot>
</div>
</template>
</dom-module><style>
@@ -2338,7 +2324,7 @@
font-size: 8pt;
}
</style>
- <content></content>
+ <slot></slot>
<div id="drag_box"></div>
<div id="hint_text"></div>
@@ -2881,7 +2867,7 @@
</tr-ui-b-info-bar-group>
</div>
<middle-container>
- <content></content>
+ <slot></slot>
<tr-ui-side-panel-container id="side_panel_container">
</tr-ui-side-panel-container>
@@ -3378,14 +3364,16 @@
padding: 4px;
font-size: 14px;
}
+
.error {
color: red;
display: none;
}
- .child_container {
+ .container {
position: relative;
display: inline-block;
+ margin-left: 15px;
}
#title {
@@ -3395,9 +3383,8 @@
}
#selectors {
- display: none;
+ display: block;
padding-bottom: 10px;
- display: none;
}
#search_page {
@@ -3427,27 +3414,157 @@
stroke: white;
}
</style>
- <div id="title">Metrics Visualization</div>
+ <span class="container" id="aggregateContainer">
+ </span>
+ <span class="container" id="pageByPageContainer">
+ <span id="selectors">
+ <span id="percentile_label">Percentile Range:</span>
+ <input class="text_input" id="start" placeholder="0"/>
+ <input class="text_input" id="end" placeholder="100"/>
+ <button id="filter" on-tap="filterByPercentile_">Filter</button>
+ <input class="text_input" id="search_page" placeholder="Page Name"/>
+ <button id="search" on-tap="searchByPage_">Search</button>
+ <span class="error" id="search_error">Sorry, could not find that page!</span>
+ </span>
+ </span>
+ <div display="block" id="submetricsContainer">
+ <span id="close">
+ <svg viewBox="0 0 128 128">
+ <line x1="28" x2="100" y1="28" y2="100"></line>
+ <line x1="28" x2="100" y1="100" y2="28"></line>
+ </svg>
+ </span>
+ </div>
+ </template>
+</dom-module><dom-module id="tr-v-ui-raster-visualization">
+ <template>
+ <style>
+ button {
+ padding: 5px;
+ font-size: 14px;
+ }
+ .error {
+ color: red;
+ display: none;
+ }
+
+ .text_input {
+ width: 200px;
+ padding: 4px;
+ font-size: 14px;
+ }
+
+ .selector_container{
+ padding: 5px;
+ }
+
+ #search {
+ display: inline-block;
+ padding-bottom: 10px;
+ }
+
+ #search_page {
+ width: 200px;
+ }
+
+ #pageSelector {
+ display: inline-block;
+ font-size: 12pt;
+ }
+
+ #close {
+ display: none;
+ vertical-align: top;
+ }
+
+ #close svg{
+ height: 1em;
+ }
+
+ #close svg line {
+ stroke-width: 18;
+ stroke: black;
+ }
+
+ #close:hover svg {
+ background: black;
+ }
+
+ #close:hover svg line {
+ stroke: white;
+ }
+ </style>
+ <span id="aggregateContainer">
+ <div>
+ <div class="selector_container">
+ <span id="select_page_label">Individual Page Results:</span>
+ <select id="pageSelector">
+ <option id="select_page" value="">Select a page</option>
+ </select>
+ </div>
+ <div class="selector_container">
+ <div id="search_page_label">Search for a page:</div>
+ <input class="text_input" id="search_page" placeholder="Page Name"/>
+ <button id="search_button">Search</button>
+ <div class="error" id="search_error">Sorry, could not find that page!</div>
+ </div>
+ </div>
+ </span>
+ <span id="pageContainer">
+ <span id="close">
+ <svg viewBox="0 0 128 128">
+ <line x1="28" x2="100" y1="28" y2="100"></line>
+ <line x1="28" x2="100" y1="100" y2="28"></line>
+ </svg>
+ </span>
+ </span>
+ </template>
+</dom-module><meta charset="utf-8"/><dom-module id="tr-v-ui-visualizations-data-container">
+ <template>
+ <style>
+ .error {
+ color: red;
+ display: none;
+ }
+
+ .sample{
+ display: none;
+ }
+
+ .subtitle{
+ font-size: 20px;
+ font-weight: bold;
+ padding-bottom: 5px;
+ }
+
+ .description{
+ font-size: 15px;
+ padding-bottom: 5px;
+ }
+
+ #title {
+ font-size: 30px;
+ font-weight: bold;
+ padding-bottom: 5px;
+ }
+ </style>
+ <div id="title">Visualizations</div>
<div class="error" id="data_error">Invalid data provided.</div>
- <div id="selectors">
- <div id="percentile_label">Percentile Range:</div>
- <input class="text_input" id="start" placeholder="0"/>
- <input class="text_input" id="end" placeholder="100"/>
- <button id="filter" on-tap="filterByPercentile_">Filter</button>
- <input class="text_input" id="search_page" placeholder="Page Name"/>
- <button id="search" on-tap="searchByPage_">Search</button>
- <div class="error" id="search_error">Sorry, could not find that page!</div>
- </div>
- <div id="container">
+ <div id="pipeline_per_frame_container">
+ <div class="subtitle">Graphics Pipeline and Raster Tasks</div>
+ <div class="description">
+ When raster tasks are completed in comparison to the rest of the graphics pipeline.<br/>
+ Only pages where raster tasks are completed after beginFrame is issued are included.
+ </div>
+ <tr-v-ui-raster-visualization id="rasterVisualization">
+ </tr-v-ui-raster-visualization>
</div>
- <div id="children">
+ <div id="metrics_container">
+ <div class="subtitle">Metrics</div>
+ <div class="description">Total amount of time taken for the indicated metrics.</div>
+ <tr-v-ui-metrics-visualization class="sample" id="metricsVisualization">
+ </tr-v-ui-metrics-visualization>
</div>
- <span id="close">
- <svg viewBox="0 0 128 128">
- <line x1="28" x2="100" y1="28" y2="100"></line>
- <line x1="28" x2="100" y1="100" y2="28"></line>
- </svg>
- </span>
</template>
</dom-module><dom-module id="tr-v-ui-histogram-set-view">
<template>
@@ -3469,6 +3586,10 @@
#container {
display: none;
}
+
+ #visualizations{
+ display: none;
+ }
</style>
<div id="zero">zero Histograms</div>
@@ -3477,8 +3598,8 @@
<tr-v-ui-histogram-set-controls id="controls">
</tr-v-ui-histogram-set-controls>
- <tr-v-ui-metrics-visualization id="metrics">
- </tr-v-ui-metrics-visualization>
+ <tr-v-ui-visualizations-data-container id="visualizations">
+ </tr-v-ui-visualizations-data-container>
<tr-v-ui-histogram-set-table id="table"></tr-v-ui-histogram-set-table>
</div>
@@ -3590,7 +3711,7 @@ if(attributes){this.mixin(this._aggregatedAttributes,attributes);}},_marshalHost
break;case Array:try{value=JSON.parse(value);}catch(x){value=null;console.warn('Polymer::Attributes: couldn`t decode Array as JSON');}
break;case Date:value=new Date(value);break;case String:default:break;}
return value;},serialize:function(value){switch(typeof value){case'boolean':return value?'':undefined;case'object':if(value instanceof Date){return value.toString();}else if(value){try{return JSON.stringify(value);}catch(x){return'';}}
-default:return value!=null?value:undefined;}}});Polymer.version="1.10.1";Polymer.Base._addFeature({_registerFeatures:function(){this._prepIs();this._prepBehaviors();this._prepConstructor();this._prepPropertyInfo();},_prepBehavior:function(b){this._addHostAttributes(b.hostAttributes);},_marshalBehavior:function(b){},_initFeatures:function(){this._marshalHostAttributes();this._marshalBehaviors();}});(function(){function resolveCss(cssText,ownerDocument){return cssText.replace(CSS_URL_RX,function(m,pre,url,post){return pre+'\''+resolve(url.replace(/["']/g,''),ownerDocument)+'\''+post;});}
+default:return value!=null?value:undefined;}}});Polymer.version="1.11.3";Polymer.Base._addFeature({_registerFeatures:function(){this._prepIs();this._prepBehaviors();this._prepConstructor();this._prepPropertyInfo();},_prepBehavior:function(b){this._addHostAttributes(b.hostAttributes);},_marshalBehavior:function(b){},_initFeatures:function(){this._marshalHostAttributes();this._marshalBehaviors();}});(function(){function resolveCss(cssText,ownerDocument){return cssText.replace(CSS_URL_RX,function(m,pre,url,post){return pre+'\''+resolve(url.replace(/["']/g,''),ownerDocument)+'\''+post;});}
function resolveAttrs(element,ownerDocument){for(var name in URL_ATTRS){var a$=URL_ATTRS[name];for(var i=0,l=a$.length,a,at,v;i<l&&(a=a$[i]);i++){if(name==='*'||element.localName===name){at=element.attributes[a];v=at&&at.value;if(v&&v.search(BINDING_RX)<0){at.value=a==='style'?resolveCss(v,ownerDocument):resolve(v,ownerDocument);}}}}}
function resolve(url,ownerDocument){if(url&&ABS_URL.test(url)){return url;}
var resolver=getUrlResolver(ownerDocument);resolver.href=url;return resolver.href||url;}
@@ -3793,9 +3914,10 @@ var bl=hbl.get(target);if(!bl){bl={};if(!Polymer.Settings.isIE||target!=window){
var key=this._boundListenerKey(eventName,methodName);bl[key]=handler;},_recallEventHandler:function(host,eventName,target,methodName){var hbl=host.__boundListeners;if(!hbl){return;}
var bl=hbl.get(target);if(!bl){return;}
var key=this._boundListenerKey(eventName,methodName);return bl[key];},_createEventHandler:function(node,eventName,methodName){var host=this;var handler=function(e){if(host[methodName]){host[methodName](e,e.detail);}else{host._warn(host._logf('_createEventHandler','listener method `'+methodName+'` not defined'));}};handler._listening=false;this._recordEventHandler(host,eventName,node,methodName,handler);return handler;},unlisten:function(node,eventName,methodName){var handler=this._recallEventHandler(this,eventName,node,methodName);if(handler){this._unlisten(node,eventName,handler);handler._listening=false;}},_listen:function(node,eventName,handler){node.addEventListener(eventName,handler);},_unlisten:function(node,eventName,handler){node.removeEventListener(eventName,handler);}});(function(){'use strict';var wrap=Polymer.DomApi.wrap;var HAS_NATIVE_TA=typeof document.head.style.touchAction==='string';var GESTURE_KEY='__polymerGestures';var HANDLED_OBJ='__polymerGesturesHandled';var TOUCH_ACTION='__polymerGesturesTouchAction';var TAP_DISTANCE=25;var TRACK_DISTANCE=5;var TRACK_LENGTH=2;var MOUSE_TIMEOUT=2500;var MOUSE_EVENTS=['mousedown','mousemove','mouseup','click'];var MOUSE_WHICH_TO_BUTTONS=[0,1,4,2];var MOUSE_HAS_BUTTONS=function(){try{return new MouseEvent('test',{buttons:1}).buttons===1;}catch(e){return false;}}();function isMouseEvent(name){return MOUSE_EVENTS.indexOf(name)>-1;}
-var SUPPORTS_PASSIVE=false;(function(){try{var opts=Object.defineProperty({},'passive',{get:function(){SUPPORTS_PASSIVE=true;}});window.addEventListener('test',null,opts);window.removeEventListener('test',null,opts);}catch(e){}}());function PASSIVE_TOUCH(){if(HAS_NATIVE_TA&&SUPPORTS_PASSIVE&&Polymer.Settings.passiveTouchGestures){return{passive:true};}}
+var SUPPORTS_PASSIVE=false;(function(){try{var opts=Object.defineProperty({},'passive',{get:function(){SUPPORTS_PASSIVE=true;}});window.addEventListener('test',null,opts);window.removeEventListener('test',null,opts);}catch(e){}}());function PASSIVE_TOUCH(eventName){if(isMouseEvent(eventName)||eventName==='touchend'){return;}
+if(HAS_NATIVE_TA&&SUPPORTS_PASSIVE&&Polymer.Settings.passiveTouchGestures){return{passive:true};}}
var IS_TOUCH_ONLY=navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);var mouseCanceller=function(mouseEvent){var sc=mouseEvent.sourceCapabilities;if(sc&&!sc.firesTouchEvents){return;}
-mouseEvent[HANDLED_OBJ]={skip:true};if(mouseEvent.type==='click'){var path=Polymer.dom(mouseEvent).path;for(var i=0;i<path.length;i++){if(path[i]===POINTERSTATE.mouse.target){return;}}
+mouseEvent[HANDLED_OBJ]={skip:true};if(mouseEvent.type==='click'){var path=Polymer.dom(mouseEvent).path;if(path){for(var i=0;i<path.length;i++){if(path[i]===POINTERSTATE.mouse.target){return;}}}
mouseEvent.preventDefault();mouseEvent.stopPropagation();}};function setupTeardownMouseCanceller(setup){var events=IS_TOUCH_ONLY?['click']:MOUSE_EVENTS;for(var i=0,en;i<events.length;i++){en=events[i];if(setup){document.addEventListener(en,mouseCanceller,true);}else{document.removeEventListener(en,mouseCanceller,true);}}}
function ignoreMouse(ev){if(!POINTERSTATE.mouse.mouseIgnoreJob){setupTeardownMouseCanceller(true);}
var unset=function(){setupTeardownMouseCanceller();POINTERSTATE.mouse.target=null;POINTERSTATE.mouse.mouseIgnoreJob=null;};POINTERSTATE.mouse.target=Polymer.dom(ev).rootTarget;POINTERSTATE.mouse.mouseIgnoreJob=Polymer.Debounce(POINTERSTATE.mouse.mouseIgnoreJob,unset,MOUSE_TIMEOUT);}
@@ -3823,9 +3945,9 @@ POINTERSTATE.touch.scrollDecided=true;var ta=firstTouchAction(ev);var prevent=fa
if(prevent){ev.preventDefault();}else{Gestures.prevent('track');}}},add:function(node,evType,handler){node=wrap(node);var recognizer=this.gestures[evType];var deps=recognizer.deps;var name=recognizer.name;var gobj=node[GESTURE_KEY];if(!gobj){node[GESTURE_KEY]=gobj={};}
for(var i=0,dep,gd;i<deps.length;i++){dep=deps[i];if(IS_TOUCH_ONLY&&isMouseEvent(dep)&&dep!=='click'){continue;}
gd=gobj[dep];if(!gd){gobj[dep]=gd={_count:0};}
-if(gd._count===0){var options=!isMouseEvent(dep)&&PASSIVE_TOUCH();node.addEventListener(dep,this.handleNative,options);}
+if(gd._count===0){node.addEventListener(dep,this.handleNative,PASSIVE_TOUCH(dep));}
gd[name]=(gd[name]||0)+1;gd._count=(gd._count||0)+1;}
-node.addEventListener(evType,handler);if(recognizer.touchAction){this.setTouchAction(node,recognizer.touchAction);}},remove:function(node,evType,handler){node=wrap(node);var recognizer=this.gestures[evType];var deps=recognizer.deps;var name=recognizer.name;var gobj=node[GESTURE_KEY];if(gobj){for(var i=0,dep,gd;i<deps.length;i++){dep=deps[i];gd=gobj[dep];if(gd&&gd[name]){gd[name]=(gd[name]||1)-1;gd._count=(gd._count||1)-1;if(gd._count===0){var options=!isMouseEvent(dep)&&PASSIVE_TOUCH();node.removeEventListener(dep,this.handleNative,options);}}}}
+node.addEventListener(evType,handler);if(recognizer.touchAction){this.setTouchAction(node,recognizer.touchAction);}},remove:function(node,evType,handler){node=wrap(node);var recognizer=this.gestures[evType];var deps=recognizer.deps;var name=recognizer.name;var gobj=node[GESTURE_KEY];if(gobj){for(var i=0,dep,gd;i<deps.length;i++){dep=deps[i];gd=gobj[dep];if(gd&&gd[name]){gd[name]=(gd[name]||1)-1;gd._count=(gd._count||1)-1;if(gd._count===0){node.removeEventListener(dep,this.handleNative,PASSIVE_TOUCH(dep));}}}}
node.removeEventListener(evType,handler);},register:function(recog){this.recognizers.push(recog);for(var i=0;i<recog.emits.length;i++){this.gestures[recog.emits[i]]=recog;}},findRecognizerByEvent:function(evName){for(var i=0,r;i<this.recognizers.length;i++){r=this.recognizers[i];for(var j=0,n;j<r.emits.length;j++){n=r.emits[j];if(n===evName){return r;}}}
return null;},setTouchAction:function(node,value){if(HAS_NATIVE_TA){node.style.touchAction=value;}
node[TOUCH_ACTION]=value;},fire:function(target,type,detail){var ev=Polymer.Base.fire(type,detail,{node:target,bubbles:true,cancelable:true});if(ev.defaultPrevented){var preventer=detail.preventer||detail.sourceEvent;if(preventer&&preventer.preventDefault){preventer.preventDefault();}}},prevent:function(evName){var recognizer=this.findRecognizerByEvent(evName);if(recognizer.info){recognizer.info.prevent=true;}},resetMouseCanceller:function(){if(POINTERSTATE.mouse.mouseIgnoreJob){POINTERSTATE.mouse.mouseIgnoreJob.complete();}}};Gestures.register({name:'downup',deps:['mousedown','touchstart','touchend'],flow:{start:['mousedown','touchstart'],end:['mouseup','touchend']},emits:['down','up'],info:{movefn:null,upfn:null},reset:function(){untrackDocument(this.info);},mousedown:function(e){if(!hasLeftMouseButton(e)){return;}
@@ -3917,7 +4039,7 @@ return node;},_expandUnicodeEscapes:function(s){return s.replace(/\\([0-9a-f]{1,
return'\\'+code;});},stringify:function(node,preserveProperties,text){text=text||'';var cssText='';if(node.cssText||node.rules){var r$=node.rules;if(r$&&!this._hasMixinRules(r$)){for(var i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){cssText=this.stringify(r,preserveProperties,cssText);}}else{cssText=preserveProperties?node.cssText:this.removeCustomProps(node.cssText);cssText=cssText.trim();if(cssText){cssText=' '+cssText+'\n';}}}
if(cssText){if(node.selector){text+=node.selector+' '+this.OPEN_BRACE+'\n';}
text+=cssText;if(node.selector){text+=this.CLOSE_BRACE+'\n\n';}}
-return text;},_hasMixinRules:function(rules){return rules[0].selector.indexOf(this.VAR_START)===0;},removeCustomProps:function(cssText){cssText=this.removeCustomPropAssignment(cssText);return this.removeCustomPropApply(cssText);},removeCustomPropAssignment:function(cssText){return cssText.replace(this._rx.customProp,'').replace(this._rx.mixinProp,'');},removeCustomPropApply:function(cssText){return cssText.replace(this._rx.mixinApply,'').replace(this._rx.varApply,'');},types:{STYLE_RULE:1,KEYFRAMES_RULE:7,MEDIA_RULE:4,MIXIN_RULE:1000},OPEN_BRACE:'{',CLOSE_BRACE:'}',_rx:{comments:/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,port:/@import[^;]*;/gim,customProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,mixinProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,mixinApply:/@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,varApply:/[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,keyframesRule:/^@[^\s]*keyframes/,multipleSpaces:/\s+/g},VAR_START:'--',MEDIA_START:'@media',AT_START:'@'};}();Polymer.StyleUtil=function(){var settings=Polymer.Settings;return{NATIVE_VARIABLES:Polymer.Settings.useNativeCSSProperties,MODULE_STYLES_SELECTOR:'style, link[rel=import][type~=css], template',INCLUDE_ATTR:'include',toCssText:function(rules,callback){if(typeof rules==='string'){rules=this.parser.parse(rules);}
+return text;},_hasMixinRules:function(rules){return rules[0].selector.indexOf(this.VAR_START)===0;},removeCustomProps:function(cssText){cssText=this.removeCustomPropAssignment(cssText);return this.removeCustomPropApply(cssText);},removeCustomPropAssignment:function(cssText){return cssText.replace(this._rx.customProp,'').replace(this._rx.mixinProp,'');},removeCustomPropApply:function(cssText){return cssText.replace(this._rx.mixinApply,'').replace(this._rx.varApply,'');},types:{STYLE_RULE:1,KEYFRAMES_RULE:7,MEDIA_RULE:4,MIXIN_RULE:1000},OPEN_BRACE:'{',CLOSE_BRACE:'}',_rx:{comments:/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,port:/@import[^;]*;/gim,customProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,mixinProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,mixinApply:/@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,varApply:/[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,keyframesRule:/^@[^\s]*keyframes/,multipleSpaces:/\s+/g},VAR_START:'--',MEDIA_START:'@media',AT_START:'@'};}();Polymer.StyleUtil=function(){var settings=Polymer.Settings;return{unscopedStyleImports:new WeakMap(),SHADY_UNSCOPED_ATTR:'shady-unscoped',NATIVE_VARIABLES:Polymer.Settings.useNativeCSSProperties,MODULE_STYLES_SELECTOR:'style, link[rel=import][type~=css], template',INCLUDE_ATTR:'include',toCssText:function(rules,callback){if(typeof rules==='string'){rules=this.parser.parse(rules);}
if(callback){this.forEachRule(rules,callback);}
return this.parser.stringify(rules,this.NATIVE_VARIABLES);},forRulesInStyles:function(styles,styleRuleCallback,keyframesRuleCallback){if(styles){for(var i=0,l=styles.length,s;i<l&&(s=styles[i]);i++){this.forEachRuleInStyle(s,styleRuleCallback,keyframesRuleCallback);}}},forActiveRulesInStyles:function(styles,styleRuleCallback,keyframesRuleCallback){if(styles){for(var i=0,l=styles.length,s;i<l&&(s=styles[i]);i++){this.forEachRuleInStyle(s,styleRuleCallback,keyframesRuleCallback,true);}}},rulesForStyle:function(style){if(!style.__cssRules&&style.textContent){style.__cssRules=this.parser.parse(style.textContent);}
return style.__cssRules;},isKeyframesSelector:function(rule){return rule.parent&&rule.parent.type===this.ruleTypes.KEYFRAMES_RULE;},forEachRuleInStyle:function(style,styleRuleCallback,keyframesRuleCallback,onlyActiveRules){var rules=this.rulesForStyle(style);var styleCallback,keyframeCallback;if(styleRuleCallback){styleCallback=function(rule){styleRuleCallback(rule,style);};}
@@ -3926,11 +4048,11 @@ this.forEachRule(rules,styleCallback,keyframeCallback,onlyActiveRules);},forEach
var skipRules=false;if(onlyActiveRules){if(node.type===this.ruleTypes.MEDIA_RULE){var matchMedia=node.selector.match(this.rx.MEDIA_MATCH);if(matchMedia){if(!window.matchMedia(matchMedia[1]).matches){skipRules=true;}}}}
if(node.type===this.ruleTypes.STYLE_RULE){styleRuleCallback(node);}else if(keyframesRuleCallback&&node.type===this.ruleTypes.KEYFRAMES_RULE){keyframesRuleCallback(node);}else if(node.type===this.ruleTypes.MIXIN_RULE){skipRules=true;}
var r$=node.rules;if(r$&&!skipRules){for(var i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){this.forEachRule(r,styleRuleCallback,keyframesRuleCallback,onlyActiveRules);}}},applyCss:function(cssText,moniker,target,contextNode){var style=this.createScopeStyle(cssText,moniker);return this.applyStyle(style,target,contextNode);},applyStyle:function(style,target,contextNode){target=target||document.head;var after=contextNode&&contextNode.nextSibling||target.firstChild;this.__lastHeadApplyNode=style;return target.insertBefore(style,after);},createScopeStyle:function(cssText,moniker){var style=document.createElement('style');if(moniker){style.setAttribute('scope',moniker);}
-style.textContent=cssText;return style;},__lastHeadApplyNode:null,applyStylePlaceHolder:function(moniker){var placeHolder=document.createComment(' Shady DOM styles for '+moniker+' ');var after=this.__lastHeadApplyNode?this.__lastHeadApplyNode.nextSibling:null;var scope=document.head;scope.insertBefore(placeHolder,after||scope.firstChild);this.__lastHeadApplyNode=placeHolder;return placeHolder;},cssFromModules:function(moduleIds,warnIfNotFound){var modules=moduleIds.trim().split(' ');var cssText='';for(var i=0;i<modules.length;i++){cssText+=this.cssFromModule(modules[i],warnIfNotFound);}
+style.textContent=cssText;return style;},__lastHeadApplyNode:null,applyStylePlaceHolder:function(moniker){var placeHolder=document.createComment(' Shady DOM styles for '+moniker+' ');var after=this.__lastHeadApplyNode?this.__lastHeadApplyNode.nextSibling:null;var scope=document.head;scope.insertBefore(placeHolder,after||scope.firstChild);this.__lastHeadApplyNode=placeHolder;return placeHolder;},cssFromModules:function(moduleIds,warnIfNotFound){var modules=moduleIds.trim().split(/\s+/);var cssText='';for(var i=0;i<modules.length;i++){cssText+=this.cssFromModule(modules[i],warnIfNotFound);}
return cssText;},cssFromModule:function(moduleId,warnIfNotFound){var m=Polymer.DomModule.import(moduleId);if(m&&!m._cssText){m._cssText=this.cssFromElement(m);}
if(!m&&warnIfNotFound){console.warn('Could not find style data in module named',moduleId);}
return m&&m._cssText||'';},cssFromElement:function(element){var cssText='';var content=element.content||element;var e$=Polymer.TreeApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_SELECTOR));for(var i=0,e;i<e$.length;i++){e=e$[i];if(e.localName==='template'){if(!e.hasAttribute('preserve-content')){cssText+=this.cssFromElement(e);}}else{if(e.localName==='style'){var include=e.getAttribute(this.INCLUDE_ATTR);if(include){cssText+=this.cssFromModules(include,true);}
-e=e.__appliedElement||e;e.parentNode.removeChild(e);cssText+=this.resolveCss(e.textContent,element.ownerDocument);}else if(e.import&&e.import.body){cssText+=this.resolveCss(e.import.body.textContent,e.import);}}}
+e=e.__appliedElement||e;e.parentNode.removeChild(e);var css=this.resolveCss(e.textContent,element.ownerDocument);if(!settings.useNativeShadow&&e.hasAttribute(this.SHADY_UNSCOPED_ATTR)){e.textContent=css;document.head.insertBefore(e,document.head.firstChild);}else{cssText+=css;}}else if(e.import&&e.import.body){var importCss=this.resolveCss(e.import.body.textContent,e.import);if(!settings.useNativeShadow&&e.hasAttribute(this.SHADY_UNSCOPED_ATTR)){if(!this.unscopedStyleImports.has(e.import)){this.unscopedStyleImports.set(e.import,true);var importStyle=document.createElement('style');importStyle.setAttribute(this.SHADY_UNSCOPED_ATTR,'');importStyle.textContent=importCss;document.head.insertBefore(importStyle,document.head.firstChild);}}else{cssText+=importCss;}}}}
return cssText;},styleIncludesToTemplate:function(targetTemplate){var styles=targetTemplate.content.querySelectorAll('style[include]');for(var i=0,s;i<styles.length;i++){s=styles[i];s.parentNode.insertBefore(this._includesToFragment(s.getAttribute('include')),s);}},_includesToFragment:function(styleIncludes){var includeArray=styleIncludes.trim().split(' ');var frag=document.createDocumentFragment();for(var i=0;i<includeArray.length;i++){var t=Polymer.DomModule.import(includeArray[i],'template');if(t){this._addStylesToFragment(frag,t.content);}}
return frag;},_addStylesToFragment:function(frag,source){var s$=source.querySelectorAll('style');for(var i=0,s;i<s$.length;i++){s=s$[i];var include=s.getAttribute('include');if(include){frag.appendChild(this._includesToFragment(include));}
if(s.textContent){frag.appendChild(s.cloneNode(true));}}},isTargetedBuild:function(buildType){return settings.useNativeShadow?buildType==='shadow':buildType==='shady';},cssBuildTypeForModule:function(module){var dm=Polymer.DomModule.import(module);if(dm){return this.getCssBuildType(dm);}},getCssBuildType:function(element){return element.getAttribute('css-build');},_findMatchingParen:function(text,start){var level=0;for(var i=start,l=text.length;i<l;i++){switch(text[i]){case'(':level++;break;case')':if(--level===0){return i;}
@@ -3938,16 +4060,25 @@ break;}}
return-1;},processVariableAndFallback:function(str,callback){var start=str.indexOf('var(');if(start===-1){return callback(str,'','','');}
var end=this._findMatchingParen(str,start+3);var inner=str.substring(start+4,end);var prefix=str.substring(0,start);var suffix=this.processVariableAndFallback(str.substring(end+1),callback);var comma=inner.indexOf(',');if(comma===-1){return callback(prefix,inner.trim(),'',suffix);}
var value=inner.substring(0,comma).trim();var fallback=inner.substring(comma+1).trim();return callback(prefix,value,fallback,suffix);},rx:{VAR_ASSIGN:/(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi,MIXIN_MATCH:/(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi,VAR_CONSUMED:/(--[\w-]+)\s*([:,;)]|$)/gi,ANIMATION_MATCH:/(animation\s*:)|(animation-name\s*:)/,MEDIA_MATCH:/@media[^(]*(\([^)]*\))/,IS_VAR:/^--/,BRACKETED:/\{[^}]*\}/g,HOST_PREFIX:'(?:^|[^.#[:])',HOST_SUFFIX:'($|[.:[\\s>+~])'},resolveCss:Polymer.ResolveUrl.resolveCss,parser:Polymer.CssParse,ruleTypes:Polymer.CssParse.types};}();Polymer.StyleTransformer=function(){var styleUtil=Polymer.StyleUtil;var settings=Polymer.Settings;var api={dom:function(node,scope,useAttr,shouldRemoveScope){this._transformDom(node,scope||'',useAttr,shouldRemoveScope);},_transformDom:function(node,selector,useAttr,shouldRemoveScope){if(node.setAttribute){this.element(node,selector,useAttr,shouldRemoveScope);}
-var c$=Polymer.dom(node).childNodes;for(var i=0;i<c$.length;i++){this._transformDom(c$[i],selector,useAttr,shouldRemoveScope);}},element:function(element,scope,useAttr,shouldRemoveScope){if(useAttr){if(shouldRemoveScope){element.removeAttribute(SCOPE_NAME);}else{element.setAttribute(SCOPE_NAME,scope);}}else{if(scope){if(element.classList){if(shouldRemoveScope){element.classList.remove(SCOPE_NAME);element.classList.remove(scope);}else{element.classList.add(SCOPE_NAME);element.classList.add(scope);}}else if(element.getAttribute){var c=element.getAttribute(CLASS);if(shouldRemoveScope){if(c){element.setAttribute(CLASS,c.replace(SCOPE_NAME,'').replace(scope,''));}}else{element.setAttribute(CLASS,(c?c+' ':'')+SCOPE_NAME+' '+scope);}}}}},elementStyles:function(element,callback){var styles=element._styles;var cssText='';var cssBuildType=element.__cssBuild;var passthrough=settings.useNativeShadow||cssBuildType==='shady';var cb;if(passthrough){var self=this;cb=function(rule){rule.selector=self._slottedToContent(rule.selector);rule.selector=rule.selector.replace(ROOT,':host > *');if(callback){callback(rule);}};}
+var c$=Polymer.dom(node).childNodes;for(var i=0;i<c$.length;i++){this._transformDom(c$[i],selector,useAttr,shouldRemoveScope);}},element:function(element,scope,useAttr,shouldRemoveScope){if(useAttr){if(shouldRemoveScope){element.removeAttribute(SCOPE_NAME);}else{element.setAttribute(SCOPE_NAME,scope);}}else{if(scope){if(element.classList){if(shouldRemoveScope){element.classList.remove(SCOPE_NAME);element.classList.remove(scope);}else{element.classList.add(SCOPE_NAME);element.classList.add(scope);}}else if(element.getAttribute){var c=element.getAttribute(CLASS);if(shouldRemoveScope){if(c){element.setAttribute(CLASS,c.replace(SCOPE_NAME,'').replace(scope,''));}}else{element.setAttribute(CLASS,(c?c+' ':'')+SCOPE_NAME+' '+scope);}}}}},elementStyles:function(element,callback){var styles=element._styles;var cssText='';var cssBuildType=element.__cssBuild;var passthrough=settings.useNativeShadow||cssBuildType==='shady';var cb;if(passthrough){var self=this;cb=function(rule){rule.selector=self._slottedToContent(rule.selector);rule.selector=rule.selector.replace(ROOT,':host > *');rule.selector=self._dirShadowTransform(rule.selector);if(callback){callback(rule);}};}
for(var i=0,l=styles.length,s;i<l&&(s=styles[i]);i++){var rules=styleUtil.rulesForStyle(s);cssText+=passthrough?styleUtil.toCssText(rules,cb):this.css(rules,element.is,element.extends,callback,element._scopeCssViaAttr)+'\n\n';}
return cssText.trim();},css:function(rules,scope,ext,callback,useAttr){var hostScope=this._calcHostScope(scope,ext);scope=this._calcElementScope(scope,useAttr);var self=this;return styleUtil.toCssText(rules,function(rule){if(!rule.isScoped){self.rule(rule,scope,hostScope);rule.isScoped=true;}
-if(callback){callback(rule,scope,hostScope);}});},_calcElementScope:function(scope,useAttr){if(scope){return useAttr?CSS_ATTR_PREFIX+scope+CSS_ATTR_SUFFIX:CSS_CLASS_PREFIX+scope;}else{return'';}},_calcHostScope:function(scope,ext){return ext?'[is='+scope+']':scope;},rule:function(rule,scope,hostScope){this._transformRule(rule,this._transformComplexSelector,scope,hostScope);},_transformRule:function(rule,transformer,scope,hostScope){rule.selector=rule.transformedSelector=this._transformRuleCss(rule,transformer,scope,hostScope);},_transformRuleCss:function(rule,transformer,scope,hostScope){var p$=rule.selector.split(COMPLEX_SELECTOR_SEP);if(!styleUtil.isKeyframesSelector(rule)){for(var i=0,l=p$.length,p;i<l&&(p=p$[i]);i++){p$[i]=transformer.call(this,p,scope,hostScope);}}
-return p$.join(COMPLEX_SELECTOR_SEP);},_transformComplexSelector:function(selector,scope,hostScope){var stop=false;var hostContext=false;var self=this;selector=selector.trim();selector=this._slottedToContent(selector);selector=selector.replace(ROOT,':host > *');selector=selector.replace(CONTENT_START,HOST+' $1');selector=selector.replace(SIMPLE_SELECTOR_SEP,function(m,c,s){if(!stop){var info=self._transformCompoundSelector(s,c,scope,hostScope);stop=stop||info.stop;hostContext=hostContext||info.hostContext;c=info.combinator;s=info.value;}else{s=s.replace(SCOPE_JUMP,' ');}
-return c+s;});if(hostContext){selector=selector.replace(HOST_CONTEXT_PAREN,function(m,pre,paren,post){return pre+paren+' '+hostScope+post+COMPLEX_SELECTOR_SEP+' '+pre+hostScope+paren+post;});}
-return selector;},_transformCompoundSelector:function(selector,combinator,scope,hostScope){var jumpIndex=selector.search(SCOPE_JUMP);var hostContext=false;if(selector.indexOf(HOST_CONTEXT)>=0){hostContext=true;}else if(selector.indexOf(HOST)>=0){selector=this._transformHostSelector(selector,hostScope);}else if(jumpIndex!==0){selector=scope?this._transformSimpleSelector(selector,scope):selector;}
+if(callback){callback(rule,scope,hostScope);}});},_calcElementScope:function(scope,useAttr){if(scope){return useAttr?CSS_ATTR_PREFIX+scope+CSS_ATTR_SUFFIX:CSS_CLASS_PREFIX+scope;}else{return'';}},_calcHostScope:function(scope,ext){return ext?'[is='+scope+']':scope;},rule:function(rule,scope,hostScope){this._transformRule(rule,this._transformComplexSelector,scope,hostScope);},_transformRule:function(rule,transformer,scope,hostScope){rule.selector=rule.transformedSelector=this._transformRuleCss(rule,transformer,scope,hostScope);},_splitSelectorList:function(selector){var parts=[];var part='';for(var i=0;i>=0&&i<selector.length;i++){if(selector[i]==='('){var end=styleUtil._findMatchingParen(selector,i);part+=selector.slice(i,end+1);i=end;}else if(selector[i]===COMPLEX_SELECTOR_SEP){parts.push(part);part='';}else{part+=selector[i];}}
+if(part){parts.push(part);}
+if(parts.length===0){parts.push(selector);}
+return parts;},_transformRuleCss:function(rule,transformer,scope,hostScope){var p$=this._splitSelectorList(rule.selector);if(!styleUtil.isKeyframesSelector(rule)){for(var i=0,l=p$.length,p;i<l&&(p=p$[i]);i++){p$[i]=transformer.call(this,p,scope,hostScope);}}
+return p$.join(COMPLEX_SELECTOR_SEP);},_ensureScopedDir:function(s){var m=s.match(DIR_PAREN);if(m&&m[1]===''&&m[0].length===s.length){s='*'+s;}
+return s;},_additionalDirSelectors:function(dir,after,prefix){if(!dir||!after){return'';}
+prefix=prefix||'';return COMPLEX_SELECTOR_SEP+prefix+' '+dir+' '+after;},_transformComplexSelector:function(selector,scope,hostScope){var stop=false;var hostContext=false;var dir=false;var self=this;selector=selector.trim();selector=this._slottedToContent(selector);selector=selector.replace(ROOT,':host > *');selector=selector.replace(CONTENT_START,HOST+' $1');selector=this._ensureScopedDir(selector);selector=selector.replace(SIMPLE_SELECTOR_SEP,function(m,c,s){if(!stop){var info=self._transformCompoundSelector(s,c,scope,hostScope);stop=stop||info.stop;hostContext=hostContext||info.hostContext;dir=dir||info.dir;c=info.combinator;s=info.value;}else{s=s.replace(SCOPE_JUMP,' ');}
+return c+s;});if(hostContext){selector=selector.replace(HOST_CONTEXT_PAREN,function(m,pre,paren,post){var replacement=pre+paren+' '+hostScope+post+COMPLEX_SELECTOR_SEP+' '+pre+hostScope+paren+post;if(dir){replacement+=self._additionalDirSelectors(paren,post,hostScope);}
+return replacement;});}
+return selector;},_transformDir:function(s){s=s.replace(HOST_DIR,HOST_DIR_REPLACE);s=s.replace(DIR_PAREN,DIR_REPLACE);return s;},_transformCompoundSelector:function(selector,combinator,scope,hostScope){var jumpIndex=selector.search(SCOPE_JUMP);var hostContext=false;var dir=false;if(selector.match(DIR_PAREN)){selector=this._transformDir(selector);dir=true;}
+if(selector.indexOf(HOST_CONTEXT)>=0){hostContext=true;}else if(selector.indexOf(HOST)>=0){selector=this._transformHostSelector(selector,hostScope);}else if(jumpIndex!==0){selector=scope?this._transformSimpleSelector(selector,scope):selector;}
if(selector.indexOf(CONTENT)>=0){combinator='';}
var stop;if(jumpIndex>=0){selector=selector.replace(SCOPE_JUMP,' ');stop=true;}
-return{value:selector,combinator:combinator,stop:stop,hostContext:hostContext};},_transformSimpleSelector:function(selector,scope){var p$=selector.split(PSEUDO_PREFIX);p$[0]+=scope;return p$.join(PSEUDO_PREFIX);},_transformHostSelector:function(selector,hostScope){var m=selector.match(HOST_PAREN);var paren=m&&m[2].trim()||'';if(paren){if(!paren[0].match(SIMPLE_SELECTOR_PREFIX)){var typeSelector=paren.split(SIMPLE_SELECTOR_PREFIX)[0];if(typeSelector===hostScope){return paren;}else{return SELECTOR_NO_MATCH;}}else{return selector.replace(HOST_PAREN,function(m,host,paren){return hostScope+paren;});}}else{return selector.replace(HOST,hostScope);}},documentRule:function(rule){rule.selector=rule.parsedSelector;this.normalizeRootSelector(rule);if(!settings.useNativeShadow){this._transformRule(rule,this._transformDocumentSelector);}},normalizeRootSelector:function(rule){rule.selector=rule.selector.replace(ROOT,'html');var parts=rule.selector.split(COMPLEX_SELECTOR_SEP);parts=parts.filter(function(part){return!part.match(HOST_OR_HOST_GT_STAR);});rule.selector=parts.join(COMPLEX_SELECTOR_SEP);},_transformDocumentSelector:function(selector){return selector.match(SCOPE_JUMP)?this._transformComplexSelector(selector,SCOPE_DOC_SELECTOR):this._transformSimpleSelector(selector.trim(),SCOPE_DOC_SELECTOR);},_slottedToContent:function(cssText){return cssText.replace(SLOTTED_PAREN,CONTENT+'> $1');},SCOPE_NAME:'style-scope'};var SCOPE_NAME=api.SCOPE_NAME;var SCOPE_DOC_SELECTOR=':not(['+SCOPE_NAME+'])'+':not(.'+SCOPE_NAME+')';var COMPLEX_SELECTOR_SEP=',';var SIMPLE_SELECTOR_SEP=/(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g;var SIMPLE_SELECTOR_PREFIX=/[[.:#*]/;var HOST=':host';var ROOT=':root';var HOST_PAREN=/(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/;var HOST_CONTEXT=':host-context';var HOST_CONTEXT_PAREN=/(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;var CONTENT='::content';var SCOPE_JUMP=/::content|::shadow|\/deep\//;var CSS_CLASS_PREFIX='.';var CSS_ATTR_PREFIX='['+SCOPE_NAME+'~=';var CSS_ATTR_SUFFIX=']';var PSEUDO_PREFIX=':';var CLASS='class';var CONTENT_START=new RegExp('^('+CONTENT+')');var SELECTOR_NO_MATCH='should_not_match';var SLOTTED_PAREN=/(?:::slotted)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;var HOST_OR_HOST_GT_STAR=/:host(?:\s*>\s*\*)?/;return api;}();Polymer.StyleExtends=function(){var styleUtil=Polymer.StyleUtil;return{hasExtends:function(cssText){return Boolean(cssText.match(this.rx.EXTEND));},transform:function(style){var rules=styleUtil.rulesForStyle(style);var self=this;styleUtil.forEachRule(rules,function(rule){self._mapRuleOntoParent(rule);if(rule.parent){var m;while(m=self.rx.EXTEND.exec(rule.cssText)){var extend=m[1];var extendor=self._findExtendor(extend,rule);if(extendor){self._extendRule(rule,extendor);}}}
+return{value:selector,combinator:combinator,stop:stop,hostContext:hostContext,dir:dir};},_transformSimpleSelector:function(selector,scope){var p$=selector.split(PSEUDO_PREFIX);p$[0]+=scope;return p$.join(PSEUDO_PREFIX);},_transformHostSelector:function(selector,hostScope){var m=selector.match(HOST_PAREN);var paren=m&&m[2].trim()||'';if(paren){if(!paren[0].match(SIMPLE_SELECTOR_PREFIX)){var typeSelector=paren.split(SIMPLE_SELECTOR_PREFIX)[0];if(typeSelector===hostScope){return paren;}else{return SELECTOR_NO_MATCH;}}else{return selector.replace(HOST_PAREN,function(m,host,paren){return hostScope+paren;});}}else{return selector.replace(HOST,hostScope);}},documentRule:function(rule){rule.selector=rule.parsedSelector;this.normalizeRootSelector(rule);if(!settings.useNativeShadow){this._transformRule(rule,this._transformDocumentSelector);}},normalizeRootSelector:function(rule){rule.selector=rule.selector.replace(ROOT,'html');var parts=this._splitSelectorList(rule.selector);parts=parts.filter(function(part){return!part.match(HOST_OR_HOST_GT_STAR);});rule.selector=parts.join(COMPLEX_SELECTOR_SEP);},_transformDocumentSelector:function(selector){return this._transformComplexSelector(selector,SCOPE_DOC_SELECTOR);},_slottedToContent:function(cssText){return cssText.replace(SLOTTED_PAREN,CONTENT+'> $1');},_dirShadowTransform:function(selector){if(!selector.match(/:dir\(/)){return selector;}
+return this._splitSelectorList(selector).map(function(s){s=this._ensureScopedDir(s);s=this._transformDir(s);var m=HOST_CONTEXT_PAREN.exec(s);if(m){s+=this._additionalDirSelectors(m[2],m[3],'');}
+return s;},this).join(COMPLEX_SELECTOR_SEP);},SCOPE_NAME:'style-scope'};var SCOPE_NAME=api.SCOPE_NAME;var SCOPE_DOC_SELECTOR=':not(['+SCOPE_NAME+'])'+':not(.'+SCOPE_NAME+')';var COMPLEX_SELECTOR_SEP=',';var SIMPLE_SELECTOR_SEP=/(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g;var SIMPLE_SELECTOR_PREFIX=/[[.:#*]/;var HOST=':host';var ROOT=':root';var HOST_PAREN=/(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/;var HOST_CONTEXT=':host-context';var HOST_CONTEXT_PAREN=/(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;var CONTENT='::content';var SCOPE_JUMP=/::content|::shadow|\/deep\//;var CSS_CLASS_PREFIX='.';var CSS_ATTR_PREFIX='['+SCOPE_NAME+'~=';var CSS_ATTR_SUFFIX=']';var PSEUDO_PREFIX=':';var CLASS='class';var CONTENT_START=new RegExp('^('+CONTENT+')');var SELECTOR_NO_MATCH='should_not_match';var SLOTTED_PAREN=/(?:::slotted)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;var HOST_OR_HOST_GT_STAR=/:host(?:\s*>\s*\*)?/;var DIR_PAREN=/(.*):dir\((ltr|rtl)\)/;var DIR_REPLACE=':host-context([dir="$2"]) $1';var HOST_DIR=/:host\(:dir\((rtl|ltr)\)\)/g;var HOST_DIR_REPLACE=':host-context([dir="$1"])';return api;}();Polymer.StyleExtends=function(){var styleUtil=Polymer.StyleUtil;return{hasExtends:function(cssText){return Boolean(cssText.match(this.rx.EXTEND));},transform:function(style){var rules=styleUtil.rulesForStyle(style);var self=this;styleUtil.forEachRule(rules,function(rule){self._mapRuleOntoParent(rule);if(rule.parent){var m;while(m=self.rx.EXTEND.exec(rule.cssText)){var extend=m[1];var extendor=self._findExtendor(extend,rule);if(extendor){self._extendRule(rule,extendor);}}}
rule.cssText=rule.cssText.replace(self.rx.EXTEND,'');});return styleUtil.toCssText(rules,function(rule){if(rule.selector.match(self.rx.STRIP)){rule.cssText='';}},true);},_mapRuleOntoParent:function(rule){if(rule.parent){var map=rule.parent.map||(rule.parent.map={});var parts=rule.selector.split(',');for(var i=0,p;i<parts.length;i++){p=parts[i];map[p.trim()]=rule;}
return map;}},_findExtendor:function(extend,rule){return rule.parent&&rule.parent.map&&rule.parent.map[extend]||this._findExtendor(extend,rule.parent);},_extendRule:function(target,source){if(target.parent!==source.parent){this._cloneAndAddRuleToParent(source,target.parent);}
target.extends=target.extends||[];target.extends.push(source);source.selector=source.selector.replace(this.rx.STRIP,'');source.selector=(source.selector&&source.selector+',\n')+target.selector;if(source.extends){source.extends.forEach(function(e){this._extendRule(target,e);},this);}},_cloneAndAddRuleToParent:function(rule,parent){rule=Object.create(rule);rule.parent=parent;if(rule.extends){rule.extends=rule.extends.slice();}
@@ -4013,7 +4144,7 @@ var selectorToMatch=hostScope;if(isHost){if(settings.useNativeShadow&&!rule.tran
selectorToMatch=rule.transformedSelector||rule.parsedSelector;}
if(isRoot&&hostScope==='html'){selectorToMatch=rule.transformedSelector||rule.parsedSelector;}
callback({selector:selectorToMatch,isHost:isHost,isRoot:isRoot});},hostAndRootPropertiesForScope:function(scope){var hostProps={},rootProps={},self=this;styleUtil.forActiveRulesInStyles(scope._styles,function(rule,style){self.whenHostOrRootRule(scope,rule,style,function(info){var element=scope._element||scope;if(matchesSelector.call(element,info.selector)){if(info.isHost){self.collectProperties(rule,hostProps);}else{self.collectProperties(rule,rootProps);}}});});return{rootProps:rootProps,hostProps:hostProps};},transformStyles:function(element,properties,scopeSelector){var self=this;var hostSelector=styleTransformer._calcHostScope(element.is,element.extends);var rxHostSelector=element.extends?'\\'+hostSelector.slice(0,-1)+'\\]':hostSelector;var hostRx=new RegExp(this.rx.HOST_PREFIX+rxHostSelector+this.rx.HOST_SUFFIX);var keyframeTransforms=this._elementKeyframeTransforms(element,scopeSelector);return styleTransformer.elementStyles(element,function(rule){self.applyProperties(rule,properties);if(!settings.useNativeShadow&&!Polymer.StyleUtil.isKeyframesSelector(rule)&&rule.cssText){self.applyKeyframeTransforms(rule,keyframeTransforms);self._scopeSelector(rule,hostRx,hostSelector,element._scopeCssViaAttr,scopeSelector);}});},_elementKeyframeTransforms:function(element,scopeSelector){var keyframesRules=element._styles._keyframes;var keyframeTransforms={};if(!settings.useNativeShadow&&keyframesRules){for(var i=0,keyframesRule=keyframesRules[i];i<keyframesRules.length;keyframesRule=keyframesRules[++i]){this._scopeKeyframes(keyframesRule,scopeSelector);keyframeTransforms[keyframesRule.keyframesName]=this._keyframesRuleTransformer(keyframesRule);}}
-return keyframeTransforms;},_keyframesRuleTransformer:function(keyframesRule){return function(cssText){return cssText.replace(keyframesRule.keyframesNameRx,keyframesRule.transformedKeyframesName);};},_scopeKeyframes:function(rule,scopeId){rule.keyframesNameRx=new RegExp(rule.keyframesName,'g');rule.transformedKeyframesName=rule.keyframesName+'-'+scopeId;rule.transformedSelector=rule.transformedSelector||rule.selector;rule.selector=rule.transformedSelector.replace(rule.keyframesName,rule.transformedKeyframesName);},_scopeSelector:function(rule,hostRx,hostSelector,viaAttr,scopeId){rule.transformedSelector=rule.transformedSelector||rule.selector;var selector=rule.transformedSelector;var scope=viaAttr?'['+styleTransformer.SCOPE_NAME+'~='+scopeId+']':'.'+scopeId;var parts=selector.split(',');for(var i=0,l=parts.length,p;i<l&&(p=parts[i]);i++){parts[i]=p.match(hostRx)?p.replace(hostSelector,scope):scope+' '+p;}
+return keyframeTransforms;},_keyframesRuleTransformer:function(keyframesRule){return function(cssText){return cssText.replace(keyframesRule.keyframesNameRx,keyframesRule.transformedKeyframesName);};},_scopeKeyframes:function(rule,scopeId){rule.keyframesNameRx=new RegExp('\\b'+rule.keyframesName+'(?!\\B|-)','g');rule.transformedKeyframesName=rule.keyframesName+'-'+scopeId;rule.transformedSelector=rule.transformedSelector||rule.selector;rule.selector=rule.transformedSelector.replace(rule.keyframesName,rule.transformedKeyframesName);},_hasDirOrHostContext:function(parsedSelector){return/:host-context|:dir/.test(parsedSelector);},_scopeSelector:function(rule,hostRx,hostSelector,viaAttr,scopeId){rule.transformedSelector=rule.transformedSelector||rule.selector;var selector=rule.transformedSelector;var scope=styleTransformer._calcElementScope(scopeId,viaAttr);var hostScope=styleTransformer._calcElementScope(hostSelector,viaAttr);var parts=selector.split(',');var isDirOrHostContextSelector=this._hasDirOrHostContext(rule.parsedSelector);for(var i=0,l=parts.length,p;i<l&&(p=parts[i]);i++){parts[i]=p.match(hostRx)?p.replace(hostSelector,scope):isDirOrHostContextSelector?p.replace(hostScope,scope+' '+hostScope):scope+' '+p;}
rule.selector=parts.join(',');},applyElementScopeSelector:function(element,selector,old,viaAttr){var c=viaAttr?element.getAttribute(styleTransformer.SCOPE_NAME):element.getAttribute('class')||'';var v=old?c.replace(old,selector):(c?c+' ':'')+this.XSCOPE_NAME+' '+selector;if(c!==v){if(viaAttr){element.setAttribute(styleTransformer.SCOPE_NAME,v);}else{element.setAttribute('class',v);}}},applyElementStyle:function(element,properties,selector,style){var cssText=style?style.textContent||'':this.transformStyles(element,properties,selector);var s=element._customStyle;if(s&&!settings.useNativeShadow&&s!==style){s._useCount--;if(s._useCount<=0&&s.parentNode){s.parentNode.removeChild(s);}}
if(settings.useNativeShadow){if(element._customStyle){element._customStyle.textContent=cssText;style=element._customStyle;}else if(cssText){style=styleUtil.applyCss(cssText,selector,element.root,element._scopeStyle);}}else{if(!style){if(cssText){style=styleUtil.applyCss(cssText,selector,null,element._scopeStyle);}}else if(!style.parentNode){if(IS_IE&&cssText.indexOf('@media')>-1){style.textContent=cssText;}
styleUtil.applyStyle(style,null,element._scopeStyle);}}
@@ -4058,7 +4189,7 @@ if(template._content._ctor){this.ctor=template._content._ctor;this._prepParentPr
var archetype=Object.create(Polymer.Base);this._customPrepAnnotations(archetype,template);this._prepParentProperties(archetype,template);archetype._prepEffects();this._customPrepEffects(archetype);archetype._prepBehaviors();archetype._prepPropertyInfo();archetype._prepBindings();archetype._notifyPathUp=this._notifyPathUpImpl;archetype._scopeElementClass=this._scopeElementClassImpl;archetype.listen=this._listenImpl;archetype._showHideChildren=this._showHideChildrenImpl;archetype.__setPropertyOrig=this.__setProperty;archetype.__setProperty=this.__setPropertyImpl;var _constructor=this._constructorImpl;var ctor=function TemplateInstance(model,host){_constructor.call(this,model,host);};ctor.prototype=archetype;archetype.constructor=ctor;template._content._ctor=ctor;this.ctor=ctor;},_getRootDataHost:function(){return this.dataHost&&this.dataHost._rootDataHost||this.dataHost;},_showHideChildrenImpl:function(hide){var c=this._children;for(var i=0;i<c.length;i++){var n=c[i];if(Boolean(hide)!=Boolean(n.__hideTemplateChildren__)){if(n.nodeType===Node.TEXT_NODE){if(hide){n.__polymerTextContent__=n.textContent;n.textContent='';}else{n.textContent=n.__polymerTextContent__;}}else if(n.style){if(hide){n.__polymerDisplay__=n.style.display;n.style.display='none';}else{n.style.display=n.__polymerDisplay__;}}}
n.__hideTemplateChildren__=hide;}},__setPropertyImpl:function(property,value,fromAbove,node){if(node&&node.__hideTemplateChildren__&&property=='textContent'){property='__polymerTextContent__';}
this.__setPropertyOrig(property,value,fromAbove,node);},_debounceTemplate:function(fn){Polymer.dom.addDebouncer(this.debounce('_debounceTemplate',fn));},_flushTemplates:function(){Polymer.dom.flush();},_customPrepEffects:function(archetype){var parentProps=archetype._parentProps;for(var prop in parentProps){archetype._addPropertyEffect(prop,'function',this._createHostPropEffector(prop));}
-for(prop in this._instanceProps){archetype._addPropertyEffect(prop,'function',this._createInstancePropEffector(prop));}},_customPrepAnnotations:function(archetype,template){archetype._template=template;var c=template._content;if(!c._notes){var rootDataHost=archetype._rootDataHost;if(rootDataHost){Polymer.Annotations.prepElement=function(){rootDataHost._prepElement();};}
+for(prop in this._instanceProps){archetype._addPropertyEffect(prop,'function',this._createInstancePropEffector(prop));}},_customPrepAnnotations:function(archetype,template){var t=archetype._template=document.createElement('template');var c=t._content=template._content;if(!c._notes){var rootDataHost=archetype._rootDataHost;if(rootDataHost){Polymer.Annotations.prepElement=function(){rootDataHost._prepElement();};}
c._notes=Polymer.Annotations.parseAnnotations(template);Polymer.Annotations.prepElement=null;this._processAnnotations(c._notes);}
archetype._notes=c._notes;archetype._parentProps=c._parentProps;},_prepParentProperties:function(archetype,template){var parentProps=this._parentProps=archetype._parentProps;if(this._forwardParentProp&&parentProps){var proto=archetype._parentPropProto;var prop;if(!proto){for(prop in this._instanceProps){delete parentProps[prop];}
proto=archetype._parentPropProto=Object.create(null);if(template!=this){Polymer.Bind.prepareModel(proto);Polymer.Base.prepareModelNotifyPath(proto);}
@@ -4273,10 +4404,11 @@ function lesserPower(x,opt_base){const base=opt_base||10;return Math.pow(base,Ma
function greaterPower(x,opt_base){const base=opt_base||10;return Math.pow(base,Math.ceil(logOrLog10(x,base)));}
function lesserWholeNumber(x){if(x===0)return 0;const pow10=(x<0)?-lesserPower(-x):lesserPower(x);return pow10*Math.floor(x/pow10);}
function greaterWholeNumber(x){if(x===0)return 0;const pow10=(x<0)?-lesserPower(-x):lesserPower(x);return pow10*Math.ceil(x/pow10);}
+function truncate(value,digits){const pow10=Math.pow(10,digits);return Math.round(value*pow10)/pow10;}
function preferredNumberLargerThanMin(min){const absMin=Math.abs(min);const conservativeGuess=tr.b.math.lesserPower(absMin);let minPreferedNumber=undefined;for(const multiplier of PREFERRED_NUMBER_SERIES_MULTIPLIERS){const tightenedGuess=conservativeGuess*multiplier;if(tightenedGuess>=absMin){minPreferedNumber=tightenedGuess;break;}}
if(minPreferedNumber===undefined){throw new Error('Could not compute preferred number for '+min);}
if(min<0)minPreferedNumber*=-1;return minPreferedNumber;}
-return{approximately,clamp,lerp,normalize,deg2rad,erf,lesserPower,greaterPower,lesserWholeNumber,greaterWholeNumber,preferredNumberLargerThanMin,};});'use strict';tr.exportTo('tr.b.math',function(){function Range(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;}
+return{approximately,clamp,lerp,normalize,deg2rad,erf,lesserPower,greaterPower,lesserWholeNumber,greaterWholeNumber,preferredNumberLargerThanMin,truncate,};});'use strict';tr.exportTo('tr.b.math',function(){function Range(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;}
Range.prototype={__proto__:Object.prototype,clone(){if(this.isEmpty)return new Range();return Range.fromExplicitRange(this.min_,this.max_);},reset(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;},get isEmpty(){return this.isEmpty_;},addRange(range){if(range.isEmpty)return;this.addValue(range.min);this.addValue(range.max);},addValue(value){if(this.isEmpty_){this.max_=value;this.min_=value;this.isEmpty_=false;return;}
this.max_=Math.max(this.max_,value);this.min_=Math.min(this.min_,value);},set min(min){this.isEmpty_=false;this.min_=min;},get min(){if(this.isEmpty_)return undefined;return this.min_;},get max(){if(this.isEmpty_)return undefined;return this.max_;},set max(max){this.isEmpty_=false;this.max_=max;},get range(){if(this.isEmpty_)return undefined;return this.max_-this.min_;},get center(){return(this.min_+this.max_)*0.5;},get duration(){if(this.isEmpty_)return 0;return this.max_-this.min_;},enclosingPowers(opt_base){if(this.isEmpty)return new Range();return Range.fromExplicitRange(tr.b.math.lesserPower(this.min_,opt_base),tr.b.math.greaterPower(this.max_,opt_base));},normalize(x){return tr.b.math.normalize(x,this.min,this.max);},lerp(x){return tr.b.math.lerp(x,this.min,this.max);},clamp(x){return tr.b.math.clamp(x,this.min,this.max);},equals(that){if(this.isEmpty&&that.isEmpty)return true;if(this.isEmpty!==that.isEmpty)return false;return(tr.b.math.approximately(this.min,that.min)&&tr.b.math.approximately(this.max,that.max));},containsExplicitRangeInclusive(min,max){if(this.isEmpty)return false;return this.min_<=min&&max<=this.max_;},containsExplicitRangeExclusive(min,max){if(this.isEmpty)return false;return this.min_<min&&max<this.max_;},intersectsExplicitRangeInclusive(min,max){if(this.isEmpty)return false;return this.min_<=max&&min<=this.max_;},intersectsExplicitRangeExclusive(min,max){if(this.isEmpty)return false;return this.min_<max&&min<this.max_;},containsRangeInclusive(range){if(range.isEmpty)return false;return this.containsExplicitRangeInclusive(range.min_,range.max_);},containsRangeExclusive(range){if(range.isEmpty)return false;return this.containsExplicitRangeExclusive(range.min_,range.max_);},intersectsRangeInclusive(range){if(range.isEmpty)return false;return this.intersectsExplicitRangeInclusive(range.min_,range.max_);},intersectsRangeExclusive(range){if(range.isEmpty)return false;return this.intersectsExplicitRangeExclusive(range.min_,range.max_);},findExplicitIntersectionDuration(min,max){min=Math.max(this.min,min);max=Math.min(this.max,max);if(max<min)return 0;return max-min;},findIntersection(range){if(this.isEmpty||range.isEmpty)return new Range();const min=Math.max(this.min,range.min);const max=Math.min(this.max,range.max);if(max<min)return new Range();return Range.fromExplicitRange(min,max);},toJSON(){if(this.isEmpty_)return{isEmpty:true};return{isEmpty:false,max:this.max,min:this.min};},filterArray(sortedArray,opt_keyFunc,opt_this){if(this.isEmpty_)return[];const keyFunc=opt_keyFunc||(x=>x);function getValue(obj){return keyFunc.call(opt_this,obj);}
const first=tr.b.findFirstTrueIndexInSortedArray(sortedArray,obj=>this.min_===undefined||this.min_<=getValue(obj));const last=tr.b.findFirstTrueIndexInSortedArray(sortedArray,obj=>this.max_!==undefined&&this.max_<getValue(obj));return sortedArray.slice(first,last);}};Range.fromDict=function(d){if(d.isEmpty===true)return new Range();if(d.isEmpty===false){const range=new Range();range.min=d.min;range.max=d.max;return range;}
@@ -4379,7 +4511,9 @@ formatter=new Intl.NumberFormat(undefined,{minimumFractionDigits,maximumFraction
return formatter;}
function max(a,b){if(a===undefined)return b;if(b===undefined)return a;return a.scale>b.scale?a:b;}
const ImprovementDirection={DONT_CARE:0,BIGGER_IS_BETTER:1,SMALLER_IS_BETTER:2};function Unit(unitName,jsonName,scaleBaseUnit,isDelta,improvementDirection,formatSpec){this.unitName=unitName;this.jsonName=jsonName;this.scaleBaseUnit=scaleBaseUnit;this.isDelta=isDelta;this.improvementDirection=improvementDirection;this.formatSpec_=formatSpec;this.baseUnit=undefined;this.correspondingDeltaUnit=undefined;}
-Unit.prototype={asJSON(){return this.jsonName;},getUnitScale_(opt_context){let formatSpec=this.formatSpec_;let formatSpecWasFunction=false;if(typeof formatSpec==='function'){formatSpecWasFunction=true;formatSpec=formatSpec();}
+Unit.prototype={asJSON(){return this.jsonName;},asJSON2(){return this.asJSON().replace('_smallerIsBetter','-').replace('_biggerIsBetter','+');},truncate(value){if(typeof value!=='number')return value;if(0===(value%1))return value;if(typeof this.formatSpec_!=='function'&&(!this.formatSpec_.unitScale||((this.formatSpec_.unitScale.length===1)&&(this.formatSpec_.unitScale[0].value===1)))){const digits=this.formatSpec_.maximumFractionDigits||this.formatSpec_.minimumFractionDigits;return tr.b.math.truncate(value,digits+1);}
+const formatted=this.format(value);let test=Math.round(value);if(formatted===this.format(test))return test;let lo=1;let hi=16;while(lo<hi-1){const digits=parseInt((lo+hi)/2);test=tr.b.math.truncate(value,digits);if(formatted===this.format(test)){hi=digits;}else{lo=digits;}}
+test=tr.b.math.truncate(value,lo);if(formatted===this.format(test))return test;return tr.b.math.truncate(value,hi);},getUnitScale_(opt_context){let formatSpec=this.formatSpec_;let formatSpecWasFunction=false;if(typeof formatSpec==='function'){formatSpecWasFunction=true;formatSpec=formatSpec();}
const context=opt_context||{};let scale=undefined;if(context.unitScale){scale=context.unitScale;}else if(context.unitPrefix){const symbol=formatSpec.baseSymbol?formatSpec.baseSymbol:this.scaleBaseUnit.baseSymbol;scale=tr.b.UnitScale.defineUnitScaleFromPrefixScale(symbol,symbol,[context.unitPrefix]).AUTO;}else{scale=formatSpec.unitScale;if(!scale){scale=[{value:1,symbol:formatSpec.baseSymbol||'',baseSymbol:formatSpec.baseSymbol||''}];if(!formatSpecWasFunction)formatSpec.unitScale=scale;}}
if(!(scale instanceof Array)){throw new Error('Unit has a malformed unit scale.');}
return scale;},get unitString(){const scale=this.getUnitScale_();if(!scale){throw new Error('A UnitScale could not be found for Unit '+this.unitName);}
@@ -4387,7 +4521,8 @@ return scale[0].symbol;},format(value,opt_context){let signString='';if(value<0)
const context=opt_context||{};const scale=this.getUnitScale_(context);let deltaValue=context.deltaValue===undefined?value:context.deltaValue;deltaValue=Math.abs(deltaValue)*this.scaleBaseUnit.value;if(deltaValue===0){deltaValue=1;}
let i=0;while(i<scale.length-1&&deltaValue/scale[i+1].value>=1){i++;}
const selectedSubUnit=scale[i];let formatSpec=this.formatSpec_;if(typeof formatSpec==='function')formatSpec=formatSpec();let unitString='';if(selectedSubUnit.symbol){if(!formatSpec.avoidSpacePrecedingUnit)unitString=' ';unitString+=selectedSubUnit.symbol;}
-value=tr.b.convertUnit(value,this.scaleBaseUnit,selectedSubUnit);const numberString=getNumberFormatter(formatSpec.minimumFractionDigits,formatSpec.maximumFractionDigits,context.minimumFractionDigits,context.maximumFractionDigits).format(value);return signString+numberString+unitString;}};Unit.reset=function(){Unit.currentTimeDisplayMode=TimeDisplayModes.ms;};Unit.timestampFromUs=function(us){return tr.b.convertUnit(us,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);};Object.defineProperty(Unit,'currentTimeDisplayMode',{get(){return Unit.currentTimeDisplayMode_;},set(value){if(Unit.currentTimeDisplayMode_===value)return;Unit.currentTimeDisplayMode_=value;Unit.dispatchEvent(new tr.b.Event('display-mode-changed'));}});Unit.didPreferredTimeDisplayUnitChange=function(){let largest=undefined;const els=tr.ui.b.findDeepElementsMatching(document.body,'tr-v-ui-preferred-display-unit');els.forEach(function(el){largest=max(largest,el.preferredTimeDisplayMode);});Unit.currentTimeDisplayMode=largest===undefined?TimeDisplayModes.ms:largest;};Unit.byName={};Unit.byJSONName={};Unit.fromJSON=function(object){const u=Unit.byJSONName[object];if(u){return u;}
+value=tr.b.convertUnit(value,this.scaleBaseUnit,selectedSubUnit);const numberString=getNumberFormatter(formatSpec.minimumFractionDigits,formatSpec.maximumFractionDigits,context.minimumFractionDigits,context.maximumFractionDigits).format(value);return signString+numberString+unitString;}};Unit.reset=function(){Unit.currentTimeDisplayMode=TimeDisplayModes.ms;};Unit.timestampFromUs=function(us){return tr.b.convertUnit(us,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);};Object.defineProperty(Unit,'currentTimeDisplayMode',{get(){return Unit.currentTimeDisplayMode_;},set(value){if(Unit.currentTimeDisplayMode_===value)return;Unit.currentTimeDisplayMode_=value;Unit.dispatchEvent(new tr.b.Event('display-mode-changed'));}});Unit.didPreferredTimeDisplayUnitChange=function(){let largest=undefined;const els=tr.ui.b.findDeepElementsMatching(document.body,'tr-v-ui-preferred-display-unit');els.forEach(function(el){largest=max(largest,el.preferredTimeDisplayMode);});Unit.currentTimeDisplayMode=largest===undefined?TimeDisplayModes.ms:largest;};Unit.byName={};Unit.byJSONName={};Unit.fromJSON=function(object){if(typeof(object)==='string'){if(object.endsWith('+')){object=object.slice(0,object.length-1)+'_biggerIsBetter';}else if(object.endsWith('-')){object=object.slice(0,object.length-1)+'_smallerIsBetter';}
+const u=Unit.byJSONName[object];if(u)return u;}
throw new Error(`Unrecognized unit "${object}"`);};Unit.define=function(params){const definedUnits=[];for(const improvementDirection of Object.values(ImprovementDirection)){const regularUnit=Unit.defineUnitVariant_(params,false,improvementDirection);const deltaUnit=Unit.defineUnitVariant_(params,true,improvementDirection);regularUnit.correspondingDeltaUnit=deltaUnit;deltaUnit.correspondingDeltaUnit=deltaUnit;definedUnits.push(regularUnit,deltaUnit);}
const baseUnit=Unit.byName[params.baseUnitName];definedUnits.forEach(u=>u.baseUnit=baseUnit);};Unit.nameSuffixForImprovementDirection=function(improvementDirection){switch(improvementDirection){case ImprovementDirection.DONT_CARE:return'';case ImprovementDirection.BIGGER_IS_BETTER:return'_biggerIsBetter';case ImprovementDirection.SMALLER_IS_BETTER:return'_smallerIsBetter';default:throw new Error('Unknown improvement direction: '+improvementDirection);}};Unit.defineUnitVariant_=function(params,isDelta,improvementDirection){let nameSuffix=isDelta?'Delta':'';nameSuffix+=Unit.nameSuffixForImprovementDirection(improvementDirection);const unitName=params.baseUnitName+nameSuffix;const jsonName=params.baseJsonName+nameSuffix;if(Unit.byName[unitName]!==undefined){throw new Error('Unit \''+unitName+'\' already exists');}
if(Unit.byJSONName[jsonName]!==undefined){throw new Error('JSON unit \''+jsonName+'\' alread exists');}
@@ -4421,7 +4556,7 @@ return{h,s,l,a:this.a};},toStringWithAlphaOverride(alpha){return'rgba('+
this.r+','+this.g+','+
this.b+','+alpha+')';}};return{Color,};});'use strict';tr.exportTo('tr.b',function(){function SinebowColorGenerator(opt_a,opt_brightness){this.a_=(opt_a===undefined)?1:opt_a;this.brightness_=(opt_brightness===undefined)?1:opt_brightness;this.colorIndex_=0;this.keyToColor={};}
SinebowColorGenerator.prototype={colorForKey(key){if(!this.keyToColor[key]){this.keyToColor[key]=this.nextColor();}
-return this.keyToColor[key];},nextColor(){const components=SinebowColorGenerator.nthColor(this.colorIndex_++);return tr.b.Color.fromString(SinebowColorGenerator.calculateColor(components[0],components[1],components[2],this.a_,this.brightness_));}};SinebowColorGenerator.PHI=(1+Math.sqrt(5))/2;SinebowColorGenerator.sinebow_=function(h){h+=0.5;h=-h;let r=Math.sin(Math.PI*h);let g=Math.sin(Math.PI*(h+1/3));let b=Math.sin(Math.PI*(h+2/3));r*=r;g*=g;b*=b;const y=2*(0.2989*r+0.5870*g+0.1140*b);r/=y;g/=y;b/=y;return[256*r,256*g,256*b];};SinebowColorGenerator.nthColor=function(n){return SinebowColorGenerator.sinebow_(n*this.PHI);};SinebowColorGenerator.calculateColor=function(r,g,b,a,brightness){if(brightness<=1){r*=brightness;g*=brightness;b*=brightness;}else{r=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),r,255);g=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),g,255);b=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),b,255);}
+return this.keyToColor[key];},nextColor(){const components=SinebowColorGenerator.nthColor(this.colorIndex_++);return tr.b.Color.fromString(SinebowColorGenerator.calculateColor(components[0],components[1],components[2],this.a_,this.brightness_));}};SinebowColorGenerator.PHI=(1+Math.sqrt(5))/2;SinebowColorGenerator.sinebow=function(h){h+=0.5;h=-h;let r=Math.sin(Math.PI*h);let g=Math.sin(Math.PI*(h+1/3));let b=Math.sin(Math.PI*(h+2/3));r*=r;g*=g;b*=b;const y=2*(0.2989*r+0.5870*g+0.1140*b);r/=y;g/=y;b/=y;return[256*r,256*g,256*b];};SinebowColorGenerator.nthColor=function(n){return SinebowColorGenerator.sinebow(n*this.PHI);};SinebowColorGenerator.calculateColor=function(r,g,b,a,brightness){if(brightness<=1){r*=brightness;g*=brightness;b*=brightness;}else{r=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),r,255);g=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),g,255);b=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),b,255);}
r=Math.round(r);g=Math.round(g);b=Math.round(b);return'rgba('+r+','+g+','+b+', '+a+')';};return{SinebowColorGenerator,};});'use strict';tr.exportTo('tr.b',function(){const numGeneralPurposeColorIds=23;const generalPurposeColors=new Array(numGeneralPurposeColorIds);const sinebowAlpha=1.0;const sinebowBrightness=1.5;const sinebowColorGenerator=new tr.b.SinebowColorGenerator(sinebowAlpha,sinebowBrightness);for(let i=0;i<numGeneralPurposeColorIds;i++){generalPurposeColors[i]=sinebowColorGenerator.nextColor();}
const reservedColorsByName={thread_state_uninterruptible:new tr.b.Color(182,125,143),thread_state_iowait:new tr.b.Color(255,140,0),thread_state_running:new tr.b.Color(126,200,148),thread_state_runnable:new tr.b.Color(133,160,210),thread_state_sleeping:new tr.b.Color(240,240,240),thread_state_unknown:new tr.b.Color(199,155,125),background_memory_dump:new tr.b.Color(0,180,180),light_memory_dump:new tr.b.Color(0,0,180),detailed_memory_dump:new tr.b.Color(180,0,180),vsync_highlight_color:new tr.b.Color(0,0,255),generic_work:new tr.b.Color(125,125,125),good:new tr.b.Color(0,125,0),bad:new tr.b.Color(180,125,0),terrible:new tr.b.Color(180,0,0),black:new tr.b.Color(0,0,0),grey:new tr.b.Color(221,221,221),white:new tr.b.Color(255,255,255),yellow:new tr.b.Color(255,255,0),olive:new tr.b.Color(100,100,0),rail_response:new tr.b.Color(67,135,253),rail_animation:new tr.b.Color(244,74,63),rail_idle:new tr.b.Color(238,142,0),rail_load:new tr.b.Color(13,168,97),startup:new tr.b.Color(230,230,0),heap_dump_stack_frame:new tr.b.Color(128,128,128),heap_dump_object_type:new tr.b.Color(0,0,255),heap_dump_child_node_arrow:new tr.b.Color(204,102,0),cq_build_running:new tr.b.Color(255,255,119),cq_build_passed:new tr.b.Color(153,238,102),cq_build_failed:new tr.b.Color(238,136,136),cq_build_abandoned:new tr.b.Color(187,187,187),cq_build_attempt_runnig:new tr.b.Color(222,222,75),cq_build_attempt_passed:new tr.b.Color(103,218,35),cq_build_attempt_failed:new tr.b.Color(197,81,81)};const numReservedColorIds=Object.keys(reservedColorsByName).length;const numColorsPerVariant=numGeneralPurposeColorIds+numReservedColorIds;function ColorScheme(){}
const paletteBase=[];paletteBase.push.apply(paletteBase,generalPurposeColors);paletteBase.push.apply(paletteBase,Object.values(reservedColorsByName));ColorScheme.colors=[];ColorScheme.properties={};ColorScheme.properties={numColorsPerVariant,};function pushVariant(func){const variantColors=paletteBase.map(func);ColorScheme.colors.push.apply(ColorScheme.colors,variantColors);}
@@ -4627,20 +4762,22 @@ ChromeGpuHelper.PROCESS_NAME='GPU Process';ChromeGpuHelper.isGpuProcess=function
return process.findAllThreadsNamed('CrGpuMain').length>0;};ChromeGpuHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype};return{ChromeGpuHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const NET_CATEGORIES=new Set(['net','netlog','disabled-by-default-netlog','disabled-by-default-network']);class ChromeThreadHelper{constructor(thread){this.thread=thread;}
getNetworkEvents(){const networkEvents=[];for(const slice of this.thread.asyncSliceGroup.slices){const categories=tr.b.getCategoryParts(slice.category);const isNetEvent=category=>NET_CATEGORIES.has(category);if(categories.filter(isNetEvent).length===0)continue;networkEvents.push(slice);}
return networkEvents;}}
-return{ChromeThreadHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const ChromeThreadHelper=tr.model.helpers.ChromeThreadHelper;function ChromeRendererHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain')||process.findAtMostOneThreadNamed('Chrome_InProcRendererThread');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)return false;if(t.name.indexOf('CompositorTileWorker')===0)return true;if(t.name.indexOf('CompositorRasterWorker')===0)return true;return false;});if(!process.name){process.name=ChromeRendererHelper.PROCESS_NAME;}}
-ChromeRendererHelper.PROCESS_NAME='Renderer';ChromeRendererHelper.isRenderProcess=function(process){if(process.findAtMostOneThreadNamed('CrRendererMain'))return true;if(process.findAtMostOneThreadNamed('Compositor'))return true;return false;};ChromeRendererHelper.isTracingProcess=function(process){return process.labels!==undefined&&process.labels.length===1&&process.labels[0]==='chrome://tracing';};ChromeRendererHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;},get isChromeTracingUI(){return ChromeRendererHelper.isTracingProcess(this.process);},};return{ChromeRendererHelper,};});'use strict';tr.exportTo('tr.model.um',function(){class Segment extends tr.model.TimedEvent{constructor(start,duration){super(start);this.duration=duration;this.expectations_=[];}
+return{ChromeThreadHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const ChromeThreadHelper=tr.model.helpers.ChromeThreadHelper;function ChromeRendererHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain')||process.findAtMostOneThreadNamed('Chrome_InProcRendererThread');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)return false;if(t.name.startsWith('CompositorTileWorker'))return true;if(t.name.startsWith('CompositorRasterWorker'))return true;return false;});this.dedicatedWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('DedicatedWorker');});this.foregroundWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ThreadPoolForegroundWorker');});if(!process.name){process.name=ChromeRendererHelper.PROCESS_NAME;}}
+ChromeRendererHelper.PROCESS_NAME='Renderer';ChromeRendererHelper.isRenderProcess=function(process){if(process.findAtMostOneThreadNamed('CrRendererMain'))return true;if(process.findAtMostOneThreadNamed('Compositor'))return true;return false;};ChromeRendererHelper.isTracingProcess=function(process){return process.labels!==undefined&&process.labels.length===1&&process.labels[0]==='chrome://tracing';};ChromeRendererHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;},get dedicatedWorkerThreads(){return this.dedicatedWorkerThreads_;},get foregroundWorkerThreads(){return this.foregroundWorkerThreads_;},get isChromeTracingUI(){return ChromeRendererHelper.isTracingProcess(this.process);},};return{ChromeRendererHelper,};});'use strict';tr.exportTo('tr.model.um',function(){class Segment extends tr.model.TimedEvent{constructor(start,duration){super(start);this.duration=duration;this.expectations_=[];}
get expectations(){return this.expectations_;}
clone(){const clone=new Segment(this.start,this.duration);clone.expectations.push(...this.expectations);return clone;}
addSegment(other){this.duration+=other.duration;this.expectations.push(...other.expectations);}}
-return{Segment,};});'use strict';tr.exportTo('tr.model.helpers',function(){const GESTURE_EVENT='SyntheticGestureController::running';const IR_REG_EXP=/Interaction\.([^/]+)(\/[^/]*)?$/;const ChromeRendererHelper=tr.model.helpers.ChromeRendererHelper;class TelemetryHelper{constructor(modelHelper){this.modelHelper=modelHelper;this.renderersWithIR_=undefined;this.segments_=undefined;this.uiSegments_=undefined;}
+return{Segment,};});'use strict';tr.exportTo('tr.model.helpers',function(){const GESTURE_EVENT='SyntheticGestureController::running';const IR_REG_EXP=/Interaction\.([^/]+)(\/[^/]*)?$/;const ChromeRendererHelper=tr.model.helpers.ChromeRendererHelper;class TelemetryHelper{constructor(modelHelper){this.modelHelper=modelHelper;this.renderersWithIR_=undefined;this.irSegments_=undefined;this.uiSegments_=undefined;this.animationSegments_=undefined;}
get renderersWithIR(){this.findIRs_();return this.renderersWithIR_;}
-get segments(){this.findIRs_();return this.segments_;}
+get irSegments(){this.findIRs_();return this.irSegments_;}
get uiSegments(){this.findIRs_();return this.uiSegments_;}
-findIRs_(){if(this.segments_!==undefined)return;this.renderersWithIR_=[];const gestureEvents=[];const interactionRecords=[];const processes=Object.values(this.modelHelper.rendererHelpers).concat(this.modelHelper.browserHelpers).map(processHelper=>processHelper.process);for(const process of processes){let foundIR=false;for(const thread of Object.values(process.threads)){for(const slice of thread.asyncSliceGroup.slices){if(slice.title===GESTURE_EVENT){gestureEvents.push(slice);}else if(IR_REG_EXP.test(slice.title)){interactionRecords.push(slice);foundIR=true;}}}
+get animationSegments(){if(this.animationSegments_===undefined){const model=this.modelHelper.model;this.animationSegments_=model.userModel.segments.filter(segment=>segment.expectations.find(ue=>ue instanceof tr.model.um.AnimationExpectation));this.animationSegments_.sort((x,y)=>x.start-y.start);}
+return this.animationSegments_;}
+findIRs_(){if(this.irSegments_!==undefined)return;this.renderersWithIR_=[];const gestureEvents=[];const interactionRecords=[];const processes=Object.values(this.modelHelper.rendererHelpers).concat(this.modelHelper.browserHelpers).map(processHelper=>processHelper.process);for(const process of processes){let foundIR=false;for(const thread of Object.values(process.threads)){for(const slice of thread.asyncSliceGroup.slices){if(slice.title===GESTURE_EVENT){gestureEvents.push(slice);}else if(IR_REG_EXP.test(slice.title)){interactionRecords.push(slice);foundIR=true;}}}
if(foundIR&&ChromeRendererHelper.isRenderProcess(process)&&!ChromeRendererHelper.isTracingProcess(process)){this.renderersWithIR_.push(new ChromeRendererHelper(this.modelHelper,process));}}
-this.segments_=[];this.uiSegments_=[];for(const ir of interactionRecords){const parts=IR_REG_EXP.exec(ir.title);let gestureEventFound=false;if(parts[1].startsWith('Gesture_')){for(const gestureEvent of gestureEvents){if(ir.boundsRange.intersectsRangeInclusive(gestureEvent.boundsRange)){this.segments_.push(new tr.model.um.Segment(gestureEvent.start,gestureEvent.duration));gestureEventFound=true;break;}}}else if(parts[1].startsWith('ui_')){this.uiSegments_.push(new tr.model.um.Segment(ir.start,ir.duration));}
-if(!gestureEventFound){this.segments_.push(new tr.model.um.Segment(ir.start,ir.duration));}}
-this.segments_.sort((x,y)=>x.start-y.start);this.uiSegments_.sort((x,y)=>x.start-y.start);}}
+this.irSegments_=[];this.uiSegments_=[];for(const ir of interactionRecords){const parts=IR_REG_EXP.exec(ir.title);let gestureEventFound=false;if(parts[1].startsWith('Gesture_')){for(const gestureEvent of gestureEvents){if(ir.boundsRange.intersectsRangeInclusive(gestureEvent.boundsRange)){this.irSegments_.push(new tr.model.um.Segment(gestureEvent.start,gestureEvent.duration));gestureEventFound=true;break;}}}else if(parts[1].startsWith('ui_')){this.uiSegments_.push(new tr.model.um.Segment(ir.start,ir.duration));}
+if(!gestureEventFound){this.irSegments_.push(new tr.model.um.Segment(ir.start,ir.duration));}}
+this.irSegments_.sort((x,y)=>x.start-y.start);this.uiSegments_.sort((x,y)=>x.start-y.start);}}
return{TelemetryHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){function findChromeBrowserProcesses(model){return model.getAllProcesses(tr.model.helpers.ChromeBrowserHelper.isBrowserProcess);}
function findChromeRenderProcesses(model){return model.getAllProcesses(tr.model.helpers.ChromeRendererHelper.isRenderProcess);}
function findChromeGpuProcess(model){const gpuProcesses=model.getAllProcesses(tr.model.helpers.ChromeGpuHelper.isGpuProcess);if(gpuProcesses.length!==1)return undefined;return gpuProcesses[0];}
@@ -4681,15 +4818,17 @@ const COMPOSITOR_ON_BIFD='Scheduler::OnBeginImplFrameDeadline';beginImplFrame=ev
const INPUT_GSU='InputLatency::GestureScrollUpdate';if(this.title===INPUT_GSU){this.addScrollUpdateEvents(rendererHelper);}},get associatedEvents(){if(this.associatedEvents_.length!==0){return this.associatedEvents_;}
const modelIndices=this.startThread.parent.model.modelIndices;const flowEvents=modelIndices.getFlowEventsWithId(this.id);if(flowEvents.length===0){return this.associatedEvents_;}
const sourceSlices=this.addDirectlyAssociatedEvents(flowEvents);const rendererHelper=this.getRendererHelper(sourceSlices);this.addOtherCausallyRelatedEvents(rendererHelper,sourceSlices,flowEvents);return this.associatedEvents_;},get inputLatency(){if(!('data'in this.args))return undefined;const data=this.args.data;const endTimeComp=data[END_COMP_NAME]||data[LEGACY_END_COMP_NAME];if(endTimeComp===undefined)return undefined;let latency=0;const endTime=endTimeComp.time;if(ORIGINAL_COMP_NAME in data){latency=endTime-data[ORIGINAL_COMP_NAME].time;}else if(UI_COMP_NAME in data){latency=endTime-data[UI_COMP_NAME].time;}else if(BEGIN_COMP_NAME in data){latency=endTime-data[BEGIN_COMP_NAME].time;}else{throw new Error('No valid begin latency component');}
-return latency;}};const eventTypeNames=['Char','ContextMenu','GestureClick','GestureFlingCancel','GestureFlingStart','GestureScrollBegin','GestureScrollEnd','GestureScrollUpdate','GestureShowPress','GestureTap','GestureTapCancel','GestureTapDown','GesturePinchBegin','GesturePinchEnd','GesturePinchUpdate','KeyDown','KeyUp','MouseDown','MouseEnter','MouseLeave','MouseMove','MouseUp','MouseWheel','RawKeyDown','ScrollUpdate','TouchCancel','TouchEnd','TouchMove','TouchStart'];const allTypeNames=['InputLatency'];eventTypeNames.forEach(function(eventTypeName){allTypeNames.push('InputLatency:'+eventTypeName);allTypeNames.push('InputLatency::'+eventTypeName);});AsyncSlice.subTypes.register(InputLatencyAsyncSlice,{typeNames:allTypeNames,categoryParts:['latencyInfo']});return{InputLatencyAsyncSlice,INPUT_EVENT_TYPE_NAMES,};});'use strict';tr.exportTo('tr.e.chrome',function(){const SAME_AS_PARENT='same-as-parent';const TITLES_FOR_USER_FRIENDLY_CATEGORY={composite:['CompositingInputsUpdater::update','ThreadProxy::SetNeedsUpdateLayers','LayerTreeHost::DoUpdateLayers','LayerTreeHost::UpdateLayers::BuildPropertyTrees','LocalFrameView::pushPaintArtifactToCompositor','LocalFrameView::updateCompositedSelectionIfNeeded','LocalFrameView::RunCompositingLifecyclePhase','UpdateLayerTree',],gc:['minorGC','majorGC','MajorGC','MinorGC','V8.GCScavenger','V8.GCIncrementalMarking','V8.GCIdleNotification','V8.GCContext','V8.GCCompactor','V8GCController::traceDOMWrappers',],iframe_creation:['WebLocalFrameImpl::createChildframe',],imageDecode:['Decode Image','ImageFrameGenerator::decode','ImageFrameGenerator::decodeAndScale','ImageResourceContent::updateImage',],input:['HitTest','ScrollableArea::scrollPositionChanged','EventHandler::handleMouseMoveEvent',],layout:['IntersectionObserverController::computeTrackedIntersectionObservations','LocalFrameView::invalidateTree','LocalFrameView::layout','LocalFrameView::performLayout','LocalFrameView::performPostLayoutTasks','LocalFrameView::performPreLayoutTasks','LocalFrameView::RunStyleAndLayoutCompositingPhases','Layout','PaintLayer::updateLayerPositionsAfterLayout','ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities','WebViewImpl::updateAllLifecyclePhases','WebViewImpl::beginFrame',],parseHTML:['BackgroundHTMLParser::pumpTokenizer','BackgroundHTMLParser::sendTokensToMainThread','HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser','HTMLDocumentParser::documentElementAvailable','HTMLDocumentParser::notifyPendingTokenizedChunks','HTMLDocumentParser::processParsedChunkFromBackgroundParser','HTMLDocumentParser::processTokenizedChunkFromBackgroundParser','ParseHTML',],raster:['DisplayListRasterSource::PerformSolidColorAnalysis','Picture::Raster','RasterBufferImpl::Playback','RasterTask','RasterizerTaskImpl::RunOnWorkerThread','SkCanvas::drawImageRect()','SkCanvas::drawPicture()','SkCanvas::drawTextBlob()','TileTaskWorkerPool::PlaybackToMemory',],record:['Canvas2DLayerBridge::flushRecordingOnly','CompositingInputsUpdater::update','CompositingRequirementsUpdater::updateRecursive','ContentLayerDelegate::paintContents','DisplayItemList::Finalize','LocalFrameView::RunPaintLifecyclePhase','LocalFrameView::RunPrePaintLifecyclePhase','Paint','PaintController::commitNewDisplayItems','PaintLayerCompositor::updateIfNeededRecursive','Picture::Record','PictureLayer::Update',],style:['CSSParserImpl::parseStyleSheet.parse','CSSParserImpl::parseStyleSheet.tokenize','Document::rebuildLayoutTree','Document::recalcStyle','Document::updateActiveStyle','Document::updateStyle','Document::updateStyleInvalidationIfNeeded','LocalFrameView::updateStyleAndLayoutIfNeededRecursive','ParseAuthorStyleSheet','RuleSet::addRulesFromSheet','StyleElement::processStyleSheet','StyleEngine::createResolver','StyleEngine::updateActiveStyleSheets','StyleSheetContents::parseAuthorStyleSheet','UpdateLayoutTree',],script_parse_and_compile:['V8.CompileFullCode','V8.NewContext','V8.Parse','V8.ParseLazy','V8.RecompileSynchronous','V8.ScriptCompiler','v8.compile','v8.parseOnBackground',],script_execute:['EvaluateScript','FunctionCall','HTMLParserScriptRunner ExecuteScript','V8.Execute','V8.RunMicrotasks','V8.Task','WindowProxy::initialize','v8.callFunction','v8.run',],resource_loading:['RenderFrameImpl::didFinishDocumentLoad','RenderFrameImpl::didFinishLoad','Resource::appendData','ResourceDispatcher::OnReceivedData','ResourceDispatcher::OnReceivedResponse','ResourceDispatcher::OnRequestComplete','ResourceFetcher::requestResource','WebURLLoaderImpl::Context::Cancel','WebURLLoaderImpl::Context::OnCompletedRequest','WebURLLoaderImpl::Context::OnReceivedData','WebURLLoaderImpl::Context::OnReceivedRedirect','WebURLLoaderImpl::Context::OnReceivedResponse','WebURLLoaderImpl::Context::Start','WebURLLoaderImpl::loadAsynchronously','WebURLLoaderImpl::loadSynchronously','content::mojom::URLLoaderClient',],renderer_misc:['DecodeFont','ThreadState::completeSweep',],v8_runtime:[],[SAME_AS_PARENT]:['SyncChannel::Send',]};const COLOR_FOR_USER_FRIENDLY_CATEGORY=new tr.b.SinebowColorGenerator();const USER_FRIENDLY_CATEGORY_FOR_TITLE=new Map();for(const category in TITLES_FOR_USER_FRIENDLY_CATEGORY){TITLES_FOR_USER_FRIENDLY_CATEGORY[category].forEach(function(title){USER_FRIENDLY_CATEGORY_FOR_TITLE.set(title,category);});}
+return latency;}};const eventTypeNames=['Char','ContextMenu','GestureClick','GestureFlingCancel','GestureFlingStart','GestureScrollBegin','GestureScrollEnd','GestureScrollUpdate','GestureShowPress','GestureTap','GestureTapCancel','GestureTapDown','GesturePinchBegin','GesturePinchEnd','GesturePinchUpdate','KeyDown','KeyUp','MouseDown','MouseEnter','MouseLeave','MouseMove','MouseUp','MouseWheel','RawKeyDown','ScrollUpdate','TouchCancel','TouchEnd','TouchMove','TouchStart'];const allTypeNames=['InputLatency'];eventTypeNames.forEach(function(eventTypeName){allTypeNames.push('InputLatency:'+eventTypeName);allTypeNames.push('InputLatency::'+eventTypeName);});AsyncSlice.subTypes.register(InputLatencyAsyncSlice,{typeNames:allTypeNames,categoryParts:['latencyInfo']});return{InputLatencyAsyncSlice,INPUT_EVENT_TYPE_NAMES,};});'use strict';tr.exportTo('tr.e.chrome',function(){const SAME_AS_PARENT='same-as-parent';const TITLES_FOR_USER_FRIENDLY_CATEGORY={composite:['CompositingInputsUpdater::update','ThreadProxy::SetNeedsUpdateLayers','LayerTreeHost::DoUpdateLayers','LayerTreeHost::UpdateLayers::BuildPropertyTrees','LocalFrameView::pushPaintArtifactToCompositor','LocalFrameView::updateCompositedSelectionIfNeeded','LocalFrameView::RunCompositingLifecyclePhase','UpdateLayerTree',],gc:['minorGC','majorGC','MajorGC','MinorGC','V8.GCScavenger','V8.GCIncrementalMarking','V8.GCIdleNotification','V8.GCContext','V8.GCCompactor','V8GCController::traceDOMWrappers',],iframe_creation:['WebLocalFrameImpl::createChildframe',],imageDecode:['Decode Image','ImageFrameGenerator::decode','ImageFrameGenerator::decodeAndScale','ImageFrameGenerator::decodeToYUV','ImageResourceContent::updateImage',],input:['HitTest','ScrollableArea::scrollPositionChanged','EventHandler::handleMouseMoveEvent',],layout:['IntersectionObserverController::computeTrackedIntersectionObservations','LocalFrameView::invalidateTree','LocalFrameView::layout','LocalFrameView::performLayout','LocalFrameView::performPostLayoutTasks','LocalFrameView::performPreLayoutTasks','LocalFrameView::RunStyleAndLayoutCompositingPhases','Layout','PaintLayer::updateLayerPositionsAfterLayout','ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities','WebViewImpl::updateAllLifecyclePhases','WebViewImpl::beginFrame',],parseHTML:['BackgroundHTMLParser::pumpTokenizer','BackgroundHTMLParser::sendTokensToMainThread','HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser','HTMLDocumentParser::documentElementAvailable','HTMLDocumentParser::notifyPendingTokenizedChunks','HTMLDocumentParser::processParsedChunkFromBackgroundParser','HTMLDocumentParser::processTokenizedChunkFromBackgroundParser','ParseHTML',],raster:['DisplayListRasterSource::PerformSolidColorAnalysis','Picture::Raster','RasterBufferImpl::Playback','RasterTask','RasterizerTaskImpl::RunOnWorkerThread','SkCanvas::drawImageRect()','SkCanvas::drawPicture()','SkCanvas::drawTextBlob()','TileTaskWorkerPool::PlaybackToMemory',],record:['Canvas2DLayerBridge::flushRecordingOnly','CompositingInputsUpdater::update','CompositingRequirementsUpdater::updateRecursive','ContentLayerDelegate::paintContents','DisplayItemList::Finalize','LocalFrameView::RunPaintLifecyclePhase','LocalFrameView::RunPrePaintLifecyclePhase','Paint','PaintController::commitNewDisplayItems','PaintLayerCompositor::updateIfNeededRecursive','Picture::Record','PictureLayer::Update',],style:['CSSParserImpl::parseStyleSheet.parse','CSSParserImpl::parseStyleSheet.tokenize','Document::rebuildLayoutTree','Document::recalcStyle','Document::updateActiveStyle','Document::updateStyle','Document::updateStyleInvalidationIfNeeded','LocalFrameView::updateStyleAndLayoutIfNeededRecursive','ParseAuthorStyleSheet','RuleSet::addRulesFromSheet','StyleElement::processStyleSheet','StyleEngine::createResolver','StyleEngine::updateActiveStyleSheets','StyleSheetContents::parseAuthorStyleSheet','UpdateLayoutTree',],script_parse_and_compile:['V8.CompileFullCode','V8.NewContext','V8.Parse','V8.ParseLazy','V8.RecompileSynchronous','V8.ScriptCompiler','v8.compile','v8.parseOnBackground',],script_execute:['EvaluateScript','FunctionCall','HTMLParserScriptRunner ExecuteScript','V8.Execute','V8.RunMicrotasks','V8.Task','WindowProxy::initialize','v8.callFunction','v8.run',],resource_loading:['RenderFrameImpl::didFinishDocumentLoad','RenderFrameImpl::didFinishLoad','Resource::appendData','ResourceDispatcher::OnReceivedData','ResourceDispatcher::OnReceivedResponse','ResourceDispatcher::OnRequestComplete','ResourceFetcher::requestResource','WebURLLoaderImpl::Context::Cancel','WebURLLoaderImpl::Context::OnCompletedRequest','WebURLLoaderImpl::Context::OnReceivedData','WebURLLoaderImpl::Context::OnReceivedRedirect','WebURLLoaderImpl::Context::OnReceivedResponse','WebURLLoaderImpl::Context::Start','WebURLLoaderImpl::loadAsynchronously','WebURLLoaderImpl::loadSynchronously','content::mojom::URLLoaderClient',],renderer_misc:['DecodeFont','ThreadState::completeSweep',],v8_runtime:[],[SAME_AS_PARENT]:['SyncChannel::Send',]};const COLOR_FOR_USER_FRIENDLY_CATEGORY=new tr.b.SinebowColorGenerator();const USER_FRIENDLY_CATEGORY_FOR_TITLE=new Map();for(const category in TITLES_FOR_USER_FRIENDLY_CATEGORY){TITLES_FOR_USER_FRIENDLY_CATEGORY[category].forEach(function(title){USER_FRIENDLY_CATEGORY_FOR_TITLE.set(title,category);});}
const USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY={netlog:'net',overhead:'overhead',startup:'startup',gpu:'gpu',};function ChromeUserFriendlyCategoryDriver(){}
ChromeUserFriendlyCategoryDriver.fromEvent=function(event){let userFriendlyCategory=USER_FRIENDLY_CATEGORY_FOR_TITLE.get(event.title);if(userFriendlyCategory){if(userFriendlyCategory===SAME_AS_PARENT){if(event.parentSlice){return ChromeUserFriendlyCategoryDriver.fromEvent(event.parentSlice);}}else{return userFriendlyCategory;}}
const eventCategoryParts=tr.b.getCategoryParts(event.category);for(let i=0;i<eventCategoryParts.length;++i){const eventCategory=eventCategoryParts[i];userFriendlyCategory=USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY[eventCategory];if(userFriendlyCategory){return userFriendlyCategory;}}
return'other';};ChromeUserFriendlyCategoryDriver.getColor=function(ufc){return COLOR_FOR_USER_FRIENDLY_CATEGORY.colorForKey(ufc);};ChromeUserFriendlyCategoryDriver.ALL_TITLES=['other'];for(const category in TITLES_FOR_USER_FRIENDLY_CATEGORY){if(category===SAME_AS_PARENT)continue;ChromeUserFriendlyCategoryDriver.ALL_TITLES.push(category);}
for(const category of Object.values(USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY)){ChromeUserFriendlyCategoryDriver.ALL_TITLES.push(category);}
ChromeUserFriendlyCategoryDriver.ALL_TITLES.sort();for(const category of ChromeUserFriendlyCategoryDriver.ALL_TITLES){ChromeUserFriendlyCategoryDriver.getColor(category);}
-return{ChromeUserFriendlyCategoryDriver,};});'use strict';tr.exportTo('tr.model',function(){return{BROWSER_PROCESS_PID_REF:-1,OBJECT_DEFAULT_SCOPE:'ptr',LOCAL_ID_PHASES:new Set(['N','D','O','(',')'])};});'use strict';tr.exportTo('tr.e.audits',function(){const Auditor=tr.c.Auditor;function ChromeAuditor(model){Auditor.call(this,model);const modelHelper=this.model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper&&modelHelper.browserHelper){this.modelHelper=modelHelper;}else{this.modelHelper=undefined;}}
-ChromeAuditor.prototype={__proto__:Auditor.prototype,runAnnotate(){if(!this.modelHelper)return;for(const pid in this.modelHelper.rendererHelpers){const rendererHelper=this.modelHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI){rendererHelper.process.important=false;}}},installUserFriendlyCategoryDriverIfNeeded(){this.model.addUserFriendlyCategoryDriver(tr.e.chrome.ChromeUserFriendlyCategoryDriver);},runAudit(){if(!this.modelHelper)return;this.model.replacePIDRefsInPatchups(tr.model.BROWSER_PROCESS_PID_REF,this.modelHelper.browserProcess.pid);this.model.applyObjectRefPatchups();}};Auditor.register(ChromeAuditor);return{ChromeAuditor,};});'use strict';tr.exportTo('tr.e.chrome',function(){const KNOWN_PROPERTIES={absX:1,absY:1,address:1,anonymous:1,childNeeds:1,children:1,classNames:1,col:1,colSpan:1,float:1,height:1,htmlId:1,name:1,posChildNeeds:1,positioned:1,positionedMovement:1,relX:1,relY:1,relativePositioned:1,row:1,rowSpan:1,selfNeeds:1,stickyPositioned:1,tag:1,width:1};function LayoutObject(snapshot,args){this.snapshot_=snapshot;this.id_=args.address;this.name_=args.name;this.childLayoutObjects_=[];this.otherProperties_={};this.tag_=args.tag;this.relativeRect_=tr.b.math.Rect.fromXYWH(args.relX,args.relY,args.width,args.height);this.absoluteRect_=tr.b.math.Rect.fromXYWH(args.absX,args.absY,args.width,args.height);this.isFloat_=args.float;this.isStickyPositioned_=args.stickyPositioned;this.isPositioned_=args.positioned;this.isRelativePositioned_=args.relativePositioned;this.isAnonymous_=args.anonymous;this.htmlId_=args.htmlId;this.classNames_=args.classNames;this.needsLayoutReasons_=[];if(args.selfNeeds){this.needsLayoutReasons_.push('self');}
+return{ChromeUserFriendlyCategoryDriver,};});'use strict';tr.exportTo('tr.model',function(){return{BROWSER_PROCESS_PID_REF:-1,OBJECT_DEFAULT_SCOPE:'ptr',LOCAL_ID_PHASES:new Set(['N','D','O','(',')'])};});'use strict';tr.exportTo('tr.e.audits',function(){const Auditor=tr.c.Auditor;const Alert=tr.model.Alert;const EventInfo=tr.model.EventInfo;function ChromeAuditor(model){Auditor.call(this,model);const modelHelper=this.model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper&&modelHelper.browserHelper){this.modelHelper=modelHelper;}else{this.modelHelper=undefined;}}
+function getMissedFrameAlerts(rendererHelpers){const alerts=[];for(const rendererHelper of rendererHelpers){if(!rendererHelper.compositorThread)continue;const thread=rendererHelper.compositorThread;const asyncSlices=Object.values(thread.asyncSliceGroup.slices);for(const slice of asyncSlices){if(slice.title!=='PipelineReporter'||!slice.args.termination_status||slice.args.termination_status!=='missed_frame')continue;const alertSlices=[slice].concat(slice.subSlices);alerts.push(new Alert(new EventInfo('Missed Frame','Frame was not submitted before deadline.'),slice.start,alertSlices));}}
+return alerts;}
+ChromeAuditor.prototype={__proto__:Auditor.prototype,runAnnotate(){if(!this.modelHelper)return;for(const pid in this.modelHelper.rendererHelpers){const rendererHelper=this.modelHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI){rendererHelper.process.important=false;}}},installUserFriendlyCategoryDriverIfNeeded(){this.model.addUserFriendlyCategoryDriver(tr.e.chrome.ChromeUserFriendlyCategoryDriver);},runAudit(){if(!this.modelHelper)return;this.model.replacePIDRefsInPatchups(tr.model.BROWSER_PROCESS_PID_REF,this.modelHelper.browserProcess.pid);this.model.applyObjectRefPatchups();const alerts=getMissedFrameAlerts(Object.values(this.modelHelper.rendererHelpers));this.model.alerts=this.model.alerts.concat(alerts);}};Auditor.register(ChromeAuditor);return{ChromeAuditor,};});'use strict';tr.exportTo('tr.e.chrome',function(){const KNOWN_PROPERTIES={absX:1,absY:1,address:1,anonymous:1,childNeeds:1,children:1,classNames:1,col:1,colSpan:1,float:1,height:1,htmlId:1,name:1,posChildNeeds:1,positioned:1,positionedMovement:1,relX:1,relY:1,relativePositioned:1,row:1,rowSpan:1,selfNeeds:1,stickyPositioned:1,tag:1,width:1};function LayoutObject(snapshot,args){this.snapshot_=snapshot;this.id_=args.address;this.name_=args.name;this.childLayoutObjects_=[];this.otherProperties_={};this.tag_=args.tag;this.relativeRect_=tr.b.math.Rect.fromXYWH(args.relX,args.relY,args.width,args.height);this.absoluteRect_=tr.b.math.Rect.fromXYWH(args.absX,args.absY,args.width,args.height);this.isFloat_=args.float;this.isStickyPositioned_=args.stickyPositioned;this.isPositioned_=args.positioned;this.isRelativePositioned_=args.relativePositioned;this.isAnonymous_=args.anonymous;this.htmlId_=args.htmlId;this.classNames_=args.classNames;this.needsLayoutReasons_=[];if(args.selfNeeds){this.needsLayoutReasons_.push('self');}
if(args.childNeeds){this.needsLayoutReasons_.push('child');}
if(args.posChildNeeds){this.needsLayoutReasons_.push('positionedChild');}
if(args.positionedMovement){this.needsLayoutReasons_.push('positionedMovement');}
@@ -4848,7 +4987,8 @@ if(this.modelDomainId_){throw new Error('Cannot add new clock sync markers after
const marker=new ClockSyncMarker(domainId,startTs,opt_endTs);if(!this.markersBySyncId_.has(syncId)){this.markersBySyncId_.set(syncId,[marker]);return;}
const markers=this.markersBySyncId_.get(syncId);if(markers.length===2){throw new Error('Clock sync with ID "'+syncId+'" is already '+'complete - cannot add a third clock sync marker to it.');}
if(markers[0].domainId===domainId){throw new Error('A clock domain cannot sync with itself.');}
-markers.push(marker);this.onSyncCompleted_(markers[0],marker);},get markersBySyncId(){return this.markersBySyncId_;},get domainsSeen(){return this.domainsSeen_;},getModelTimeTransformer(domainId){this.onDomainSeen_(domainId);if(!this.modelDomainId_){this.selectModelDomainId_();}
+markers.push(marker);this.onSyncCompleted_(markers[0],marker);},get completeSyncIds(){const completeSyncIds=[];for(const[syncId,markers]of this.markersBySyncId){if(markers.length===2)completeSyncIds.push(syncId);}
+return completeSyncIds;},get markersBySyncId(){return this.markersBySyncId_;},get domainsSeen(){return this.domainsSeen_;},getModelTimeTransformer(domainId){this.onDomainSeen_(domainId);if(!this.modelDomainId_){this.selectModelDomainId_();}
return this.getTimeTransformerRaw_(domainId,this.modelDomainId_).fn;},getTimeTransformerError(fromDomainId,toDomainId){this.onDomainSeen_(fromDomainId);this.onDomainSeen_(toDomainId);return this.getTimeTransformerRaw_(fromDomainId,toDomainId).error;},getTimeTransformerRaw_(fromDomainId,toDomainId){const transformer=this.getTransformerBetween_(fromDomainId,toDomainId);if(!transformer){throw new Error('No clock sync markers exist pairing clock domain "'+
fromDomainId+'" '+'with target clock domain "'+
toDomainId+'".');}
@@ -4944,8 +5084,9 @@ slice.duration=ts-slice.start;slice.didNotFinish=false;slice.colorId=opt_colorId
return slice;},pushCompleteSlice(category,title,ts,duration,tts,cpuDuration,opt_args,opt_argsStripped,opt_colorId,opt_bindId){const colorId=opt_colorId||ColorScheme.getColorIdForGeneralPurposeString(title);const sliceConstructorSubTypes=this.sliceConstructorSubTypes;const sliceType=sliceConstructorSubTypes.getConstructor(category,title);const slice=new sliceType(category,title,colorId,ts,opt_args?opt_args:{},duration,tts,cpuDuration,opt_argsStripped,opt_bindId);if(duration===undefined){slice.didNotFinish=true;}
this.pushSlice(slice);return slice;},autoCloseOpenSlices(){this.updateBounds();const maxTimestamp=this.bounds.max;for(let sI=0;sI<this.slices.length;sI++){const slice=this.slices[sI];if(slice.didNotFinish){slice.duration=maxTimestamp-slice.start;}}
this.openPartialSlices_=[];},shiftTimestampsForward(amount){for(let sI=0;sI<this.slices.length;sI++){const slice=this.slices[sI];slice.start=(slice.start+amount);}},updateBounds(){this.bounds.reset();for(let i=0;i<this.slices.length;i++){this.bounds.addValue(this.slices[i].start);this.bounds.addValue(this.slices[i].end);}},copySlice(slice){const sliceConstructorSubTypes=this.sliceConstructorSubTypes;const sliceType=sliceConstructorSubTypes.getConstructor(slice.category,slice.title);const newSlice=new sliceType(slice.category,slice.title,slice.colorId,slice.start,slice.args,slice.duration,slice.cpuStart,slice.cpuDuration);newSlice.didNotFinish=slice.didNotFinish;return newSlice;},*findTopmostSlicesInThisContainer(eventPredicate,opt_this){if(!this.haveTopLevelSlicesBeenBuilt){throw new Error('Nope');}
-for(const s of this.topLevelSlices){yield*s.findTopmostSlicesRelativeToThisSlice(eventPredicate);}},*childEvents(){yield*this.slices;},*childEventContainers(){},*getDescendantEventsInSortedRanges(ranges,opt_containerPredicate){if(opt_containerPredicate===undefined||opt_containerPredicate(this)){let rangeIndex=0;let range=ranges[rangeIndex];for(const event of this.childEvents()){while(event.start>range.max){rangeIndex++;if(rangeIndex>=ranges.length)return;range=ranges[rangeIndex];}
-if(event.end>=range.min)yield event;}}},getSlicesOfName(title){const slices=[];for(let i=0;i<this.slices.length;i++){if(this.slices[i].title===title){slices.push(this.slices[i]);}}
+for(const s of this.topLevelSlices){yield*s.findTopmostSlicesRelativeToThisSlice(eventPredicate);}},*childEvents(){yield*this.slices;},*childEventContainers(){},*getDescendantEventsInSortedRanges(ranges,opt_containerPredicate){if(ranges.length===0||(opt_containerPredicate!==undefined&&!opt_containerPredicate(this))){return;}
+let rangeIndex=0;let range=ranges[rangeIndex];for(const event of this.childEvents()){while(event.start>range.max){rangeIndex++;if(rangeIndex>=ranges.length)return;range=ranges[rangeIndex];}
+if(event.end>=range.min)yield event;}},getSlicesOfName(title){const slices=[];for(let i=0;i<this.slices.length;i++){if(this.slices[i].title===title){slices.push(this.slices[i]);}}
return slices;},iterSlicesInTimeRange(callback,start,end){const ret=[];tr.b.iterateOverIntersectingIntervals(this.topLevelSlices,function(s){return s.start;},function(s){return s.duration;},start,end,function(topLevelSlice){callback(topLevelSlice);for(const slice of topLevelSlice.enumerateAllDescendents()){callback(slice);}});return ret;},findFirstSlice(){if(!this.haveTopLevelSlicesBeenBuilt){throw new Error('Nope');}
if(0===this.slices.length)return undefined;return this.slices[0];},findSliceAtTs(ts){if(!this.haveTopLevelSlicesBeenBuilt)throw new Error('Nope');let i=tr.b.findIndexInSortedClosedIntervals(this.topLevelSlices,getSliceLo,getSliceHi,ts);if(i===-1||i===this.topLevelSlices.length){return undefined;}
let curSlice=this.topLevelSlices[i];while(true){i=tr.b.findIndexInSortedClosedIntervals(curSlice.subSlices,getSliceLo,getSliceHi,ts);if(i===-1||i===curSlice.subSlices.length){return curSlice;}
@@ -4989,7 +5130,8 @@ if(this.samples_&&this.samples_.length){this.bounds.addValue(this.samples_[0].st
for(let i=0;i<this.kernelSliceGroup.length;i++){categoriesDict[this.kernelSliceGroup.slices[i].category]=true;}
for(let i=0;i<this.asyncSliceGroup.length;i++){categoriesDict[this.asyncSliceGroup.slices[i].category]=true;}
if(this.samples_){for(let i=0;i<this.samples_.length;i++){categoriesDict[this.samples_[i].category]=true;}}},autoCloseOpenSlices(){this.sliceGroup.autoCloseOpenSlices();this.asyncSliceGroup.autoCloseOpenSlices();this.kernelSliceGroup.autoCloseOpenSlices();},mergeKernelWithUserland(){if(this.kernelSliceGroup.length>0){const newSlices=SliceGroup.merge(this.sliceGroup,this.kernelSliceGroup);this.sliceGroup.slices=newSlices.slices;this.kernelSliceGroup=new SliceGroup(this);this.updateBounds();}},createSubSlices(){this.sliceGroup.createSubSlices();this.samples_=this.parent.model.samples.filter(sample=>sample.thread===this);},get userFriendlyName(){return this.name||this.tid;},get userFriendlyDetails(){return'tid: '+this.tid+
-(this.name?', name: '+this.name:'');},getSettingsKey(){if(!this.name)return undefined;const parentKey=this.parent.getSettingsKey();if(!parentKey)return undefined;return parentKey+'.'+this.name;},getProcess(){return this.parent;},indexOfTimeSlice(timeSlice){const i=tr.b.findLowIndexInSortedArray(this.timeSlices,function(slice){return slice.start;},timeSlice.start);if(this.timeSlices[i]!==timeSlice)return undefined;return i;},getCpuTimeForRange(range){let totalCpuTime=0;tr.b.iterateOverIntersectingIntervals(this.sliceGroup.topLevelSlices,slice=>slice.start,slice=>slice.end,range.min,range.max,slice=>{if(slice.duration===0)return;if(!slice.cpuDuration)return;const intersection=range.findIntersection(slice.range);const fractionOfSliceInsideRangeOfInterest=intersection.duration/slice.duration;totalCpuTime+=slice.cpuDuration*fractionOfSliceInsideRangeOfInterest;});return totalCpuTime;},getSchedulingStatsForRange(start,end){const stats={};if(!this.timeSlices)return stats;function addStatsForSlice(threadTimeSlice){const overlapStart=Math.max(threadTimeSlice.start,start);const overlapEnd=Math.min(threadTimeSlice.end,end);const schedulingState=threadTimeSlice.schedulingState;if(!(schedulingState in stats))stats[schedulingState]=0;stats[schedulingState]+=overlapEnd-overlapStart;}
+(this.name?', name: '+this.name:'');},getSettingsKey(){if(!this.name)return undefined;const parentKey=this.parent.getSettingsKey();if(!parentKey)return undefined;return parentKey+'.'+this.name;},getProcess(){return this.parent;},indexOfTimeSlice(timeSlice){const i=tr.b.findLowIndexInSortedArray(this.timeSlices,function(slice){return slice.start;},timeSlice.start);if(this.timeSlices[i]!==timeSlice)return undefined;return i;},sumOverToplevelSlicesInRange(range,func){let sum=0;tr.b.iterateOverIntersectingIntervals(this.sliceGroup.topLevelSlices,slice=>slice.start,slice=>slice.end,range.min,range.max,slice=>{let fractionOfSliceInsideRangeOfInterest=1;if(slice.duration>0){const intersection=range.findIntersection(slice.range);fractionOfSliceInsideRangeOfInterest=intersection.duration/slice.duration;}
+sum+=func(slice)*fractionOfSliceInsideRangeOfInterest;});return sum;},getCpuTimeForRange(range){return this.sumOverToplevelSlicesInRange(range,slice=>slice.cpuDuration||0);},getNumToplevelSlicesForRange(range){return this.sumOverToplevelSlicesInRange(range,slice=>1);},getSchedulingStatsForRange(start,end){const stats={};if(!this.timeSlices)return stats;function addStatsForSlice(threadTimeSlice){const overlapStart=Math.max(threadTimeSlice.start,start);const overlapEnd=Math.min(threadTimeSlice.end,end);const schedulingState=threadTimeSlice.schedulingState;if(!(schedulingState in stats))stats[schedulingState]=0;stats[schedulingState]+=overlapEnd-overlapStart;}
tr.b.iterateOverIntersectingIntervals(this.timeSlices,function(x){return x.start;},function(x){return x.end;},start,end,addStatsForSlice);return stats;},get samples(){return this.samples_;},get type(){const re=/^[^0-9|\/]+/;const matches=re.exec(this.name);if(matches&&matches[0])return matches[0];throw new Error('Could not determine thread type for thread name '+
this.name);}};Thread.compare=function(x,y){let tmp=x.parent.compareTo(y.parent);if(tmp)return tmp;tmp=x.sortIndex-y.sortIndex;if(tmp)return tmp;if(x.name!==undefined){if(y.name!==undefined){tmp=x.name.localeCompare(y.name);}else{tmp=-1;}}else if(y.name!==undefined){tmp=1;}
if(tmp)return tmp;return x.tid-y.tid;};return{Thread,};});'use strict';tr.exportTo('tr.model',function(){const Thread=tr.model.Thread;const Counter=tr.model.Counter;function ProcessBase(model){if(!model){throw new Error('Must provide a model');}
@@ -5049,7 +5191,7 @@ const MemoryAllocatorDumpInfoType={PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN:0
const SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME;const EFFECTIVE_SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME;const MemoryAllocatorDumpInfoType=tr.model.MemoryAllocatorDumpInfoType;const PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN=MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN;const PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER=MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER;function getSize(dump){const numeric=dump.numerics[SIZE_NUMERIC_NAME];if(numeric===undefined)return 0;return numeric.value;}
function hasSize(dump){return dump.numerics[SIZE_NUMERIC_NAME]!==undefined;}
function optional(value,defaultValue){if(value===undefined)return defaultValue;return value;}
-GlobalMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Global memory dump at '+
+GlobalMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get stableId(){return'memory.'+this.model.globalMemoryDumps.indexOf(this);},get userFriendlyName(){return'Global memory dump at '+
tr.b.Unit.byName.timeStampInMs.format(this.start);},get containerName(){return'global space';},finalizeGraph(){this.removeWeakDumps();this.setUpTracingOverheadOwnership();this.aggregateNumerics();this.calculateSizes();this.calculateEffectiveSizes();this.discountTracingOverheadFromVmRegions();this.forceRebuildingMemoryAllocatorDumpByFullNameIndices();},removeWeakDumps(){this.traverseAllocatorDumpsInDepthFirstPreOrder(function(dump){if(dump.weak)return;if((dump.owns!==undefined&&dump.owns.target.weak)||(dump.parent!==undefined&&dump.parent.weak)){dump.weak=true;}});function removeWeakDumpsFromListRecursively(dumps){tr.b.inPlaceFilter(dumps,function(dump){if(dump.weak){return false;}
removeWeakDumpsFromListRecursively(dump.children);tr.b.inPlaceFilter(dump.ownedBy,function(ownershipLink){return!ownershipLink.source.weak;});return true;});}
this.iterateContainerDumps(function(containerDump){const memoryAllocatorDumps=containerDump.memoryAllocatorDumps;if(memoryAllocatorDumps!==undefined){removeWeakDumpsFromListRecursively(memoryAllocatorDumps);}});},calculateSizes(){this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateMemoryAllocatorDumpSize_.bind(this));},calculateMemoryAllocatorDumpSize_(dump){let shouldDefineSize=false;function getDependencySize(dependencyDump){const numeric=dependencyDump.numerics[SIZE_NUMERIC_NAME];if(numeric===undefined)return 0;shouldDefineSize=true;return numeric.value;}
@@ -5085,12 +5227,13 @@ openDumps.add(dump);dump.ownedBy.forEach(function(ownershipLink){visit.call(this
this.iterateAllRootAllocatorDumps(visit);},traverseAllocatorDumpsInDepthFirstPreOrder(fn){const visitedDumps=new WeakSet();function visit(dump){if(visitedDumps.has(dump))return;if(dump.owns!==undefined&&!visitedDumps.has(dump.owns.target)){return;}
if(dump.parent!==undefined&&!visitedDumps.has(dump.parent)){return;}
fn.call(this,dump);visitedDumps.add(dump);dump.ownedBy.forEach(function(ownershipLink){visit.call(this,ownershipLink.source);},this);dump.children.forEach(visit,this);}
-this.iterateAllRootAllocatorDumps(visit);}};tr.model.EventRegistry.register(GlobalMemoryDump,{name:'globalMemoryDump',pluralName:'globalMemoryDumps'});return{GlobalMemoryDump,};});'use strict';tr.exportTo('tr.model',function(){const InstantEventType={GLOBAL:1,PROCESS:2};function InstantEvent(category,title,colorId,start,args){tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.args=args;this.type=undefined;}
-InstantEvent.prototype={__proto__:tr.model.TimedEvent.prototype};function GlobalInstantEvent(category,title,colorId,start,args){InstantEvent.apply(this,arguments);this.type=InstantEventType.GLOBAL;}
+this.iterateAllRootAllocatorDumps(visit);}};tr.model.EventRegistry.register(GlobalMemoryDump,{name:'globalMemoryDump',pluralName:'globalMemoryDumps'});return{GlobalMemoryDump,};});'use strict';tr.exportTo('tr.model',function(){const InstantEventType={GLOBAL:1,PROCESS:2};function InstantEvent(category,title,colorId,start,args,parent){tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.args=args;this.parent_=parent;this.type=undefined;}
+InstantEvent.prototype={__proto__:tr.model.TimedEvent.prototype,};function GlobalInstantEvent(category,title,colorId,start,args,parent){InstantEvent.apply(this,arguments);this.type=InstantEventType.GLOBAL;}
GlobalInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Global instant event '+this.title+' @ '+
-tr.b.Unit.byName.timeStampInMs.format(start);}};function ProcessInstantEvent(category,title,colorId,start,args){InstantEvent.apply(this,arguments);this.type=InstantEventType.PROCESS;}
+tr.b.Unit.byName.timeStampInMs.format(start);},get stableId(){return'instant.'+this.parent_.instantEvents.indexOf(this);},};function ProcessInstantEvent(category,title,colorId,start,args,parent){InstantEvent.apply(this,arguments);this.type=InstantEventType.PROCESS;}
ProcessInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Process-level instant event '+this.title+' @ '+
-tr.b.Unit.byName.timeStampInMs.format(start);}};tr.model.EventRegistry.register(InstantEvent,{name:'instantEvent',pluralName:'instantEvents'});return{GlobalInstantEvent,ProcessInstantEvent,InstantEventType,InstantEvent,};});'use strict';tr.exportTo('tr.model',function(){const Cpu=tr.model.Cpu;const ProcessBase=tr.model.ProcessBase;function Kernel(model){ProcessBase.call(this,model);this.cpus={};this.softwareMeasuredCpuCount_=undefined;}
+tr.b.Unit.byName.timeStampInMs.format(start);},get stableId(){return this.parent_.stableId+'.instant.'+
+this.parent_.instantEvents.indexOf(this);},};tr.model.EventRegistry.register(InstantEvent,{name:'instantEvent',pluralName:'instantEvents'});return{GlobalInstantEvent,ProcessInstantEvent,InstantEventType,InstantEvent,};});'use strict';tr.exportTo('tr.model',function(){const Cpu=tr.model.Cpu;const ProcessBase=tr.model.ProcessBase;function Kernel(model){ProcessBase.call(this,model);this.cpus={};this.softwareMeasuredCpuCount_=undefined;}
Kernel.compare=function(x,y){return 0;};Kernel.prototype={__proto__:ProcessBase.prototype,compareTo(that){return Kernel.compare(this,that);},get userFriendlyName(){return'Kernel';},get userFriendlyDetails(){return'Kernel';},get stableId(){return'Kernel';},getOrCreateCpu(cpuNumber){if(!this.cpus[cpuNumber]){this.cpus[cpuNumber]=new Cpu(this,cpuNumber);}
return this.cpus[cpuNumber];},get softwareMeasuredCpuCount(){return this.softwareMeasuredCpuCount_;},set softwareMeasuredCpuCount(softwareMeasuredCpuCount){if(this.softwareMeasuredCpuCount_!==undefined&&this.softwareMeasuredCpuCount_!==softwareMeasuredCpuCount){throw new Error('Cannot change the softwareMeasuredCpuCount once it is set');}
this.softwareMeasuredCpuCount_=softwareMeasuredCpuCount;},get bestGuessAtCpuCount(){const realCpuCount=Object.keys(this.cpus).length;if(realCpuCount!==0){return realCpuCount;}
@@ -5138,7 +5281,8 @@ region.byteStats.sharedCleanResident;}
if(region.byteStats.proportionalResident!==undefined){thisByteStats.nativeLibraryProportionalResident=(thisByteStats.nativeLibraryProportionalResident||0)+
region.byteStats.proportionalResident;}}}};return{VMRegion,VMRegionClassificationNode,};});'use strict';tr.exportTo('tr.model',function(){const DISCOUNTED_ALLOCATOR_NAMES=['winheap','malloc'];const TRACING_OVERHEAD_PATH=['allocated_objects','tracing_overhead'];const SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME;const RESIDENT_SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.RESIDENT_SIZE_NUMERIC_NAME;function getSizeNumericValue(dump,sizeNumericName){const sizeNumeric=dump.numerics[sizeNumericName];if(sizeNumeric===undefined)return 0;return sizeNumeric.value;}
function ProcessMemoryDump(globalMemoryDump,process,start){tr.model.ContainerMemoryDump.call(this,start);this.process=process;this.globalMemoryDump=globalMemoryDump;this.totals=undefined;this.vmRegions=undefined;this.heapDumps=undefined;this.tracingOverheadOwnershipSetUp_=false;this.tracingOverheadDiscountedFromVmRegions_=false;}
-ProcessMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Process memory dump at '+
+ProcessMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get stableId(){return this.process.stableId+'.memory.'+
+this.process.memoryDumps.indexOf(this);},get userFriendlyName(){return'Process memory dump at '+
tr.b.Unit.byName.timeStampInMs.format(this.start);},get containerName(){return this.process.userFriendlyName;},get processMemoryDumps(){const dumps={};dumps[this.process.pid]=this;return dumps;},get hasOwnVmRegions(){return this.vmRegions!==undefined;},setUpTracingOverheadOwnership(opt_model){if(this.tracingOverheadOwnershipSetUp_)return;this.tracingOverheadOwnershipSetUp_=true;const tracingDump=this.getMemoryAllocatorDumpByFullName('tracing');if(tracingDump===undefined||tracingDump.owns!==undefined){return;}
if(tracingDump.owns!==undefined)return;const hasDiscountedFromAllocatorDumps=DISCOUNTED_ALLOCATOR_NAMES.some(function(allocatorName){const allocatorDump=this.getMemoryAllocatorDumpByFullName(allocatorName);if(allocatorDump===undefined){return false;}
let nextPathIndex=0;let currentDump=allocatorDump;let currentFullName=allocatorName;for(;nextPathIndex<TRACING_OVERHEAD_PATH.length;nextPathIndex++){const childFullName=currentFullName+'/'+
@@ -5234,7 +5378,7 @@ const sid=this.decodeBytes(4*subAuthorityCount);return{pSid,attributes,sid};},de
EtwImporter.canImport=function(events){if(!events.hasOwnProperty('name')||!events.hasOwnProperty('content')||events.name!=='ETW'){return false;}
return true;};EtwImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'EtwImporter';},get model(){return this.model_;},createThreadIfNeeded(pid,tid){this.tidsToPid_[tid]=pid;},removeThreadIfPresent(tid){this.tidsToPid_[tid]=undefined;},getPidFromWindowsTid(tid){if(tid===0)return 0;const pid=this.tidsToPid_[tid];if(pid===undefined){return 0;}
return pid;},getThreadFromWindowsTid(tid){const pid=this.getPidFromWindowsTid(tid);const process=this.model_.getProcess(pid);if(!process)return undefined;return process.getThread(tid);},getOrCreateCpu(cpuNumber){const cpu=this.model_.kernel.getOrCreateCpu(cpuNumber);return cpu;},importEvents(){this.events_.content.forEach(this.parseInfo.bind(this));if(this.walltime_===undefined||this.ticks_===undefined){throw Error('Cannot find clock sync information in the system trace.');}
-if(this.is64bit_===undefined){throw Error('Cannot determine pointer size of the system trace.');}
+if(this.is64bit_===undefined){throw Error('Cannot determine pointer size of the system trace.'+'Consider deselecting "System tracing" or disabling the "Paging '+'Executive" feature of Windows');}
this.events_.content.forEach(this.parseEvent.bind(this));},importTimestamp(timestamp){const ts=parseInt(timestamp,16);return(ts-this.walltime_+this.ticks_)/1000.;},parseInfo(event){if(event.hasOwnProperty('guid')&&event.hasOwnProperty('walltime')&&event.hasOwnProperty('tick')&&event.guid==='ClockSync'){this.walltime_=parseInt(event.walltime,16);this.ticks_=parseInt(event.tick,16);}
if(this.is64bit_===undefined&&event.hasOwnProperty('guid')&&event.hasOwnProperty('op')&&event.hasOwnProperty('ver')&&event.hasOwnProperty('payload')&&event.guid===kThreadGuid&&event.op===kThreadDCStartOpcode){const decodedSize=tr.b.Base64.getDecodedBufferLength(event.payload);if(event.ver===1){if(decodedSize>=52){this.is64bit_=true;}else{this.is64bit_=false;}}else if(event.ver===2){if(decodedSize>=64){this.is64bit_=true;}else{this.is64bit_=false;}}else if(event.ver===3){if(decodedSize>=60){this.is64bit_=true;}else{this.is64bit_=false;}}}
return true;},parseEvent(event){if(!event.hasOwnProperty('guid')||!event.hasOwnProperty('op')||!event.hasOwnProperty('ver')||!event.hasOwnProperty('cpu')||!event.hasOwnProperty('ts')||!event.hasOwnProperty('payload')){return false;}
@@ -5644,7 +5788,9 @@ TraceCodeMap.prototype={addEntry(addressHex,size,name,scriptId){const entry=new
return bank;}};function TraceCodeBank(){this.entries_=[];}
TraceCodeBank.prototype={removeEntry(address){if(this.entries_.length===0)return undefined;const index=tr.b.findLowIndexInSortedArray(this.entries_,function(entry){return entry.address;},address);const entry=this.entries_[index];if(!entry||entry.address!==address)return undefined;this.entries_.splice(index,1);return entry;},lookupEntry(address){const index=tr.b.findFirstTrueIndexInSortedArray(this.entries_,e=>(address<e.address))-1;const entry=this.entries_[index];return entry&&address<entry.address+entry.size?entry:undefined;},addEntry(newEntry){if(this.entries_.length===0){this.entries_.push(newEntry);}
const endAddress=newEntry.address+newEntry.size;const lastIndex=tr.b.findLowIndexInSortedArray(this.entries_,function(entry){return entry.address;},endAddress);let index;for(index=lastIndex-1;index>=0;--index){const entry=this.entries_[index];const entryEndAddress=entry.address+entry.size;if(entryEndAddress<=newEntry.address)break;}
-++index;this.entries_.splice(index,lastIndex-index,newEntry);}};return{TraceCodeMap,};});'use strict';tr.exportTo('tr.importer',function(){function ContextProcessor(model){this.model_=model;this.activeContexts_=[];this.stackPerType_={};this.contextCache_={};this.contextSetCache_={};this.cachedEntryForActiveContexts_=undefined;this.seenSnapshots_={};}
+++index;this.entries_.splice(index,lastIndex-index,newEntry);}};return{TraceCodeMap,};});'use strict';tr.exportTo('tr.e.measure',function(){const AsyncSlice=tr.model.AsyncSlice;const MEASURE_NAME_REGEX=/([^\/:]+):(.*?)(?:\/([A-Za-z0-9+/]+=?=?))?$/;function MeasureAsyncSlice(){this.groupTitle_='Ungrouped Measure';const matched=MEASURE_NAME_REGEX.exec(arguments[1]);if(matched!==null){arguments[1]=matched[2];this.groupTitle_=matched[1];}
+AsyncSlice.apply(this,arguments);}
+MeasureAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get viewSubGroupTitle(){return this.groupTitle_;},get title(){return this.title_;},set title(title){this.title_=title;}};AsyncSlice.subTypes.register(MeasureAsyncSlice,{categoryParts:['blink.user_timing']});return{MEASURE_NAME_REGEX,MeasureAsyncSlice,};});'use strict';tr.exportTo('tr.importer',function(){function ContextProcessor(model){this.model_=model;this.activeContexts_=[];this.stackPerType_={};this.contextCache_={};this.contextSetCache_={};this.cachedEntryForActiveContexts_=undefined;this.seenSnapshots_={};}
ContextProcessor.prototype={enterContext(contextType,scopedId){const newActiveContexts=[this.getOrCreateContext_(contextType,scopedId),];for(const oldContext of this.activeContexts_){if(oldContext.type===contextType){this.pushContext_(oldContext);}else{newActiveContexts.push(oldContext);}}
this.activeContexts_=newActiveContexts;this.cachedEntryForActiveContexts_=undefined;},leaveContext(contextType,scopedId){this.leaveContextImpl_(context=>context.type===contextType&&context.snapshot.scope===scopedId.scope&&context.snapshot.idRef===scopedId.id);},destroyContext(scopedId){for(const stack of Object.values(this.stackPerType_)){let newLength=0;for(let i=0;i<stack.length;++i){if(stack[i].snapshot.scope!==scopedId.scope||stack[i].snapshot.idRef!==scopedId.id){stack[newLength++]=stack[i];}}
stack.length=newLength;}
@@ -5686,7 +5832,7 @@ this.scope=scope;this.id=id;this.pid=pid;}
ScopedId.prototype={toString(){const pidStr=this.pid===undefined?'':'pid: '+this.pid+', ';return'{'+pidStr+'scope: '+this.scope+', id: '+this.id+'}';},toStringWithDelimiter(delim){return(this.pid===undefined?'':this.pid)+delim+
this.scope+delim+this.id;}};return{ScopedId,};});'use strict';tr.exportTo('tr.ui.annotations',function(){function XMarkerAnnotationView(viewport,annotation){this.viewport_=viewport;this.annotation_=annotation;}
XMarkerAnnotationView.prototype={__proto__:tr.ui.annotations.AnnotationView.prototype,draw(ctx){const dt=this.viewport_.currentDisplayTransform;const viewX=dt.xWorldToView(this.annotation_.timestamp);ctx.beginPath();tr.ui.b.drawLine(ctx,viewX,0,viewX,ctx.canvas.height);ctx.strokeStyle=this.annotation_.strokeStyle;ctx.stroke();}};return{XMarkerAnnotationView,};});'use strict';tr.exportTo('tr.model',function(){function XMarkerAnnotation(timestamp){tr.model.Annotation.apply(this,arguments);this.timestamp=timestamp;this.strokeStyle='rgba(0, 0, 255, 0.5)';}
-XMarkerAnnotation.fromDict=function(dict){return new XMarkerAnnotation(dict.args.timestamp);};XMarkerAnnotation.prototype={__proto__:tr.model.Annotation.prototype,toDict(){return{typeName:'xmarker',args:{timestamp:this.timestamp}};},createView_(viewport){return new tr.ui.annotations.XMarkerAnnotationView(viewport,this);}};tr.model.Annotation.register(XMarkerAnnotation,{typeName:'xmarker'});return{XMarkerAnnotation,};});'use strict';tr.exportTo('tr.e.importer',function(){const Base64=tr.b.Base64;const deepCopy=tr.b.deepCopy;const ColorScheme=tr.b.ColorScheme;const HeapDumpTraceEventImporter=tr.e.importer.HeapDumpTraceEventImporter;const LegacyHeapDumpTraceEventImporter=tr.e.importer.LegacyHeapDumpTraceEventImporter;const StreamingEventExpander=tr.e.importer.StreamingEventExpander;const ProfilingDictionaryReader=tr.e.importer.ProfilingDictionaryReader;function getEventColor(event,opt_customName){if(event.cname){return ColorScheme.getColorIdForReservedName(event.cname);}else if(opt_customName||event.name){return ColorScheme.getColorIdForGeneralPurposeString(opt_customName||event.name);}}
+XMarkerAnnotation.fromDict=function(dict){return new XMarkerAnnotation(dict.args.timestamp);};XMarkerAnnotation.prototype={__proto__:tr.model.Annotation.prototype,toDict(){return{typeName:'xmarker',args:{timestamp:this.timestamp}};},createView_(viewport){return new tr.ui.annotations.XMarkerAnnotationView(viewport,this);}};tr.model.Annotation.register(XMarkerAnnotation,{typeName:'xmarker'});return{XMarkerAnnotation,};});'use strict';tr.exportTo('tr.e.importer',function(){const Base64=tr.b.Base64;const deepCopy=tr.b.deepCopy;const ColorScheme=tr.b.ColorScheme;const HeapDumpTraceEventImporter=tr.e.importer.HeapDumpTraceEventImporter;const LegacyHeapDumpTraceEventImporter=tr.e.importer.LegacyHeapDumpTraceEventImporter;const StreamingEventExpander=tr.e.importer.StreamingEventExpander;const ProfilingDictionaryReader=tr.e.importer.ProfilingDictionaryReader;const MEASURE_NAME_REGEX=tr.e.measure.MEASURE_NAME_REGEX;function getEventColor(event,opt_customName){if(event.cname){return ColorScheme.getColorIdForReservedName(event.cname);}else if(opt_customName||event.name){return ColorScheme.getColorIdForGeneralPurposeString(opt_customName||event.name);}}
function isLegacyChromeClockSyncEvent(event){return event.name!==undefined&&event.name.startsWith(LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX)&&((event.ph==='S')||(event.ph==='F'));}
const PRODUCER='producer';const CONSUMER='consumer';const STEP='step';const BACKGROUND=tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;const LIGHT=tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;const DETAILED=tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;const MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER=[undefined,BACKGROUND,LIGHT,DETAILED];const GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX='global/';const LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX='ClockSyncEvent.';const BYTE_STAT_NAME_MAP={'pc':'privateCleanResident','pd':'privateDirtyResident','sc':'sharedCleanResident','sd':'sharedDirtyResident','pss':'proportionalResident','sw':'swapped'};const WEAK_MEMORY_ALLOCATOR_DUMP_FLAG=1<<0;const OBJECT_TYPE_NAME_PATTERNS=[{prefix:'const char *WTF::getStringWithTypeName() [T = ',suffix:']'},{prefix:'const char* WTF::getStringWithTypeName() [with T = ',suffix:']'},{prefix:'const char *__cdecl WTF::getStringWithTypeName<',suffix:'>(void)'}];const SUBTRACE_FIELDS=new Set(['powerTraceAsString','systemTraceEvents','androidProcessDump',]);const NON_METADATA_FIELDS=new Set(['displayTimeUnit','samples','stackFrames','traceAnnotations','traceEvents',...SUBTRACE_FIELDS]);function TraceEventImporter(model,eventData){this.hasEvents_=undefined;this.importPriority=1;this.model_=model;this.events_=undefined;this.sampleEvents_=undefined;this.stackFrameEvents_=undefined;this.stackFrameTree_=new tr.model.ProfileTree();this.subtraces_=[];this.eventsWereFromString_=false;this.softwareMeasuredCpuCount_=undefined;this.allAsyncEvents_=[];this.allFlowEvents_=[];this.allObjectEvents_=[];this.contextProcessorPerThread={};this.traceEventSampleStackFramesByName_={};this.v8ProcessCodeMaps_={};this.v8ProcessRootStackFrame_={};this.v8SamplingData_=[];this.profileTrees_=new Map();this.profileInfo_=new Map();this.legacyChromeClockSyncStartEvent_=undefined;this.legacyChromeClockSyncFinishEvent_=undefined;this.allMemoryDumpEvents_={};this.heapProfileExpander=new ProfilingDictionaryReader();this.objectTypeNameMap_={};this.clockDomainId_=tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;this.toModelTime_=undefined;if(typeof(eventData)==='string'||eventData instanceof String){eventData=eventData.trim();if(eventData[0]==='['){eventData=eventData.replace(/\s*,\s*$/,'');if(eventData[eventData.length-1]!==']'){eventData=eventData+']';}}
this.events_=JSON.parse(eventData);this.eventsWereFromString_=true;}else{this.events_=eventData;}
@@ -5721,9 +5867,8 @@ if(event.argsStripped)return;if(event.name==='process_name'){const process=this.
this.softwareMeasuredCpuCount_=n;}else if(event.name==='stackFrames'){const stackFrames=event.args.stackFrames;if(stackFrames===undefined){this.model_.importWarning({type:'metadata_parse_error',message:'No stack frames found in a \''+event.name+'\' metadata event'});}else{this.importStackFrames_(stackFrames,'p'+event.pid+':');}}else if(event.name==='typeNames'){const objectTypeNameMap=event.args.typeNames;if(objectTypeNameMap===undefined){this.model_.importWarning({type:'metadata_parse_error',message:'No mapping from object type IDs to names found in a \''+
event.name+'\' metadata event'});}else{this.importObjectTypeNameMap_(objectTypeNameMap,event.pid);}}else if(event.name==='TraceConfig'){this.model_.metadata.push({name:'TraceConfig',value:event.args.value});}else{this.model_.importWarning({type:'metadata_parse_error',message:'Unrecognized metadata name: '+event.name});}},processInstantEvent(event){if(event.name==='JitCodeAdded'||event.name==='JitCodeMoved'){this.v8SamplingData_.push(event);return;}
if(event.s==='t'||event.s===undefined){this.processDurationEvent(event);return;}
-let constructor;switch(event.s){case'g':constructor=tr.model.GlobalInstantEvent;break;case'p':constructor=tr.model.ProcessInstantEvent;break;default:this.model_.importWarning({type:'instant_parse_error',message:'I phase event with unknown "s" field value.'});return;}
-const instantEvent=new constructor(event.cat,event.name,getEventColor(event),this.toModelTimeFromUs_(event.ts),this.deepCopyIfNeeded_(event.args));switch(instantEvent.type){case tr.model.InstantEventType.GLOBAL:this.model_.instantEvents.push(instantEvent);break;case tr.model.InstantEventType.PROCESS:{const process=this.model_.getOrCreateProcess(event.pid);process.instantEvents.push(instantEvent);break;}
-default:throw new Error('Unknown instant event type: '+event.s);}},getOrCreateProfileTree_(sampleType,id){if(!this.profileTrees_.has(sampleType)){this.profileTrees_.set(sampleType,new Map());}
+let constructor;let parent;switch(event.s){case'g':constructor=tr.model.GlobalInstantEvent;parent=this.model_;break;case'p':constructor=tr.model.ProcessInstantEvent;parent=this.model_.getOrCreateProcess(event.pid);break;default:this.model_.importWarning({type:'instant_parse_error',message:'I phase event with unknown "s" field value.'});return;}
+const instantEvent=new constructor(event.cat,event.name,getEventColor(event),this.toModelTimeFromUs_(event.ts),this.deepCopyIfNeeded_(event.args),parent);parent.instantEvents.push(instantEvent);},getOrCreateProfileTree_(sampleType,id){if(!this.profileTrees_.has(sampleType)){this.profileTrees_.set(sampleType,new Map());}
const profileTreeMap=this.profileTrees_.get(sampleType);if(profileTreeMap.has(id)){return profileTreeMap.get(id);}
const profileTree=new tr.model.ProfileTree();profileTreeMap.set(id,profileTree);const info=this.profileInfo_.get(id);if(info!==undefined){profileTree.startTime=info.startTime;profileTree.pid=info.pid;profileTree.tid=info.tid;}
return profileTree;},processSample(event){if(event.args===undefined||event.args.data===undefined){return;}
@@ -5789,7 +5934,8 @@ const leafNode=this.stackFrameTree_.getNode('g'+event.sf);const sample=new tr.mo
if(event.cat===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:'Nestable async events (ph: b, e, or n) require a '+'cat parameter.'});continue;}
if(event.name===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:'Nestable async events (ph: b, e, or n) require a '+'name parameter.'});continue;}
const id=TraceEventImporter.scopedIdForEvent_(event);if(id===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:'Nestable async events (ph: b, e, or n) require an '+'id parameter.'});continue;}
-if(event.cat==='blink.user_timing'){const matched=/([^\/:]+):([^\/]+)\/?(.*)/.exec(event.name);if(matched!==null){const key=matched[1]+':'+event.cat;event.args=JSON.parse(Base64.atob(matched[3])||'{}');if(nestableMeasureAsyncEventsByKey[key]===undefined){nestableMeasureAsyncEventsByKey[key]=[];}
+if(event.cat==='blink.user_timing'){const matched=MEASURE_NAME_REGEX.exec(event.name);if(matched!==null){const key=matched[1]+':'+event.cat;try{event.args=JSON.parse(Base64.atob(matched[3])||'{}');}catch(e){}
+if(nestableMeasureAsyncEventsByKey[key]===undefined){nestableMeasureAsyncEventsByKey[key]=[];}
nestableMeasureAsyncEventsByKey[key].push(asyncEventState);continue;}}
const key=event.cat+':'+id.toStringWithDelimiter(':');if(nestableAsyncEventsByKey[key]===undefined){nestableAsyncEventsByKey[key]=[];}
nestableAsyncEventsByKey[key].push(asyncEventState);}
@@ -5850,13 +5996,13 @@ flowStatus[event.bind_id]=true;}else{if(!processFlowConsumer(flowIdToEvent,slice
flowStatus[event.bind_id]=false;if(event.flowPhase===STEP){if(!processFlowProducer(flowIdToEvent,flowStatus,event,slice)){continue;}
flowStatus[event.bind_id]=true;}}
continue;}
-let flowEvent;if(event.ph==='s'){if(flowIdToEvent[event.id]){this.model_.importWarning({type:'flow_slice_start_error',message:'event id '+event.id+' already seen when '+'encountering start of flow event.'});continue;}
+const fullFlowId=JSON.stringify({id:event.id,cat:event.cat,name:event.name});let flowEvent;if(event.ph==='s'){if(flowIdToEvent[fullFlowId]){this.model_.importWarning({type:'flow_slice_start_error',message:'event id '+event.id+' already seen when '+'encountering start of flow event.'});continue;}
flowEvent=createFlowEvent(thread,event);if(!flowEvent){this.model_.importWarning({type:'flow_slice_start_error',message:'event id '+event.id+' does not start '+'at an actual slice, so cannot be created.'});continue;}
-flowIdToEvent[event.id]=flowEvent;}else if(event.ph==='t'||event.ph==='f'){flowEvent=flowIdToEvent[event.id];if(flowEvent===undefined){this.model_.importWarning({type:'flow_slice_ordering_error',message:'Found flow phase '+event.ph+' for id: '+event.id+' but no flow start found.'});continue;}
+flowIdToEvent[fullFlowId]=flowEvent;}else if(event.ph==='t'||event.ph==='f'){flowEvent=flowIdToEvent[fullFlowId];if(flowEvent===undefined){this.model_.importWarning({type:'flow_slice_ordering_error',message:'Found flow phase '+event.ph+' for id: '+event.id+' but no flow start found.'});continue;}
let bindToParent=event.ph==='t';if(event.ph==='f'){if(event.bp===undefined){if(event.cat.indexOf('input')>-1){bindToParent=true;}else if(event.cat.indexOf('ipc.flow')>-1){bindToParent=true;}}else{if(event.bp!=='e'){this.model_.importWarning({type:'flow_slice_bind_point_error',message:'Flow event with invalid binding point (event.bp).'});continue;}
bindToParent=true;}}
const ok=finishFlowEventWith(flowEvent,thread,event,refGuid,bindToParent);if(ok){this.model_.flowEvents.push(flowEvent);}else{this.model_.importWarning({type:'flow_slice_end_error',message:'event id '+event.id+' does not end '+'at an actual slice, so cannot be created.'});}
-flowIdToEvent[event.id]=undefined;if(ok&&event.ph==='t'){flowEvent=createFlowEvent(thread,event);flowIdToEvent[event.id]=flowEvent;}}}},createExplicitObjects_(){if(this.allObjectEvents_.length===0)return;const processEvent=function(objectEventState){const event=objectEventState.event;const scopedId=TraceEventImporter.scopedIdForEvent_(event);const thread=objectEventState.thread;if(event.name===undefined){this.model_.importWarning({type:'object_parse_error',message:'While processing '+JSON.stringify(event)+': '+'Object events require an name parameter.'});}
+flowIdToEvent[fullFlowId]=undefined;if(ok&&event.ph==='t'){flowEvent=createFlowEvent(thread,event);flowIdToEvent[fullFlowId]=flowEvent;}}}},createExplicitObjects_(){if(this.allObjectEvents_.length===0)return;const processEvent=function(objectEventState){const event=objectEventState.event;const scopedId=TraceEventImporter.scopedIdForEvent_(event);const thread=objectEventState.thread;if(event.name===undefined){this.model_.importWarning({type:'object_parse_error',message:'While processing '+JSON.stringify(event)+': '+'Object events require an name parameter.'});}
if(scopedId===undefined||scopedId.id===undefined){this.model_.importWarning({type:'object_parse_error',message:'While processing '+JSON.stringify(event)+': '+'Object events require an id parameter.'});}
const process=thread.parent;const ts=this.toModelTimeFromUs_(event.ts);let instance;if(event.ph==='N'){try{instance=process.objects.idWasCreated(scopedId,event.cat,event.name,ts);}catch(e){this.model_.importWarning({type:'object_parse_error',message:'While processing create of '+
scopedId+' at ts='+ts+': '+e});return;}}else if(event.ph==='O'){if(event.args.snapshot===undefined){this.model_.importWarning({type:'object_parse_error',message:'While processing '+scopedId+' at ts='+ts+': '+'Snapshots must have args: {snapshot: ...}'});return;}
@@ -5947,9 +6093,7 @@ const importance=rawEdge.importance;const edge=new tr.model.MemoryAllocatorDumpL
sourceDump.owns.target.fullName+').'});}else{sourceDump.owns=edge;targetDump.ownedBy.push(edge);}
break;case'retention':sourceDump.retains.push(edge);targetDump.retainedBy.push(edge);break;default:this.model_.importWarning({type:'memory_dump_parse_error',message:'Invalid edge type: '+rawEdge.type+' (PID='+pid+', dump ID='+dumpId+', source='+sourceGuid+', target='+targetGuid+', importance='+importance+').'});}}}}},toModelTimeFromUs_(ts){if(!this.toModelTime_){this.toModelTime_=this.model_.clockSyncManager.getModelTimeTransformer(this.clockDomainId_);}
return this.toModelTime_(tr.b.Unit.timestampFromUs(ts));},maybeToModelTimeFromUs_(ts){if(ts===undefined){return undefined;}
-return this.toModelTimeFromUs_(ts);}};tr.importer.Importer.register(TraceEventImporter);return{TraceEventImporter,};});'use strict';tr.exportTo('tr.e.measure',function(){const AsyncSlice=tr.model.AsyncSlice;function MeasureAsyncSlice(){this.groupTitle_='Ungrouped Measure';const matched=/([^\/:]+):([^\/:]+)\/?(.*)/.exec(arguments[1]);if(matched!==null){arguments[1]=matched[2];this.groupTitle_=matched[1];}
-AsyncSlice.apply(this,arguments);}
-MeasureAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get viewSubGroupTitle(){return this.groupTitle_;},get title(){return this.title_;},set title(title){this.title_=title;}};AsyncSlice.subTypes.register(MeasureAsyncSlice,{categoryParts:['blink.user_timing']});return{MeasureAsyncSlice,};});'use strict';tr.exportTo('tr.e.net',function(){const AsyncSlice=tr.model.AsyncSlice;function NetAsyncSlice(){AsyncSlice.apply(this,arguments);this.url_=undefined;this.byteCount_=undefined;this.isTitleComputed_=false;this.isUrlComputed_=false;}
+return this.toModelTimeFromUs_(ts);}};tr.importer.Importer.register(TraceEventImporter);return{TraceEventImporter,};});'use strict';tr.exportTo('tr.e.net',function(){const AsyncSlice=tr.model.AsyncSlice;function NetAsyncSlice(){AsyncSlice.apply(this,arguments);this.url_=undefined;this.byteCount_=undefined;this.isTitleComputed_=false;this.isUrlComputed_=false;}
NetAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get viewSubGroupTitle(){return'NetLog';},get title(){if(this.isTitleComputed_||!this.isTopLevel){return this.title_;}
if(this.url!==undefined&&this.url.length>0){this.title_=this.url;}else if(this.args!==undefined&&this.args.source_type!==undefined){this.title_=this.args.source_type;}
this.isTitleComputed_=true;return this.title_;},set title(title){this.title_=title;},get url(){if(this.isUrlComputed_){return this.url_;}
@@ -6029,23 +6173,25 @@ if(event[4]==='F'){action+=' fua';}
if(event[5]==='A'){action+=' ahead';}
if(event[6]==='S'){action+=' sync';}
if(event[7]==='M'){action+=' meta';}
-const device=event[1];const sector=parseInt(event[8]);const numSectors=parseInt(event[9]);const key=device+'-'+sector+'-'+numSectors;this.openAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,action);return true;},blockRqCompleteEvent(eventName,cpuNumber,pid,ts,eventBase){const event=new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? '+'\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);if(!event)return false;const device=event[1];const sector=parseInt(event[8]);const numSectors=parseInt(event[9]);const error=parseInt(event[10]);const key=device+'-'+sector+'-'+numSectors;this.closeAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,{device,sector,numSectors,error});return true;}};Parser.register(DiskParser);return{DiskParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function DrmParser(importer){Parser.call(this,importer);importer.registerEventHandler('drm_vblank_event',DrmParser.prototype.vblankEvent.bind(this));}
-DrmParser.prototype={__proto__:Parser.prototype,drmVblankSlice(ts,eventName,args){const kthread=this.importer.getOrCreatePseudoThread('drm_vblank');kthread.openSlice=eventName;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},vblankEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/crtc=(\d+), seq=(\d+)/.exec(eventBase.details);if(!event)return false;const crtc=parseInt(event[1]);const seq=parseInt(event[2]);this.drmVblankSlice(ts,'vblank:'+crtc,{crtc,seq});return true;}};Parser.register(DrmParser);return{DrmParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function ExynosParser(importer){Parser.call(this,importer);importer.registerEventHandler('exynos_busfreq_target_int',ExynosParser.prototype.busfreqTargetIntEvent.bind(this));importer.registerEventHandler('exynos_busfreq_target_mif',ExynosParser.prototype.busfreqTargetMifEvent.bind(this));importer.registerEventHandler('exynos_page_flip_state',ExynosParser.prototype.pageFlipStateEvent.bind(this));}
-ExynosParser.prototype={__proto__:Parser.prototype,exynosBusfreqSample(name,ts,frequency){const targetCpu=this.importer.getOrCreateCpu(0);const counter=targetCpu.getOrCreateCounter('',name);if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries('frequency',ColorScheme.getColorIdForGeneralPurposeString(counter.name+'.'+'frequency')));}
-counter.series.forEach(function(series){series.addCounterSample(ts,frequency);});},busfreqTargetIntEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/frequency=(\d+)/.exec(eventBase.details);if(!event)return false;this.exynosBusfreqSample('INT Frequency',ts,parseInt(event[1]));return true;},busfreqTargetMifEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/frequency=(\d+)/.exec(eventBase.details);if(!event)return false;this.exynosBusfreqSample('MIF Frequency',ts,parseInt(event[1]));return true;},exynosPageFlipStateOpenSlice(ts,pipe,fb,state){const kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');kthread.openSliceTS=ts;kthread.openSlice=state;},exynosPageFlipStateCloseSlice(ts,pipe,fb,args){const kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');if(kthread.openSlice){const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
-kthread.openSlice=undefined;},pageFlipStateEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/pipe=(\d+), fb=(\d+), state=(.*)/.exec(eventBase.details);if(!event)return false;const pipe=parseInt(event[1]);const fb=parseInt(event[2]);const state=event[3];this.exynosPageFlipStateCloseSlice(ts,pipe,fb,{pipe,fb});if(state!=='flipped'){this.exynosPageFlipStateOpenSlice(ts,pipe,fb,state);}
-return true;}};Parser.register(ExynosParser);return{ExynosParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function FenceParser(importer){Parser.call(this,importer);this.model_=importer.model_;importer.registerEventHandler('fence_init',FenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('fence_destroy',FenceParser.prototype.fenceDestroyEvent.bind(this));importer.registerEventHandler('fence_enable_signal',FenceParser.prototype.fenceEnableSignalEvent.bind(this));importer.registerEventHandler('fence_signaled',FenceParser.prototype.fenceSignaledEvent.bind(this));this.model_=importer.model_;}
-const fenceRE=/driver=(\S+) timeline=(\S+) context=(\d+) seqno=(\d+)/;FenceParser.prototype={__proto__:Parser.prototype,initEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
+const device=event[1];const sector=parseInt(event[8]);const numSectors=parseInt(event[9]);const key=device+'-'+sector+'-'+numSectors;this.openAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,action);return true;},blockRqCompleteEvent(eventName,cpuNumber,pid,ts,eventBase){const event=new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? '+'\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);if(!event)return false;const device=event[1];const sector=parseInt(event[8]);const numSectors=parseInt(event[9]);const error=parseInt(event[10]);const key=device+'-'+sector+'-'+numSectors;this.closeAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,{device,sector,numSectors,error});return true;}};Parser.register(DiskParser);return{DiskParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function DmaFenceParser(importer){Parser.call(this,importer);this.model_=importer.model_;importer.registerEventHandler('dma_fence_init',DmaFenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('dma_fence_emit',DmaFenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('dma_fence_destroy',DmaFenceParser.prototype.fenceDestroyEvent.bind(this));importer.registerEventHandler('dma_fence_enable_signal',DmaFenceParser.prototype.fenceEnableSignalEvent.bind(this));importer.registerEventHandler('dma_fence_signaled',DmaFenceParser.prototype.fenceSignaledEvent.bind(this));importer.registerEventHandler('dma_fence_wait_start',DmaFenceParser.prototype.fenceWaitEvent.bind(this));importer.registerEventHandler('dma_fence_wait_end',DmaFenceParser.prototype.fenceWaitEvent.bind(this));importer.registerEventHandler('fence_init',DmaFenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('fence_emit',DmaFenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('fence_destroy',DmaFenceParser.prototype.fenceDestroyEvent.bind(this));importer.registerEventHandler('fence_enable_signal',DmaFenceParser.prototype.fenceEnableSignalEvent.bind(this));importer.registerEventHandler('fence_signaled',DmaFenceParser.prototype.fenceSignaledEvent.bind(this));importer.registerEventHandler('fence_wait_start',DmaFenceParser.prototype.fenceWaitEvent.bind(this));importer.registerEventHandler('fence_wait_end',DmaFenceParser.prototype.fenceWaitEvent.bind(this));this.model_=importer.model_;}
+const fenceRE=/driver=(\S+) timeline=(\S+) context=(\d+) seqno=(\d+)/;DmaFenceParser.prototype={__proto__:Parser.prototype,initEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
const thread=this.importer.getOrCreatePseudoThread(event[2]);thread.lastActiveTs=ts;return true;},fenceDestroyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
-const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_destroy('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{'driver':event[1],'context':event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
+const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_destroy('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{driver:event[1],context:event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
if(thread.thread.sliceGroup.openSliceCount>0){thread.thread.sliceGroup.endSlice(ts);}
thread.lastActiveTs=ts;},fenceEnableSignalEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
-const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_enable('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{'driver':event[1],'context':event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
+const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_enable('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{driver:event[1],context:event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
if(thread.thread.sliceGroup.openSliceCount>0){thread.thread.sliceGroup.endSlice(ts);}
thread.lastActiveTs=ts;},fenceSignaledEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
-const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_signal('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{'driver':event[1],'context':event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
+const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_signal('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{driver:event[1],context:event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
if(thread.thread.sliceGroup.openSliceCount>0){thread.thread.sliceGroup.endSlice(ts);}
-thread.lastActiveTs=ts;return true;},};Parser.register(FenceParser);return{FenceParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function GestureParser(importer){Parser.call(this,importer);importer.registerEventHandler('tracing_mark_write:log',GestureParser.prototype.logEvent.bind(this));importer.registerEventHandler('tracing_mark_write:SyncInterpret',GestureParser.prototype.syncEvent.bind(this));importer.registerEventHandler('tracing_mark_write:HandleTimer',GestureParser.prototype.timerEvent.bind(this));}
+thread.lastActiveTs=ts;return true;},fenceWaitEvent(eventName,cpuNumber,pid,ts,eventBase){if(eventBase.tgid===undefined)return false;const event=fenceRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;const slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
+const name='dma_fence_wait("'+event[2]+'")';if(eventName.endsWith('start')){const slice=slices.beginSlice(null,name,ts,{driver:event[1],context:event[3],seqno:event[4],});}else{if(slices.openSliceCount>0){slices.endSlice(ts);}}
+return true;},};Parser.register(DmaFenceParser);return{DmaFenceParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function DrmParser(importer){Parser.call(this,importer);importer.registerEventHandler('drm_vblank_event',DrmParser.prototype.vblankEvent.bind(this));}
+DrmParser.prototype={__proto__:Parser.prototype,drmVblankSlice(ts,eventName,args){const kthread=this.importer.getOrCreatePseudoThread('drm_vblank');kthread.openSlice=eventName;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},vblankEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/crtc=(\d+), seq=(\d+)/.exec(eventBase.details);if(!event)return false;const crtc=parseInt(event[1]);const seq=parseInt(event[2]);this.drmVblankSlice(ts,'vblank:'+crtc,{crtc,seq});return true;}};Parser.register(DrmParser);return{DrmParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function ExynosParser(importer){Parser.call(this,importer);importer.registerEventHandler('exynos_busfreq_target_int',ExynosParser.prototype.busfreqTargetIntEvent.bind(this));importer.registerEventHandler('exynos_busfreq_target_mif',ExynosParser.prototype.busfreqTargetMifEvent.bind(this));importer.registerEventHandler('exynos_page_flip_state',ExynosParser.prototype.pageFlipStateEvent.bind(this));}
+ExynosParser.prototype={__proto__:Parser.prototype,exynosBusfreqSample(name,ts,frequency){const targetCpu=this.importer.getOrCreateCpu(0);const counter=targetCpu.getOrCreateCounter('',name);if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries('frequency',ColorScheme.getColorIdForGeneralPurposeString(counter.name+'.'+'frequency')));}
+counter.series.forEach(function(series){series.addCounterSample(ts,frequency);});},busfreqTargetIntEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/frequency=(\d+)/.exec(eventBase.details);if(!event)return false;this.exynosBusfreqSample('INT Frequency',ts,parseInt(event[1]));return true;},busfreqTargetMifEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/frequency=(\d+)/.exec(eventBase.details);if(!event)return false;this.exynosBusfreqSample('MIF Frequency',ts,parseInt(event[1]));return true;},exynosPageFlipStateOpenSlice(ts,pipe,fb,state){const kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');kthread.openSliceTS=ts;kthread.openSlice=state;},exynosPageFlipStateCloseSlice(ts,pipe,fb,args){const kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');if(kthread.openSlice){const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+kthread.openSlice=undefined;},pageFlipStateEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/pipe=(\d+), fb=(\d+), state=(.*)/.exec(eventBase.details);if(!event)return false;const pipe=parseInt(event[1]);const fb=parseInt(event[2]);const state=event[3];this.exynosPageFlipStateCloseSlice(ts,pipe,fb,{pipe,fb});if(state!=='flipped'){this.exynosPageFlipStateOpenSlice(ts,pipe,fb,state);}
+return true;}};Parser.register(ExynosParser);return{ExynosParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function GestureParser(importer){Parser.call(this,importer);importer.registerEventHandler('tracing_mark_write:log',GestureParser.prototype.logEvent.bind(this));importer.registerEventHandler('tracing_mark_write:SyncInterpret',GestureParser.prototype.syncEvent.bind(this));importer.registerEventHandler('tracing_mark_write:HandleTimer',GestureParser.prototype.timerEvent.bind(this));}
GestureParser.prototype={__proto__:Parser.prototype,gestureOpenSlice(title,ts,opt_args){const thread=this.importer.getOrCreatePseudoThread('gesture').thread;thread.sliceGroup.beginSlice('touchpad_gesture',title,ts,opt_args);},gestureCloseSlice(title,ts){const thread=this.importer.getOrCreatePseudoThread('gesture').thread;if(thread.sliceGroup.openSliceCount){const slice=thread.sliceGroup.mostRecentlyOpenedPartialSlice;if(slice.title!==title){this.importer.model.importWarning({type:'title_match_error',message:'Titles do not match. Title is '+
slice.title+' in openSlice, and is '+
title+' in endSlice'});}else{thread.sliceGroup.endSlice(ts);}}},logEvent(eventName,cpuNumber,pid,ts,eventBase){const innerEvent=/^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);switch(innerEvent[1]){case'start':this.gestureOpenSlice('GestureLog',ts,{name:innerEvent[2]});break;case'end':this.gestureCloseSlice('GestureLog',ts);}
@@ -6057,7 +6203,10 @@ pushLastSliceIfNeeded(thread,event[1],ts);thread.lastEntryTitle=undefined;thread
Parser.register(I2cParser);return{I2cParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function I915Parser(importer){Parser.call(this,importer);importer.registerEventHandler('i915_gem_object_create',I915Parser.prototype.gemObjectCreateEvent.bind(this));importer.registerEventHandler('i915_gem_object_bind',I915Parser.prototype.gemObjectBindEvent.bind(this));importer.registerEventHandler('i915_gem_object_unbind',I915Parser.prototype.gemObjectBindEvent.bind(this));importer.registerEventHandler('i915_gem_object_change_domain',I915Parser.prototype.gemObjectChangeDomainEvent.bind(this));importer.registerEventHandler('i915_gem_object_pread',I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));importer.registerEventHandler('i915_gem_object_pwrite',I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));importer.registerEventHandler('i915_gem_object_fault',I915Parser.prototype.gemObjectFaultEvent.bind(this));importer.registerEventHandler('i915_gem_object_clflush',I915Parser.prototype.gemObjectDestroyEvent.bind(this));importer.registerEventHandler('i915_gem_object_destroy',I915Parser.prototype.gemObjectDestroyEvent.bind(this));importer.registerEventHandler('i915_gem_ring_dispatch',I915Parser.prototype.gemRingDispatchEvent.bind(this));importer.registerEventHandler('i915_gem_ring_flush',I915Parser.prototype.gemRingFlushEvent.bind(this));importer.registerEventHandler('i915_gem_request',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_add',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_complete',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_retire',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_wait_begin',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_wait_end',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_ring_wait_begin',I915Parser.prototype.gemRingWaitEvent.bind(this));importer.registerEventHandler('i915_gem_ring_wait_end',I915Parser.prototype.gemRingWaitEvent.bind(this));importer.registerEventHandler('i915_reg_rw',I915Parser.prototype.regRWEvent.bind(this));importer.registerEventHandler('i915_flip_request',I915Parser.prototype.flipEvent.bind(this));importer.registerEventHandler('i915_flip_complete',I915Parser.prototype.flipEvent.bind(this));importer.registerEventHandler('intel_gpu_freq_change',I915Parser.prototype.gpuFrequency.bind(this));}
I915Parser.prototype={__proto__:Parser.prototype,i915FlipOpenSlice(ts,obj,plane){const kthread=this.importer.getOrCreatePseudoThread('i915_flip');kthread.openSliceTS=ts;kthread.openSlice='flip:'+obj+'/'+plane;},i915FlipCloseSlice(ts,args){const kthread=this.importer.getOrCreatePseudoThread('i915_flip');if(kthread.openSlice){const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
kthread.openSlice=undefined;},i915GemObjectSlice(ts,eventName,obj,args){const kthread=this.importer.getOrCreatePseudoThread('i915_gem');kthread.openSlice=eventName+':'+obj;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915GemRingSlice(ts,eventName,dev,ring,args){const kthread=this.importer.getOrCreatePseudoThread('i915_gem_ring');kthread.openSlice=eventName+':'+dev+'.'+ring;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915RegSlice(ts,eventName,reg,args){const kthread=this.importer.getOrCreatePseudoThread('i915_reg');kthread.openSlice=eventName+':'+reg;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915FreqChangeSlice(ts,eventName,args){const kthread=this.importer.getOrCreatePseudoThread('i915_gpu_freq');kthread.openSlice=eventName;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},gemObjectCreateEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), size=(\d+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const size=parseInt(event[2]);this.i915GemObjectSlice(ts,eventName,obj,{obj,size});return true;},gemObjectBindEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), offset=(\w+), size=(\d+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const offset=event[2];const size=parseInt(event[3]);this.i915ObjectGemSlice(ts,eventName+':'+obj,{obj,offset,size});return true;},gemObjectChangeDomainEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), read=(\w+=>\w+), write=(\w+=>\w+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const read=event[2];const write=event[3];this.i915GemObjectSlice(ts,eventName,obj,{obj,read,write});return true;},gemObjectPreadWriteEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), offset=(\d+), len=(\d+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const offset=parseInt(event[2]);const len=parseInt(event[3]);this.i915GemObjectSlice(ts,eventName,obj,{obj,offset,len});return true;},gemObjectFaultEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), (\w+) index=(\d+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const type=event[2];const index=parseInt(event[3]);this.i915GemObjectSlice(ts,eventName,obj,{obj,type,index});return true;},gemObjectDestroyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];this.i915GemObjectSlice(ts,eventName,obj,{obj});return true;},gemRingDispatchEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase.details);if(!event)return false;const dev=parseInt(event[1]);const ring=parseInt(event[2]);const seqno=parseInt(event[3]);this.i915GemRingSlice(ts,eventName,dev,ring,{dev,ring,seqno});return true;},gemRingFlushEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev=(\d+), ring=(\w+), invalidate=(\w+), flush=(\w+)/.exec(eventBase.details);if(!event)return false;const dev=parseInt(event[1]);const ring=parseInt(event[2]);const invalidate=event[3];const flush=event[4];this.i915GemRingSlice(ts,eventName,dev,ring,{dev,ring,invalidate,flush});return true;},gemRequestEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase.details);if(!event)return false;const dev=parseInt(event[1]);const ring=parseInt(event[2]);const seqno=parseInt(event[3]);this.i915GemRingSlice(ts,eventName,dev,ring,{dev,ring,seqno});return true;},gemRingWaitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev=(\d+), ring=(\d+)/.exec(eventBase.details);if(!event)return false;const dev=parseInt(event[1]);const ring=parseInt(event[2]);this.i915GemRingSlice(ts,eventName,dev,ring,{dev,ring});return true;},regRWEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/(\w+) reg=(\w+), len=(\d+), val=(\(\w+, \w+\))/.exec(eventBase.details);if(!event)return false;const rw=event[1];const reg=event[2];const len=event[3];const data=event[3];this.i915RegSlice(ts,rw,reg,{rw,reg,len,data});return true;},flipEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/plane=(\d+), obj=(\w+)/.exec(eventBase.details);if(!event)return false;const plane=parseInt(event[1]);const obj=event[2];if(eventName==='i915_flip_request'){this.i915FlipOpenSlice(ts,obj,plane);}else{this.i915FlipCloseSlice(ts,{obj,plane});}
-return true;},gpuFrequency(eventName,cpuNumver,pid,ts,eventBase){const event=/new_freq=(\d+)/.exec(eventBase.details);if(!event)return false;const freq=parseInt(event[1]);this.i915FreqChangeSlice(ts,eventName,{freq});return true;}};Parser.register(I915Parser);return{I915Parser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function IrqParser(importer){Parser.call(this,importer);importer.registerEventHandler('irq_handler_entry',IrqParser.prototype.irqHandlerEntryEvent.bind(this));importer.registerEventHandler('irq_handler_exit',IrqParser.prototype.irqHandlerExitEvent.bind(this));importer.registerEventHandler('softirq_raise',IrqParser.prototype.softirqRaiseEvent.bind(this));importer.registerEventHandler('softirq_entry',IrqParser.prototype.softirqEntryEvent.bind(this));importer.registerEventHandler('softirq_exit',IrqParser.prototype.softirqExitEvent.bind(this));importer.registerEventHandler('ipi_entry',IrqParser.prototype.ipiEntryEvent.bind(this));importer.registerEventHandler('ipi_exit',IrqParser.prototype.ipiExitEvent.bind(this));importer.registerEventHandler('preempt_disable',IrqParser.prototype.preemptStartEvent.bind(this));importer.registerEventHandler('preempt_enable',IrqParser.prototype.preemptEndEvent.bind(this));importer.registerEventHandler('irq_disable',IrqParser.prototype.irqoffStartEvent.bind(this));importer.registerEventHandler('irq_enable',IrqParser.prototype.irqoffEndEvent.bind(this));}
+return true;},gpuFrequency(eventName,cpuNumver,pid,ts,eventBase){const event=/new_freq=(\d+)/.exec(eventBase.details);if(!event)return false;const freq=parseInt(event[1]);this.i915FreqChangeSlice(ts,eventName,{freq});return true;}};Parser.register(I915Parser);return{I915Parser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function IonHeapParser(importer){Parser.call(this,importer);importer.registerEventHandler('ion_heap_shrink',IonHeapParser.prototype.traceIonHeapShrink.bind(this));importer.registerEventHandler('ion_heap_grow',IonHeapParser.prototype.traceIonHeapGrow.bind(this));this.model_=importer.model_;}
+const TestExports={};const ionHeapRE=new RegExp('heap_name=(\\S+), len=(\\d+), total_allocated=(\\d+)');TestExports.ionHeapRE=ionHeapRE;IonHeapParser.prototype={__proto__:Parser.prototype,traceIonHeapShrink(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=ionHeapRE.exec(eventBase.details);if(!event)return false;const name=event[1];const len=parseInt(event[2]);const totalAllocated=parseInt(event[3]);const ionHeap=totalAllocated+len;const ctr=this.model_.kernel.getOrCreateCounter(null,name+' ion heap');if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,ionHeap);});return true;},traceIonHeapGrow(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=ionHeapRE.exec(eventBase.details);if(!event)return false;const name=event[1];const len=parseInt(event[2]);const totalAllocated=parseInt(event[3]);const ionHeap=totalAllocated+len;const ctr=this.model_.kernel.getOrCreateCounter(null,name+' ion heap');if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,ionHeap);});return true;}};Parser.register(IonHeapParser);return{IonHeapParser,_IonHeapParserTestExports:TestExports};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function IrqParser(importer){Parser.call(this,importer);importer.registerEventHandler('irq_handler_entry',IrqParser.prototype.irqHandlerEntryEvent.bind(this));importer.registerEventHandler('irq_handler_exit',IrqParser.prototype.irqHandlerExitEvent.bind(this));importer.registerEventHandler('softirq_raise',IrqParser.prototype.softirqRaiseEvent.bind(this));importer.registerEventHandler('softirq_entry',IrqParser.prototype.softirqEntryEvent.bind(this));importer.registerEventHandler('softirq_exit',IrqParser.prototype.softirqExitEvent.bind(this));importer.registerEventHandler('ipi_entry',IrqParser.prototype.ipiEntryEvent.bind(this));importer.registerEventHandler('ipi_exit',IrqParser.prototype.ipiExitEvent.bind(this));importer.registerEventHandler('preempt_disable',IrqParser.prototype.preemptStartEvent.bind(this));importer.registerEventHandler('preempt_enable',IrqParser.prototype.preemptEndEvent.bind(this));importer.registerEventHandler('irq_disable',IrqParser.prototype.irqoffStartEvent.bind(this));importer.registerEventHandler('irq_enable',IrqParser.prototype.irqoffEndEvent.bind(this));}
const irqHandlerEntryRE=/irq=(\d+) name=(.+)/;const irqHandlerExitRE=/irq=(\d+) ret=(.+)/;const softirqRE=/vec=(\d+) \[action=(.+)\]/;const ipiHandlerExitRE=/\((.+)\)/;const preemptirqRE=/caller=(.+) parent=(.+)/;IrqParser.prototype={__proto__:Parser.prototype,irqHandlerEntryEvent(eventName,cpuNumber,pid,ts,eventBase){const event=irqHandlerEntryRE.exec(eventBase.details);if(!event)return false;const irq=parseInt(event[1]);const name=event[2];const thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);thread.lastEntryTs=ts;thread.irqName=name;return true;},irqHandlerExitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=irqHandlerExitRE.exec(eventBase.details);if(!event)return false;const irq=parseInt(event[1]);const ret=event[2];const thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){const duration=ts-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('','IRQ ('+thread.irqName+')',ColorScheme.getColorIdForGeneralPurposeString(event[1]),thread.lastEntryTs,{ret},duration);thread.thread.sliceGroup.pushSlice(slice);}
thread.lastEntryTs=undefined;thread.irqName=undefined;return true;},softirqRaiseEvent(eventName,cpuNumber,pid,ts,eventBase){return true;},softirqEntryEvent(eventName,cpuNumber,pid,ts,eventBase){const event=softirqRE.exec(eventBase.details);if(!event)return false;const action=event[2];const thread=this.importer.getOrCreatePseudoThread('softirq cpu '+cpuNumber);thread.lastEntryTs=ts;return true;},softirqExitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=softirqRE.exec(eventBase.details);if(!event)return false;const vec=parseInt(event[1]);const action=event[2];const thread=this.importer.getOrCreatePseudoThread('softirq cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){const duration=ts-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('',action,ColorScheme.getColorIdForGeneralPurposeString(event[1]),thread.lastEntryTs,{vec},duration);thread.thread.sliceGroup.pushSlice(slice);}
thread.lastEntryTs=undefined;return true;},ipiEntryEvent(eventName,cpuNumber,pid,ts,eventBase){const thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);thread.lastEntryTs=ts;return true;},ipiExitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=ipiHandlerExitRE.exec(eventBase.details);if(!event)return false;const ipiName=event[1];const thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){const duration=ts-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('','IPI ('+ipiName+')',ColorScheme.getColorIdForGeneralPurposeString(ipiName),thread.lastEntryTs,{},duration);thread.thread.sliceGroup.pushSlice(slice);}
@@ -6115,7 +6264,11 @@ powerCounter.series.forEach(function(series){series.addCounterSample(ts,powerSta
powerCounter.series.forEach(function(series){if(series.name==='Min Frequency'){series.addCounterSample(ts,minFreq);}
if(series.name==='Max Frequency'){series.addCounterSample(ts,maxFreq);}});},powerStartEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/type=(\d+) state=(\d) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[3]);const cpuState=parseInt(event[2]);this.cpuStateSlice(ts,targetCpuNumber,event[1],cpuState);return true;},powerFrequencyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/type=(\d+) state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[3]);const powerState=parseInt(event[2]);this.cpuFrequencySlice(ts,targetCpuNumber,powerState);return true;},cpuFrequencyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[2]);const powerState=parseInt(event[1]);this.cpuFrequencySlice(ts,targetCpuNumber,powerState);return true;},cpuFrequencyLimitsEvent(eventName,cpu,pid,ts,eventBase){const event=/min=(\d+) max=(\d+) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[3]);const minFreq=parseInt(event[1]);const maxFreq=parseInt(event[2]);this.cpuFrequencyLimitsSlice(ts,targetCpuNumber,minFreq,maxFreq);return true;},cpuIdleEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[2]);const cpuState=parseInt(event[1]);this.cpuIdleSlice(ts,targetCpuNumber,cpuState);return true;}};Parser.register(PowerParser);return{PowerParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function RegulatorParser(importer){Parser.call(this,importer);importer.registerEventHandler('regulator_enable',RegulatorParser.prototype.regulatorEnableEvent.bind(this));importer.registerEventHandler('regulator_enable_delay',RegulatorParser.prototype.regulatorEnableDelayEvent.bind(this));importer.registerEventHandler('regulator_enable_complete',RegulatorParser.prototype.regulatorEnableCompleteEvent.bind(this));importer.registerEventHandler('regulator_disable',RegulatorParser.prototype.regulatorDisableEvent.bind(this));importer.registerEventHandler('regulator_disable_complete',RegulatorParser.prototype.regulatorDisableCompleteEvent.bind(this));importer.registerEventHandler('regulator_set_voltage',RegulatorParser.prototype.regulatorSetVoltageEvent.bind(this));importer.registerEventHandler('regulator_set_voltage_complete',RegulatorParser.prototype.regulatorSetVoltageCompleteEvent.bind(this));this.model_=importer.model_;}
const regulatorEnableRE=/name=(.+)/;const regulatorDisableRE=/name=(.+)/;const regulatorSetVoltageCompleteRE=/name=(\S+), val=(\d+)/;RegulatorParser.prototype={__proto__:Parser.prototype,getCtr_(ctrName,valueName){const ctr=this.model_.kernel.getOrCreateCounter(null,'vreg '+ctrName+' '+valueName);if(ctr.series[0]===undefined){ctr.addSeries(new tr.model.CounterSeries(valueName,ColorScheme.getColorIdForGeneralPurposeString(ctrName+'.'+valueName)));}
-return ctr;},regulatorEnableEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorEnableRE.exec(eventBase.details);if(!event)return false;const name=event[1];const ctr=this.getCtr_(name,'enabled');ctr.series[0].addCounterSample(ts,1);return true;},regulatorEnableDelayEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorEnableCompleteEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorDisableEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorDisableRE.exec(eventBase.details);if(!event)return false;const name=event[1];const ctr=this.getCtr_(name,'enabled');ctr.series[0].addCounterSample(ts,0);return true;},regulatorDisableCompleteEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorSetVoltageEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorSetVoltageCompleteEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorSetVoltageCompleteRE.exec(eventBase.details);if(!event)return false;const name=event[1];const voltage=parseInt(event[2]);const ctr=this.getCtr_(name,'voltage');ctr.series[0].addCounterSample(ts,voltage);return true;}};Parser.register(RegulatorParser);return{RegulatorParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function SchedParser(importer){Parser.call(this,importer);importer.registerEventHandler('sched_switch',SchedParser.prototype.schedSwitchEvent.bind(this));importer.registerEventHandler('sched_wakeup',SchedParser.prototype.schedWakeupEvent.bind(this));importer.registerEventHandler('sched_blocked_reason',SchedParser.prototype.schedBlockedEvent.bind(this));importer.registerEventHandler('sched_cpu_hotplug',SchedParser.prototype.schedCpuHotplugEvent.bind(this));}
+return ctr;},regulatorEnableEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorEnableRE.exec(eventBase.details);if(!event)return false;const name=event[1];const ctr=this.getCtr_(name,'enabled');ctr.series[0].addCounterSample(ts,1);return true;},regulatorEnableDelayEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorEnableCompleteEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorDisableEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorDisableRE.exec(eventBase.details);if(!event)return false;const name=event[1];const ctr=this.getCtr_(name,'enabled');ctr.series[0].addCounterSample(ts,0);return true;},regulatorDisableCompleteEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorSetVoltageEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorSetVoltageCompleteEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorSetVoltageCompleteRE.exec(eventBase.details);if(!event)return false;const name=event[1];const voltage=parseInt(event[2]);const ctr=this.getCtr_(name,'voltage');ctr.series[0].addCounterSample(ts,voltage);return true;}};Parser.register(RegulatorParser);return{RegulatorParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function RssParser(importer){Parser.call(this,importer);importer.registerEventHandler('rss_stat',RssParser.prototype.rssStat.bind(this));}
+const TestExports={};const rssStatRE=new RegExp('member=(\\d+) size=(\\d+)');TestExports.rssStatRE=rssStatRE;const unknownThreadName='<...>';RssParser.prototype={__proto__:Parser.prototype,rssStat(eventName,cpuNumber,pid,ts,eventBase){const event=rssStatRE.exec(eventBase.details);if(!event)return false;const member=parseInt(event[1]);const size=parseInt(event[2]);if(eventBase.tgid===undefined){return false;}
+const tgid=parseInt(eventBase.tgid);const process=this.importer.model_.getOrCreateProcess(tgid);let subTitle='';if(member===0){subTitle=' (file pages)';}else if(member===1){subTitle=' (anon)';}
+const rssCounter=process.getOrCreateCounter('RSS','RSS '+member+subTitle);if(rssCounter.numSeries===0){rssCounter.addSeries(new tr.model.CounterSeries('RSS',tr.b.ColorScheme.getColorIdForGeneralPurposeString(rssCounter.name)));}
+rssCounter.series.forEach(function(series){series.addCounterSample(ts,size);});return true;},};Parser.register(RssParser);return{RssParser,_RssParserTestExports:TestExports};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function SchedParser(importer){Parser.call(this,importer);importer.registerEventHandler('sched_switch',SchedParser.prototype.schedSwitchEvent.bind(this));importer.registerEventHandler('sched_wakeup',SchedParser.prototype.schedWakeupEvent.bind(this));importer.registerEventHandler('sched_blocked_reason',SchedParser.prototype.schedBlockedEvent.bind(this));importer.registerEventHandler('sched_cpu_hotplug',SchedParser.prototype.schedCpuHotplugEvent.bind(this));}
const TestExports={};const schedSwitchRE=new RegExp('prev_comm=(.+) prev_pid=(\\d+) prev_prio=(\\d+) '+'prev_state=(\\S\\+?|\\S\\|\\S) ==> '+'next_comm=(.+) next_pid=(\\d+) next_prio=(\\d+)');const schedBlockedRE=new RegExp('pid=(\\d+) iowait=(\\d) caller=(.+)');TestExports.schedSwitchRE=schedSwitchRE;const schedWakeupRE=/comm=(.+) pid=(\d+) prio=(\d+)(?: success=\d+)? target_cpu=(\d+)/;TestExports.schedWakeupRE=schedWakeupRE;const unknownThreadName='<...>';SchedParser.prototype={__proto__:Parser.prototype,schedSwitchEvent(eventName,cpuNumber,pid,ts,eventBase){const event=schedSwitchRE.exec(eventBase.details);if(!event)return false;const prevState=event[4];const nextComm=event[5];const nextPid=parseInt(event[6]);const nextPrio=parseInt(event[7]);if(eventBase.tgid!==undefined){const tgid=parseInt(eventBase.tgid);const process=this.importer.model_.getOrCreateProcess(tgid);const storedThread=process.getThread(pid);if(!storedThread){const thread=process.getOrCreateThread(pid);thread.name=eventBase.threadName;}else if(storedThread.name===unknownThreadName){storedThread.name=eventBase.threadName;}}
const nextThread=this.importer.threadsByLinuxPid[nextPid];let nextName;if(nextThread){nextName=nextThread.userFriendlyName;}else{nextName=nextComm;}
const cpu=this.importer.getOrCreateCpu(cpuNumber);cpu.switchActiveThread(ts,{stateWhenDescheduled:prevState},nextPid,nextName,{comm:nextComm,tid:nextPid,prio:nextPrio});return true;},schedWakeupEvent(eventName,cpuNumber,pid,ts,eventBase){const event=schedWakeupRE.exec(eventBase.details);if(!event)return false;const fromPid=pid;const comm=event[1];pid=parseInt(event[2]);const prio=parseInt(event[3]);this.importer.markPidRunnable(ts,pid,comm,prio,fromPid);return true;},schedCpuHotplugEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/cpu (\d+) (.+) error=(\d+)/.exec(eventBase.details);if(!event)return false;cpuNumber=event[1];const state=event[2];const targetCpu=this.importer.getOrCreateCpu(cpuNumber);const powerCounter=targetCpu.getOrCreateCounter('','Cpu Hotplug');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('State',tr.b.ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'State')));}
@@ -6137,7 +6290,7 @@ function stripSuffix(str,suffix){if(!endsWith(str,suffix))return str;return str.
let events=[];if(produceResult){for(let i=0;i<rawEvents.length;i++){let event=rawEvents[i];event=stripSuffix(event,'\\n\\');events.push(event);}}else{events=[rawEvents[rawEvents.length-1]];}
const oldLastEvent=events[events.length-1];const newLastEvent=stripSuffix(oldLastEvent,'\\n";');if(newLastEvent===oldLastEvent)return failure;events[events.length-1]=newLastEvent;return{ok:true,lines:produceResult?events:undefined,eventsBeginAtLine};};FTraceImporter._extractEventsFromSystraceMultiHTML=function(incomingEvents,produceResult){const failure={ok:false};if(produceResult===undefined)produceResult=true;const header=incomingEvents instanceof tr.b.TraceStream?incomingEvents.header:incomingEvents;if(!(new RegExp('^<!DOCTYPE HTML>','i').test(header)))return failure;const r=new tr.importer.SimpleLineReader(incomingEvents);let events=[];let eventsBeginAtLine;while(!/^# tracer:/.test(events)){if(!r.advanceToLineMatching(/^ <script class="trace-data" type="application\/text">$/)){return failure;}
eventsBeginAtLine=r.curLineNumber+1;r.beginSavingLines();if(!r.advanceToLineMatching(/^ <\/script>$/))return failure;events=r.endSavingLinesAndGetResult();events=events.slice(1,events.length-1);}
-if(!r.advanceToLineMatching(/^<\/body>$/))return failure;if(!r.advanceToLineMatching(/^<\/html>$/))return failure;return{ok:true,lines:produceResult?events:undefined,eventsBeginAtLine,};};FTraceImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'FTraceImporter';},get model(){return this.model_;},importClockSyncMarkers(){this.lazyInit_();this.forEachLine_(function(text,eventBase,cpuNumber,pid,ts){const eventName=eventBase.eventName;if(eventName!=='tracing_mark_write'&&eventName!=='0')return;if(traceEventClockSyncRE.exec(eventBase.details)||genericClockSyncRE.exec(eventBase.details)){this.traceClockSyncEvent_(eventName,cpuNumber,pid,ts,eventBase);}else if(realTimeClockSyncRE.exec(eventBase.details)){const match=realTimeClockSyncRE.exec(eventBase.details);this.model_.realtime_to_monotonic_offset_ms=ts-match[1];}}.bind(this));},importEvents(){const modelTimeTransformer=this.model_.clockSyncManager.getModelTimeTransformer(this.clockDomainId_);this.importCpuData_(modelTimeTransformer);this.buildMapFromLinuxPidsToThreads_();this.buildPerThreadCpuSlicesFromCpuState_();},registerEventHandler(eventName,handler){this.eventHandlers_[eventName]=handler;},getOrCreateCpu(cpuNumber){return this.model_.kernel.getOrCreateCpu(cpuNumber);},getOrCreateKernelThread(kernelThreadName,pid,tid){if(!this.kernelThreadStates_[kernelThreadName]){const thread=this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);thread.name=kernelThreadName;this.kernelThreadStates_[kernelThreadName]={pid,thread,openSlice:undefined,openSliceTS:undefined};this.threadsByLinuxPid[tid]=thread;}
+if(!r.advanceToLineMatching(/^<\/body>$/))return failure;if(!r.advanceToLineMatching(/^<\/html>$/))return failure;return{ok:true,lines:produceResult?events:undefined,eventsBeginAtLine,};};FTraceImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'FTraceImporter';},get model(){return this.model_;},importClockSyncMarkers(){this.lazyInit_();this.forEachLine_(function(text,eventBase,cpuNumber,pid,ts){const eventName=eventBase.eventName;if(eventName!=='tracing_mark_write'&&eventName!=='0')return;if(traceEventClockSyncRE.exec(eventBase.details)||genericClockSyncRE.exec(eventBase.details)){this.traceClockSyncEvent_(eventName,cpuNumber,pid,ts,eventBase);}else if(realTimeClockSyncRE.exec(eventBase.details)){const match=realTimeClockSyncRE.exec(eventBase.details);this.model_.realtime_to_monotonic_offset_ms=ts-match[1];}}.bind(this));},importEvents(){if(this.lines_.length===0)return;const modelTimeTransformer=this.model_.clockSyncManager.getModelTimeTransformer(this.clockDomainId_);this.importCpuData_(modelTimeTransformer);this.buildMapFromLinuxPidsToThreads_();this.buildPerThreadCpuSlicesFromCpuState_();},registerEventHandler(eventName,handler){this.eventHandlers_[eventName]=handler;},getOrCreateCpu(cpuNumber){return this.model_.kernel.getOrCreateCpu(cpuNumber);},getOrCreateKernelThread(kernelThreadName,pid,tid){if(!this.kernelThreadStates_[kernelThreadName]){const thread=this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);thread.name=kernelThreadName;this.kernelThreadStates_[kernelThreadName]={pid,thread,openSlice:undefined,openSliceTS:undefined};this.threadsByLinuxPid[tid]=thread;}
return this.kernelThreadStates_[kernelThreadName];},getOrCreateBinderKernelThread(kernelThreadName,pid,tid){const key=kernelThreadName+pid+tid;if(!this.kernelThreadStates_[key]){const thread=this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);thread.name=kernelThreadName;this.kernelThreadStates_[key]={pid,thread,openSlice:undefined,openSliceTS:undefined};this.threadsByLinuxPid[tid]=thread;}
return this.kernelThreadStates_[key];},getOrCreatePseudoThread(threadName){let thread=this.kernelThreadStates_[threadName];if(!thread){thread=this.getOrCreateKernelThread(threadName,pseudoKernelPID,this.pseudoThreadCounter);this.pseudoThreadCounter++;}
return thread;},markPidRunnable(ts,pid,comm,prio,fromPid){this.wakeups_.push({ts,tid:pid,fromTid:fromPid});},addPidBlockedReason(ts,pid,iowait,caller){this.blockedReasons_.push({ts,tid:pid,iowait,caller});},buildMapFromLinuxPidsToThreads_(){this.threadsByLinuxPid={};this.model_.getAllThreads().forEach(function(thread){this.threadsByLinuxPid[thread.tid]=thread;}.bind(this));},buildPerThreadCpuSlicesFromCpuState_(){const SCHEDULING_STATE=tr.model.SCHEDULING_STATE;for(const cpuNumber in this.model_.kernel.cpus){const cpu=this.model_.kernel.cpus[cpuNumber];for(let i=0;i<cpu.slices.length;i++){const cpuSlice=cpu.slices[i];const thread=this.threadsByLinuxPid[cpuSlice.args.tid];if(!thread)continue;cpuSlice.threadThatWasRunning=thread;if(!thread.tempCpuSlices){thread.tempCpuSlices=[];}
@@ -6254,7 +6407,8 @@ throw new Error('Invalid titles in combineInitiatorTypes');}
ProtoExpectation.prototype={get isValid(){return this.end>this.start;},containsTypeNames(typeNames){return this.associatedEvents.some(x=>typeNames.indexOf(x.typeName)>=0);},containsSliceTitle(title){return this.associatedEvents.some(x=>title===x.title);},createInteractionRecord(model){if(this.type!==ProtoExpectation.IGNORED_TYPE&&!this.isValid){model.importWarning({type:'ProtoExpectation',message:'Please file a bug with this trace. '+this.debug(),showToUser:true});return undefined;}
const duration=this.end-this.start;let ir=undefined;switch(this.type){case ProtoExpectation.RESPONSE_TYPE:ir=new tr.model.um.ResponseExpectation(model,this.initiatorType,this.start,duration,this.isAnimationBegin);break;case ProtoExpectation.ANIMATION_TYPE:ir=new tr.model.um.AnimationExpectation(model,this.initiatorType,this.start,duration);break;}
if(!ir)return undefined;ir.sourceEvents.addEventSet(this.associatedEvents);function pushAssociatedEvents(event){ir.associatedEvents.push(event);if(event.associatedEvents){ir.associatedEvents.addEventSet(event.associatedEvents);}}
-this.associatedEvents.forEach(function(event){pushAssociatedEvents(event);if(event.subSlices){event.subSlices.forEach(pushAssociatedEvents);}});return ir;},merge(other){this.initiatorType=combineInitiatorTypes(this.initiatorType,other.initiatorType);this.associatedEvents.addEventSet(other.associatedEvents);this.start=Math.min(this.start,other.start);this.end=Math.max(this.end,other.end);if(other.isAnimationBegin){this.isAnimationBegin=true;}},pushEvent(event){this.start=Math.min(this.start,event.start);this.end=Math.max(this.end,event.end);this.associatedEvents.push(event);},pushSample(sample){this.start=Math.min(this.start,sample.timestamp);this.end=Math.max(this.end,sample.timestamp);this.associatedEvents.push(sample);},containsTimestampInclusive(timestamp){return(this.start<=timestamp)&&(timestamp<=this.end);},intersects(other){return(other.start<this.end)&&(other.end>this.start);},isNear(event,threshold){return(this.end+threshold)>event.start;},debug(){let debugString=this.type+'(';debugString+=parseInt(this.start)+' ';debugString+=parseInt(this.end);this.associatedEvents.forEach(function(event){debugString+=' '+event.typeName;});return debugString+')';}};return{ProtoExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const ProtoExpectation=tr.importer.ProtoExpectation;const INITIATOR_TYPE=tr.model.um.INITIATOR_TYPE;const INPUT_TYPE=tr.e.cc.INPUT_EVENT_TYPE_NAMES;const KEYBOARD_TYPE_NAMES=[INPUT_TYPE.CHAR,INPUT_TYPE.KEY_DOWN_RAW,INPUT_TYPE.KEY_DOWN,INPUT_TYPE.KEY_UP];const MOUSE_RESPONSE_TYPE_NAMES=[INPUT_TYPE.CLICK,INPUT_TYPE.CONTEXT_MENU];const MOUSE_WHEEL_TYPE_NAMES=[INPUT_TYPE.MOUSE_WHEEL];const MOUSE_DRAG_TYPE_NAMES=[INPUT_TYPE.MOUSE_DOWN,INPUT_TYPE.MOUSE_MOVE,INPUT_TYPE.MOUSE_UP];const TAP_TYPE_NAMES=[INPUT_TYPE.TAP,INPUT_TYPE.TAP_CANCEL,INPUT_TYPE.TAP_DOWN];const PINCH_TYPE_NAMES=[INPUT_TYPE.PINCH_BEGIN,INPUT_TYPE.PINCH_END,INPUT_TYPE.PINCH_UPDATE];const FLING_TYPE_NAMES=[INPUT_TYPE.FLING_CANCEL,INPUT_TYPE.FLING_START];const TOUCH_TYPE_NAMES=[INPUT_TYPE.TOUCH_END,INPUT_TYPE.TOUCH_MOVE,INPUT_TYPE.TOUCH_START];const SCROLL_TYPE_NAMES=[INPUT_TYPE.SCROLL_BEGIN,INPUT_TYPE.SCROLL_END,INPUT_TYPE.SCROLL_UPDATE];const ALL_HANDLED_TYPE_NAMES=[].concat(KEYBOARD_TYPE_NAMES,MOUSE_RESPONSE_TYPE_NAMES,MOUSE_WHEEL_TYPE_NAMES,MOUSE_DRAG_TYPE_NAMES,PINCH_TYPE_NAMES,TAP_TYPE_NAMES,FLING_TYPE_NAMES,TOUCH_TYPE_NAMES,SCROLL_TYPE_NAMES);const RENDERER_FLING_TITLE='InputHandlerProxy::HandleGestureFling::started';const PLAYBACK_EVENT_TITLE='VideoPlayback';const CSS_ANIMATION_TITLE='Animation';const VR_COUNTER_NAMES=['gpu.WebVR FPS','gpu.WebVR frame time (ms)','gpu.WebVR pose prediction (ms)',];const VR_EVENT_NAMES=['VrShellGl::AcquireFrame','VrShellGl::DrawFrame','VrShellGl::DrawSubmitFrameWhenReady','VrShellGl::DrawUiView','VrShellGl::UpdateController',];const VR_RESPONSE_MS=1000;const INPUT_MERGE_THRESHOLD_MS=200;const ANIMATION_MERGE_THRESHOLD_MS=32;const MOUSE_WHEEL_THRESHOLD_MS=40;const MOUSE_MOVE_THRESHOLD_MS=40;function compareEvents(x,y){if(x.start!==y.start){return x.start-y.start;}
+this.associatedEvents.forEach(function(event){pushAssociatedEvents(event);if(event.subSlices){event.subSlices.forEach(pushAssociatedEvents);}});return ir;},merge(other){this.initiatorType=combineInitiatorTypes(this.initiatorType,other.initiatorType);this.associatedEvents.addEventSet(other.associatedEvents);this.start=Math.min(this.start,other.start);this.end=Math.max(this.end,other.end);if(other.isAnimationBegin){this.isAnimationBegin=true;}},pushEvent(event){this.start=Math.min(this.start,event.start);this.end=Math.max(this.end,event.end);this.associatedEvents.push(event);},pushSample(sample){this.start=Math.min(this.start,sample.timestamp);this.end=Math.max(this.end,sample.timestamp);this.associatedEvents.push(sample);},containsTimestampInclusive(timestamp){return(this.start<=timestamp)&&(timestamp<=this.end);},intersects(other){return(other.start<this.end)&&(other.end>this.start);},isNear(event,threshold){return(this.end+threshold)>event.start;},debug(){let debugString=this.type+'(';debugString+=parseInt(this.start)+' ';debugString+=parseInt(this.end);this.associatedEvents.forEach(function(event){debugString+=' '+event.typeName;});return debugString+')';}};return{ProtoExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const ProtoExpectation=tr.importer.ProtoExpectation;const INITIATOR_TYPE=tr.model.um.INITIATOR_TYPE;const INPUT_TYPE=tr.e.cc.INPUT_EVENT_TYPE_NAMES;const KEYBOARD_TYPE_NAMES=[INPUT_TYPE.CHAR,INPUT_TYPE.KEY_DOWN_RAW,INPUT_TYPE.KEY_DOWN,INPUT_TYPE.KEY_UP];const MOUSE_RESPONSE_TYPE_NAMES=[INPUT_TYPE.CLICK,INPUT_TYPE.CONTEXT_MENU];const MOUSE_WHEEL_TYPE_NAMES=[INPUT_TYPE.MOUSE_WHEEL];const MOUSE_DRAG_TYPE_NAMES=[INPUT_TYPE.MOUSE_DOWN,INPUT_TYPE.MOUSE_MOVE,INPUT_TYPE.MOUSE_UP];const TAP_TYPE_NAMES=[INPUT_TYPE.TAP,INPUT_TYPE.TAP_CANCEL,INPUT_TYPE.TAP_DOWN];const PINCH_TYPE_NAMES=[INPUT_TYPE.PINCH_BEGIN,INPUT_TYPE.PINCH_END,INPUT_TYPE.PINCH_UPDATE];const FLING_TYPE_NAMES=[INPUT_TYPE.FLING_CANCEL,INPUT_TYPE.FLING_START];const TOUCH_TYPE_NAMES=[INPUT_TYPE.TOUCH_END,INPUT_TYPE.TOUCH_MOVE,INPUT_TYPE.TOUCH_START];const SCROLL_TYPE_NAMES=[INPUT_TYPE.SCROLL_BEGIN,INPUT_TYPE.SCROLL_END,INPUT_TYPE.SCROLL_UPDATE];const ALL_HANDLED_TYPE_NAMES=[].concat(KEYBOARD_TYPE_NAMES,MOUSE_RESPONSE_TYPE_NAMES,MOUSE_WHEEL_TYPE_NAMES,MOUSE_DRAG_TYPE_NAMES,PINCH_TYPE_NAMES,TAP_TYPE_NAMES,FLING_TYPE_NAMES,TOUCH_TYPE_NAMES,SCROLL_TYPE_NAMES);const RENDERER_FLING_TITLE='InputHandlerProxy::HandleGestureFling::started';const PLAYBACK_EVENT_TITLE='VideoPlayback';const CSS_ANIMATION_TITLE='Animation';const VR_COUNTER_NAMES=['gpu.WebVR FPS','gpu.WebVR frame time (ms)','gpu.WebVR pose prediction (ms)','gpu.WebXR FPS',];const VR_EXPECTATION_EVENTS={'Vr.AcquireGvrFrame':{'histogramName':'acquire_frame','description':'Duration acquire a frame from GVR','hasCpuTime':true,},'Vr.DrawFrame':{'histogramName':'draw_frame','description':'Duration to render one frame','hasCpuTime':true,},'Vr.PostSubmitDrawOnGpu':{'histogramName':'post_submit_draw_on_gpu','description':'Duration to draw a frame on GPU post submit to '+'GVR. Note this duration may include time spent on '+'reprojection','hasCpuTime':false,},'Vr.ProcessControllerInput':{'histogramName':'update_controller','description':'Duration to query input from the controller','hasCpuTime':true,},'Vr.ProcessControllerInputForWebXr':{'histogramName':'update_controller_webxr','description':'Duration to query input from the controller for WebXR','hasCpuTime':true,},'Vr.SubmitFrameNow':{'histogramName':'submit_frame','description':'Duration to submit a frame to GVR','hasCpuTime':true,}};const WEBXR_INSTANT_EVENTS={'WebXR frame time (ms)':{'javascript':{'histogramName':'webxr_frame_time_javascript','description':'WebXR frame time spent on JavaScript',},'rendering':{'histogramName':'webxr_frame_time_rendering','description':'WebXR frame time spent on rendering'}},'WebXR pose prediction':{'milliseconds':{'histogramName':'webxr_pose_prediction','description':'WebXR pose prediction in ms',},},};const XR_DEVICE_SERVICE_PROCESS='Service: xr_device_service';function isXrDeviceServiceProcess(process){if(process.name===XR_DEVICE_SERVICE_PROCESS)return true;return false;}
+const VR_RESPONSE_MS=1000;const INPUT_MERGE_THRESHOLD_MS=200;const ANIMATION_MERGE_THRESHOLD_MS=32;const MOUSE_WHEEL_THRESHOLD_MS=40;const MOUSE_MOVE_THRESHOLD_MS=40;function compareEvents(x,y){if(x.start!==y.start){return x.start-y.start;}
if(x.end!==y.end){return x.end-y.end;}
if(x.guid&&y.guid){return x.guid-y.guid;}
return 0;}
@@ -6311,9 +6465,10 @@ return protoExpectations;}
function handleVrAnimations(modelHelper,sortedInputEvents,warn){const events=[];const processes=[];if(typeof modelHelper.gpuHelper!=='undefined'){processes.push(modelHelper.gpuHelper.process);}
for(const helper of Object.values(modelHelper.rendererHelpers)){processes.push(helper.process);}
for(const helper of Object.values(modelHelper.browserHelpers)){processes.push(helper.process);}
+for(const service of modelHelper.model.getAllProcesses(isXrDeviceServiceProcess)){processes.push(service);}
let vrCounterStart=Number.MAX_SAFE_INTEGER;let vrEventStart=Number.MAX_SAFE_INTEGER;for(const proc of processes){for(const[counterName,counterSeries]of
Object.entries(proc.counters)){if(VR_COUNTER_NAMES.includes(counterName)){for(const series of counterSeries.series){for(const sample of series.samples){events.push(sample);vrCounterStart=Math.min(vrCounterStart,sample.timestamp);}}}}
-for(const thread of Object.values(proc.threads)){for(const container of thread.childEventContainers()){for(const slice of container.slices){if(VR_EVENT_NAMES.includes(slice.title)){events.push(slice);vrEventStart=Math.min(vrEventStart,slice.start);}}}}}
+for(const thread of Object.values(proc.threads)){for(const container of thread.childEventContainers()){for(const slice of container.slices){if(slice.title in VR_EXPECTATION_EVENTS||slice.title in WEBXR_INSTANT_EVENTS){events.push(slice);vrEventStart=Math.min(vrEventStart,slice.start);}}}}}
if(events.length===0){return[];}
events.sort(function(x,y){if(x.range.min!==y.range.min){return x.range.min-y.range.min;}
return x.guid-y.guid;});vrCounterStart=(vrCounterStart===Number.MAX_SAFE_INTEGER)?0:vrCounterStart;vrEventStart=(vrEventStart===Number.MAX_SAFE_INTEGER)?0:vrEventStart;const vrAnimationStart=Math.max(vrCounterStart,vrEventStart)+
@@ -6359,7 +6514,7 @@ if((handledEvents.indexOf(event)>=0)&&(!isImplFrameEvent(event))){warn({type:'Us
handledEvents.push(event);});});sortedInputEvents.forEach(function(event){if(handledEvents.indexOf(event)<0){warn({type:'UserModelBuilder',message:`double-handled event: ${event.typeName} @ ${event.start}`,showToUser:false,});}});}
function findInputExpectations(modelHelper){let warning;function warn(w){if(warning)return;warning=w;}
const sortedInputEvents=getSortedInputEvents(modelHelper);let protoExpectations=findProtoExpectations(modelHelper,sortedInputEvents,warn);protoExpectations=postProcessProtoExpectations(modelHelper,protoExpectations);checkAllInputEventsHandled(modelHelper,sortedInputEvents,protoExpectations,warn);if(warning)modelHelper.model.importWarning(warning);const expectations=[];protoExpectations.forEach(function(protoExpectation){const ir=protoExpectation.createInteractionRecord(modelHelper.model);if(ir){expectations.push(ir);}});return expectations;}
-return{findInputExpectations,compareEvents,CSS_ANIMATION_TITLE,};});'use strict';tr.exportTo('tr.b',function(){class FixedColorScheme{constructor(namesToColors){this.namesToColors_=namesToColors;}
+return{findInputExpectations,compareEvents,CSS_ANIMATION_TITLE,VR_EXPECTATION_EVENTS,WEBXR_INSTANT_EVENTS,};});'use strict';tr.exportTo('tr.b',function(){class FixedColorScheme{constructor(namesToColors){this.namesToColors_=namesToColors;}
static fromNames(names){const namesToColors=new Map();const generator=new tr.b.SinebowColorGenerator();for(const name of names){namesToColors.set(name,generator.colorForKey(name));}
return new FixedColorScheme(namesToColors);}
getColor(name){const color=this.namesToColors_.get(name);if(color===undefined)throw new Error('Unknown color: '+name);return color;}}
@@ -6378,9 +6533,11 @@ function makeKeyUniqueAndSet(map,key,value){let uniqueKey=key;let nextIndex=2;wh
map.set(uniqueKey,value);}
function skipDumpsThatDoNotIntersectRange(dumps,opt_range){if(!opt_range)return dumps;return dumps.filter(d=>opt_range.intersectsExplicitRangeInclusive(d.start,d.end));}
function hasCategoryAndName(event,category,title){return event.title===title&&event.category&&tr.b.getCategoryParts(event.category).includes(category);}
-return{hasCategoryAndName,filterExpectationsByRange,perceptualBlend,splitGlobalDumpsByBrowserName};});'use strict';tr.exportTo('tr.e.chrome',function(){const CHROME_INTERNAL_URLS=['','about:blank','data:text/html,pluginplaceholderdata','chrome-error://chromewebdata/'];const SCHEDULER_TOP_LEVEL_TASK_TITLE='ThreadControllerImpl::RunTask';const SCHEDULOER_TOP_LEVEL_TASKS=new Set([SCHEDULER_TOP_LEVEL_TASK_TITLE,'ThreadControllerImpl::DoWork','TaskQueueManager::ProcessTaskFromWorkQueue']);class EventFinderUtils{static hasCategoryAndName(event,category,title){return event.title===title&&event.category&&tr.b.getCategoryParts(event.category).includes(category);}
+return{hasCategoryAndName,filterExpectationsByRange,perceptualBlend,splitGlobalDumpsByBrowserName};});'use strict';tr.exportTo('tr.e.chrome',function(){const CHROME_INTERNAL_URLS=['','about:blank','data:text/html,pluginplaceholderdata','chrome-error://chromewebdata/'];const SCHEDULER_TOP_LEVEL_TASK_TITLE='ThreadControllerImpl::RunTask';const SCHEDULER_TOP_LEVEL_TASKS=new Set([SCHEDULER_TOP_LEVEL_TASK_TITLE,'ThreadControllerImpl::DoWork','TaskQueueManager::ProcessTaskFromWorkQueue']);class EventFinderUtils{static hasCategoryAndName(event,category,title){return event.title===title&&event.category&&tr.b.getCategoryParts(event.category).includes(category);}
static*getMainThreadEvents(rendererHelper,eventTitle,eventCategory){if(!rendererHelper.mainThread)return;for(const ev of rendererHelper.mainThread.sliceGroup.childEvents()){if(rendererHelper.isTelemetryInternalEvent(ev))continue;if(!this.hasCategoryAndName(ev,eventCategory,eventTitle)){continue;}
yield ev;}}
+static getNetworkEventsInRange(process,range){const networkEvents=[];for(const thread of Object.values(process.threads)){const threadHelper=new tr.model.helpers.ChromeThreadHelper(thread);const events=threadHelper.getNetworkEvents();for(const event of events){if(range.intersectsExplicitRangeInclusive(event.start,event.end)){networkEvents.push(event);}}}
+return networkEvents;}
static getSortedMainThreadEventsByFrame(rendererHelper,eventTitle,eventCategory){const eventsByFrame=new Map();const events=this.getMainThreadEvents(rendererHelper,eventTitle,eventCategory);for(const ev of events){const frameIdRef=ev.args.frame;if(frameIdRef===undefined)continue;if(!eventsByFrame.has(frameIdRef)){eventsByFrame.set(frameIdRef,[]);}
eventsByFrame.get(frameIdRef).push(ev);}
return eventsByFrame;}
@@ -6392,7 +6549,8 @@ static findNextEventStartingOnOrAfterTimestamp(sortedEvents,timestamp){const fir
return sortedEvents[firstIndexOnOrAfterTimestamp];}
static findNextEventStartingAfterTimestamp(sortedEvents,timestamp){const firstIndexOnOrAfterTimestamp=tr.b.findFirstTrueIndexInSortedArray(sortedEvents,e=>e.start>timestamp);if(firstIndexOnOrAfterTimestamp===sortedEvents.length){return undefined;}
return sortedEvents[firstIndexOnOrAfterTimestamp];}
-static findToplevelSchedulerTasks(mainThread){const tasks=[];tasks.push(...mainThread.findTopmostSlices(slice=>slice.category==='toplevel'&&SCHEDULOER_TOP_LEVEL_TASKS.has(slice.title)));return tasks;}}
+static findToplevelSchedulerTasks(mainThread){const tasks=[];for(const task of mainThread.findTopmostSlices(slice=>slice.category==='toplevel'&&SCHEDULER_TOP_LEVEL_TASKS.has(slice.title))){tasks.push(task);}
+return tasks;}}
return{EventFinderUtils,CHROME_INTERNAL_URLS,SCHEDULER_TOP_LEVEL_TASK_TITLE,};});'use strict';tr.exportTo('tr.e.chrome',function(){const TIME_TO_INTERACTIVE_WINDOW_SIZE_MS=5000;const ACTIVE_REQUEST_TOLERANCE=2;const FCI_MIN_CLUSTER_SEPARATION_MS=1000;const TASK_CLUSTER_HEAVINESS_THRESHOLD_MS=250;const ENDPOINT_TYPES={LONG_TASK_START:'LONG_TASK_START',LONG_TASK_END:'LONG_TASK_END',REQUEST_START:'REQUEST_START',REQUEST_END:'REQUEST_END'};function getEndpoints_(events,startType,endType){const endpoints=[];for(const event of events){endpoints.push({time:event.start,type:startType});endpoints.push({time:event.end,type:endType});}
return endpoints;}
function reachedTTIQuiscence_(timestamp,networkQuietWindowStart,mainThreadQuietWindowStart){if(networkQuietWindowStart===undefined||mainThreadQuietWindowStart===undefined){return false;}
@@ -6422,16 +6580,14 @@ return Math.max(fiCandidate,domContentLoadedEnd);}
return{findInteractiveTime,findFirstCpuIdleTime,requiredFCIWindowSizeMs,findFCITaskClusters,};});'use strict';tr.exportTo('tr.model.um',function(){const LOAD_SUBTYPE_NAMES={SUCCESSFUL:'Successful',FAILED:'Failed',};const DOES_LOAD_SUBTYPE_NAME_EXIST={};for(const key in LOAD_SUBTYPE_NAMES){DOES_LOAD_SUBTYPE_NAME_EXIST[LOAD_SUBTYPE_NAMES[key]]=true;}
function LoadExpectation(parentModel,initiatorTitle,start,duration,renderer,navigationStart,fmpEvent,dclEndEvent,cpuIdleTime,timeToInteractive,url,frameId){if(!DOES_LOAD_SUBTYPE_NAME_EXIST[initiatorTitle]){throw new Error(initiatorTitle+' is not in LOAD_SUBTYPE_NAMES');}
tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);this.renderProcess=renderer;this.renderMainThread=undefined;this.routingId=undefined;this.parentRoutingId=undefined;this.loadFinishedEvent=undefined;this.navigationStart=navigationStart;this.fmpEvent=fmpEvent;this.domContentLoadedEndEvent=dclEndEvent;this.firstCpuIdleTime=cpuIdleTime;this.timeToInteractive=timeToInteractive;this.url=url;this.frameId=frameId;}
-LoadExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:LoadExpectation};tr.model.um.UserExpectation.subTypes.register(LoadExpectation,{stageTitle:'Load',colorId:tr.b.ColorScheme.getColorIdForReservedName('rail_load')});return{LOAD_SUBTYPE_NAMES,LoadExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const LONG_TASK_THRESHOLD_MS=50;const IGNORE_URLS=['','about:blank',];function getNetworkEventsInRange(process,range){const networkEvents=[];for(const thread of Object.values(process.threads)){const threadHelper=new tr.model.helpers.ChromeThreadHelper(thread);const events=threadHelper.getNetworkEvents();for(const event of events){if(range.intersectsExplicitRangeInclusive(event.start,event.end)){networkEvents.push(event);}}}
-return networkEvents;}
-function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
+LoadExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:LoadExpectation};tr.model.um.UserExpectation.subTypes.register(LoadExpectation,{stageTitle:'Load',colorId:tr.b.ColorScheme.getColorIdForReservedName('rail_load')});return{LOAD_SUBTYPE_NAMES,LoadExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const LONG_TASK_THRESHOLD_MS=50;const IGNORE_URLS=['','about:blank',];function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
return snapshot;}
function findFirstMeaningfulPaintCandidates(rendererHelper){const candidatesForFrameId={};for(const ev of rendererHelper.process.getDescendantEvents()){if(!tr.e.chrome.EventFinderUtils.hasCategoryAndName(ev,'loading','firstMeaningfulPaintCandidate')){continue;}
if(rendererHelper.isTelemetryInternalEvent(ev))continue;const frameIdRef=ev.args.frame;if(frameIdRef===undefined)continue;let list=candidatesForFrameId[frameIdRef];if(list===undefined){candidatesForFrameId[frameIdRef]=list=[];}
list.push(ev);}
return candidatesForFrameId;}
function computeInteractivityMetricSample_(rendererHelper,navigationStart,fmpEvent,domContentLoadedEndEvent,searchWindowEnd){if(domContentLoadedEndEvent===undefined||fmpEvent===undefined){return{interactiveTime:undefined,firstCpuIdleTime:undefined};}
-const firstMeaningfulPaintTime=fmpEvent.start;const mainThreadTasks=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const longTasks=mainThreadTasks.filter(task=>task.duration>=LONG_TASK_THRESHOLD_MS);const longTasksInWindow=longTasks.filter(task=>task.range.intersectsExplicitRangeInclusive(firstMeaningfulPaintTime,searchWindowEnd));const resourceLoadEvents=getNetworkEventsInRange(rendererHelper.process,tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd));const firstCpuIdleTime=tr.e.chrome.findFirstCpuIdleTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow);const interactiveTime=resourceLoadEvents.length>0?tr.e.chrome.findInteractiveTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow,resourceLoadEvents):undefined;return{interactiveTime,firstCpuIdleTime};}
+const firstMeaningfulPaintTime=fmpEvent.start;const mainThreadTasks=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const longTasks=mainThreadTasks.filter(task=>task.duration>=LONG_TASK_THRESHOLD_MS);const longTasksInWindow=longTasks.filter(task=>task.range.intersectsExplicitRangeInclusive(firstMeaningfulPaintTime,searchWindowEnd));const resourceLoadEvents=tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd));const firstCpuIdleTime=tr.e.chrome.findFirstCpuIdleTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow);const interactiveTime=resourceLoadEvents.length>0?tr.e.chrome.findInteractiveTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow,resourceLoadEvents):undefined;return{interactiveTime,firstCpuIdleTime};}
function constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,navigationStart,fmpEvent,searchWindowEnd,url,frameId){const dclTimesForFrame=frameToDomContentLoadedEndEvents.get(frameId)||[];const dclSearchRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd);const dclTimesInWindow=dclSearchRange.filterArray(dclTimesForFrame,event=>event.start);let domContentLoadedEndEvent=undefined;if(dclTimesInWindow.length!==0){domContentLoadedEndEvent=dclTimesInWindow[dclTimesInWindow.length-1];}
const{interactiveTime,firstCpuIdleTime}=computeInteractivityMetricSample_(rendererHelper,navigationStart,fmpEvent,domContentLoadedEndEvent,searchWindowEnd);const duration=(interactiveTime===undefined)?searchWindowEnd-navigationStart.start:interactiveTime-navigationStart.start;return new tr.model.um.LoadExpectation(rendererHelper.modelHelper.model,tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL,navigationStart.start,duration,rendererHelper.process,navigationStart,fmpEvent,domContentLoadedEndEvent,firstCpuIdleTime,interactiveTime,url,frameId);}
function collectLoadExpectationsForRenderer(rendererHelper){const samples=[];const frameToNavStartEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const frameToDomContentLoadedEndEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'domContentLoadedEventEnd','blink.user_timing');function addSamples(frameIdRef,navigationStart,fmpCandidateEvents,searchWindowEnd,url){let fmpMarkerEvent=tr.e.chrome.EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(fmpCandidateEvents,searchWindowEnd);if(fmpMarkerEvent!==undefined&&navigationStart.start>fmpMarkerEvent.start){fmpMarkerEvent=undefined;}
@@ -6494,7 +6650,7 @@ return false;}
return{decorate,define,elementIsChildOf,};});'use strict';tr.exportTo('tr.b.math',function(){function Rect(){this.x=0;this.y=0;this.width=0;this.height=0;}
Rect.fromXYWH=function(x,y,w,h){const rect=new Rect();rect.x=x;rect.y=y;rect.width=w;rect.height=h;return rect;};Rect.fromArray=function(ary){if(ary.length!==4){throw new Error('ary.length must be 4');}
const rect=new Rect();rect.x=ary[0];rect.y=ary[1];rect.width=ary[2];rect.height=ary[3];return rect;};Rect.prototype={__proto__:Object.prototype,get left(){return this.x;},get top(){return this.y;},get right(){return this.x+this.width;},get bottom(){return this.y+this.height;},toString(){return'Rect('+this.x+', '+this.y+', '+
-this.width+', '+this.height+')';},toArray(){return[this.x,this.y,this.width,this.height];},clone(){const rect=new Rect();rect.x=this.x;rect.y=this.y;rect.width=this.width;rect.height=this.height;return rect;},enlarge(pad){const rect=new Rect();this.enlargeFast(rect,pad);return rect;},enlargeFast(out,pad){out.x=this.x-pad;out.y=this.y-pad;out.width=this.width+2*pad;out.height=this.height+2*pad;return out;},size(){return{width:this.width,height:this.height};},scale(s){const rect=new Rect();this.scaleFast(rect,s);return rect;},scaleSize(s){return Rect.fromXYWH(this.x,this.y,this.width*s,this.height*s);},scaleFast(out,s){out.x=this.x*s;out.y=this.y*s;out.width=this.width*s;out.height=this.height*s;return out;},translate(v){const rect=new Rect();this.translateFast(rect,v);return rect;},translateFast(out,v){out.x=this.x+v[0];out.y=this.x+v[1];out.width=this.width;out.height=this.height;return out;},asUVRectInside(containingRect){const rect=new Rect();rect.x=(this.x-containingRect.x)/containingRect.width;rect.y=(this.y-containingRect.y)/containingRect.height;rect.width=this.width/containingRect.width;rect.height=this.height/containingRect.height;return rect;},intersects(that){let ok=true;ok&=this.x<that.right;ok&=this.right>that.x;ok&=this.y<that.bottom;ok&=this.bottom>that.y;return ok;},equalTo(rect){return rect&&(this.x===rect.x)&&(this.y===rect.y)&&(this.width===rect.width)&&(this.height===rect.height);}};return{Rect,};});'use strict';tr.exportTo('tr.ui.b',function(){function instantiateTemplate(selector,doc){doc=doc||document;const el=Polymer.dom(doc).querySelector(selector);if(!el){throw new Error('Element not found');}
+this.width+', '+this.height+')';},toArray(){return[this.x,this.y,this.width,this.height];},clone(){const rect=new Rect();rect.x=this.x;rect.y=this.y;rect.width=this.width;rect.height=this.height;return rect;},enlarge(pad){const rect=new Rect();this.enlargeFast(rect,pad);return rect;},enlargeFast(out,pad){out.x=this.x-pad;out.y=this.y-pad;out.width=this.width+2*pad;out.height=this.height+2*pad;return out;},size(){return{width:this.width,height:this.height};},scale(s){const rect=new Rect();this.scaleFast(rect,s);return rect;},scaleSize(s){return Rect.fromXYWH(this.x,this.y,this.width*s,this.height*s);},scaleFast(out,s){out.x=this.x*s;out.y=this.y*s;out.width=this.width*s;out.height=this.height*s;return out;},translate(v){const rect=new Rect();this.translateFast(rect,v);return rect;},translateFast(out,v){out.x=this.x+v[0];out.y=this.x+v[1];out.width=this.width;out.height=this.height;return out;},asUVRectInside(containingRect){const rect=new Rect();rect.x=(this.x-containingRect.x)/containingRect.width;rect.y=(this.y-containingRect.y)/containingRect.height;rect.width=this.width/containingRect.width;rect.height=this.height/containingRect.height;return rect;},intersects(that){let ok=true;ok&=this.x<that.right;ok&=this.right>that.x;ok&=this.y<that.bottom;ok&=this.bottom>that.y;return ok;},equalTo(rect){return rect&&(this.x===rect.x)&&(this.y===rect.y)&&(this.width===rect.width)&&(this.height===rect.height);}};return{Rect,};});'use strict';tr.exportTo('tr.ui.b',function(){function instantiateTemplate(selector,doc){doc=doc||document;const el=Polymer.dom(doc).querySelector(selector);if(!el){throw new Error('Element not found: '+selector);}
return doc.importNode(el.content,true);}
function windowRectForElement(element){const position=[element.offsetLeft,element.offsetTop];const size=[element.offsetWidth,element.offsetHeight];let node=element.offsetParent;while(node){position[0]+=node.offsetLeft;position[1]+=node.offsetTop;node=node.offsetParent;}
return tr.b.math.Rect.fromXYWH(position[0],position[1],size[0],size[1]);}
@@ -6580,7 +6736,7 @@ if(!window.chrome.skiaBenchmarking.getOpTimings){return false;}
return true;};PictureSnapshot.CanGetInfo=function(){if(!PictureSnapshot.HasSkiaBenchmarking()){return false;}
if(!window.chrome.skiaBenchmarking.getInfo){return false;}
return true;};PictureSnapshot.HowToEnablePictureDebugging=function(){if(tr.isHeadless){return'Pictures only work in chrome';}
-const usualReason=['For pictures to show up, you need to have Chrome running with ','--enable-skia-benchmarking. Please restart chrome with this flag ','and try again.'].join('');if(!PictureSnapshot.HasSkiaBenchmarking()){return usualReason;}
+const usualReason=['For pictures to show up, the Chrome browser displaying the trace ','needs to be running with --enable-skia-benchmarking. Please restart ','chrome with this flag and try loading the trace again.'].join('');if(!PictureSnapshot.HasSkiaBenchmarking()){return usualReason;}
if(!PictureSnapshot.CanRasterize()){return'Your chrome is old: chrome.skipBenchmarking.rasterize not found';}
if(!PictureSnapshot.CanGetOps()){return'Your chrome is old: chrome.skiaBenchmarking.getOps not found';}
if(!PictureSnapshot.CanGetOpTimings()){return'Your chrome is old: '+'chrome.skiaBenchmarking.getOpTimings not found';}
@@ -6670,16 +6826,13 @@ this.findMatches_=findMatches;},get analysisViewRelatedEvents(){return this.anal
if(!(analysisViewRelatedEvents instanceof EventSet)){analysisViewRelatedEvents=new EventSet();}
this.analysisViewRelatedEvents_=analysisViewRelatedEvents;},get analysisLinkHoveredEvents(){return this.analysisLinkHoveredEvents_;},set analysisLinkHoveredEvents(analysisLinkHoveredEvents){if(this.appliedToModel_){throw new Error('Cannot mutate this state right now');}
if(!(analysisLinkHoveredEvents instanceof EventSet)){analysisLinkHoveredEvents=new EventSet();}
-this.analysisLinkHoveredEvents_=analysisLinkHoveredEvents;},get isAppliedToModel(){return this.appliedToModel_!==undefined;},get viewSpecificBrushingStates(){return this.viewSpecificBrushingStates_;},set viewSpecificBrushingStates(viewSpecificBrushingStates){this.viewSpecificBrushingStates_=viewSpecificBrushingStates;},get dimmedEvents_(){const dimmedEvents=new EventSet();dimmedEvents.addEventSet(this.findMatches);dimmedEvents.addEventSet(this.analysisViewRelatedEvents_);return dimmedEvents;},get brightenedEvents_(){const brightenedEvents=new EventSet();brightenedEvents.addEventSet(this.selection_);brightenedEvents.addEventSet(this.analysisLinkHoveredEvents_);return brightenedEvents;},applyToEventSelectionStates(model){this.appliedToModel_=model;const dimmedEvents=this.dimmedEvents_;if(model){const newDefaultState=(dimmedEvents.length?SelectionState.DIMMED0:SelectionState.NONE);const currentDefaultState=tr.b.getFirstElement(model.getDescendantEvents()).selectionState;if(currentDefaultState!==newDefaultState){for(const e of model.getDescendantEvents()){e.selectionState=newDefaultState;}}}
-let score;for(const e of dimmedEvents){score=0;if(this.findMatches_.contains(e)){score++;}
-if(this.analysisViewRelatedEvents_.contains(e)){score++;}
-e.selectionState=SelectionState.getFromDimmingLevel(score);}
-for(const e of this.brightenedEvents_){score=0;if(this.selection_.contains(e)){score++;}
-if(this.analysisLinkHoveredEvents_.contains(e)){score++;}
-e.selectionState=SelectionState.getFromBrighteningLevel(score);}},transferModelOwnershipToClone(that){if(!this.appliedToModel_){throw new Error('Not applied');}
+this.analysisLinkHoveredEvents_=analysisLinkHoveredEvents;},get isAppliedToModel(){return this.appliedToModel_!==undefined;},get viewSpecificBrushingStates(){return this.viewSpecificBrushingStates_;},set viewSpecificBrushingStates(viewSpecificBrushingStates){this.viewSpecificBrushingStates_=viewSpecificBrushingStates;},get defaultState_(){const standoutEventExists=(this.analysisLinkHoveredEvents_.length>0||this.analysisViewRelatedEvents_.length>0||this.findMatches_.length>0);return(standoutEventExists?SelectionState.DIMMED0:SelectionState.NONE);},get brightenedEvents_(){const brightenedEvents=new EventSet();brightenedEvents.addEventSet(this.findMatches);brightenedEvents.addEventSet(this.analysisViewRelatedEvents_);brightenedEvents.addEventSet(this.selection_);brightenedEvents.addEventSet(this.analysisLinkHoveredEvents_);return brightenedEvents;},applyToEventSelectionStates(model){this.appliedToModel_=model;if(model){const newDefaultState=this.defaultState_;const currentDefaultState=tr.b.getFirstElement(model.getDescendantEvents()).selectionState;if(currentDefaultState!==newDefaultState){for(const e of model.getDescendantEvents()){e.selectionState=newDefaultState;}}}
+let level;for(const e of this.brightenedEvents_){level=0;if(this.analysisViewRelatedEvents_.contains(e)||this.findMatches_.contains(e)){level++;}
+if(this.analysisLinkHoveredEvents_.contains(e)){level++;}
+if(this.selection_.contains(e)){level++;}
+e.selectionState=SelectionState.getFromBrighteningLevel(level);}},transferModelOwnershipToClone(that){if(!this.appliedToModel_){throw new Error('Not applied');}
that.appliedToModel_=this.appliedToModel_;this.appliedToModel_=undefined;},unapplyFromEventSelectionStates(){if(!this.appliedToModel_){throw new Error('Not applied');}
-const model=this.appliedToModel_;this.appliedToModel_=undefined;const dimmedEvents=this.dimmedEvents_;const defaultState=(dimmedEvents.length?SelectionState.DIMMED0:SelectionState.NONE);for(const e of this.brightenedEvents_){e.selectionState=defaultState;}
-for(const e of dimmedEvents){e.selectionState=defaultState;}
+const model=this.appliedToModel_;this.appliedToModel_=undefined;const defaultState=this.defaultState_;for(const e of this.brightenedEvents_){e.selectionState=defaultState;}
return defaultState;}};return{BrushingState,};});'use strict';tr.exportTo('tr.ui.b',function(){function Animation(){}
Animation.prototype={canTakeOverFor(existingAnimation){throw new Error('Not implemented');},takeOverFor(existingAnimation,newStartTimestamp,target){throw new Error('Not implemented');},start(timestamp,target){throw new Error('Not implemented');},didStopEarly(timestamp,target,willBeTakenOverByAnotherAnimation){},tick(timestamp,target){throw new Error('Not implemented');}};return{Animation,};});'use strict';tr.exportTo('tr.ui.b',function(){function AnimationController(){tr.b.EventTarget.call(this);this.target_=undefined;this.activeAnimation_=undefined;this.tickScheduled_=false;}
AnimationController.prototype={__proto__:tr.b.EventTarget.prototype,get target(){return this.target_;},set target(target){if(this.activeAnimation_){throw new Error('Cannot change target while animation is running.');}
@@ -6967,6 +7120,9 @@ merge(other){const result=new RunningStatistics();result.count_=this.count_+othe
(this.count*other.count*deltaMean*deltaMean/result.count);if(this.meanlogs_===undefined||other.meanlogs_===undefined){result.meanlogs_=undefined;}else{result.meanlogs_=(this.count*this.meanlogs_+
other.count*other.meanlogs_)/result.count;}}
return result;}
+truncate(unit){this.max_=unit.truncate(this.max_);if(this.meanlogs_!==undefined){const formatted=unit.format(this.geometricMean);let lo=1;let hi=16;while(lo<hi-1){const digits=parseInt((lo+hi)/2);const test=tr.b.math.truncate(this.meanlogs_,digits);if(formatted===unit.format(Math.exp(test))){hi=digits;}else{lo=digits;}}
+const test=tr.b.math.truncate(this.meanlogs_,lo);if(formatted===unit.format(Math.exp(test))){this.meanlogs_=test;}else{this.meanlogs_=tr.b.math.truncate(this.meanlogs_,hi);}}
+this.mean_=unit.truncate(this.mean_);this.min_=unit.truncate(this.min_);this.sum_=unit.truncate(this.sum_);this.variance_=unit.truncate(this.variance_);}
asDict(){if(!this.count){return[];}
return[this.count_,this.max_,this.meanlogs_,this.mean_,this.min_,this.sum_,this.variance_,];}
static fromDict(dict){const result=new RunningStatistics();if(dict.length!==7){return result;}
@@ -6986,9 +7142,16 @@ asDict(){const result={type:this.constructor.name};if(this.guid_!==undefined){re
this.asDictInto_(result);return result;}
asDictInto_(d){throw new Error('Abstract virtual method: subclasses must override '+'this method if they override canAddDiagnostic');}
static fromDict(d){const typeInfo=Diagnostic.findTypeInfoWithName(d.type);if(!typeInfo){throw new Error('Unrecognized diagnostic type: '+d.type);}
-const diagnostic=typeInfo.constructor.fromDict(d);if(d.guid!==undefined)diagnostic.guid=d.guid;return diagnostic;}}
-const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Diagnostic;tr.b.decorateExtensionRegistry(Diagnostic,options);Diagnostic.addEventListener('will-register',function(e){const constructor=e.typeInfo.constructor;if(!(constructor.fromDict instanceof Function)||(constructor.fromDict===Diagnostic.fromDict)||(constructor.fromDict.length!==1)){throw new Error('Diagnostics must define fromDict(d)');}});return{Diagnostic,};});'use strict';tr.exportTo('tr.v.d',function(){class Breakdown extends tr.v.d.Diagnostic{constructor(){super();this.values_=new Map();this.colorScheme=undefined;}
+const diagnostic=typeInfo.constructor.fromDict(d);if(d.guid!==undefined)diagnostic.guid=d.guid;return diagnostic;}
+static deserialize(type,d,deserializer){const typeInfo=Diagnostic.findTypeInfoWithName(type);if(!typeInfo){throw new Error('Unrecognized diagnostic type: '+type);}
+return typeInfo.constructor.deserialize(d,deserializer);}}
+const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Diagnostic;tr.b.decorateExtensionRegistry(Diagnostic,options);Diagnostic.addEventListener('will-register',function(e){const constructor=e.typeInfo.constructor;if(!(constructor.deserialize instanceof Function)||(constructor.deserialize===Diagnostic.deserialize)||(constructor.deserialize.length!==2)){throw new Error(`Please define ${constructor.name}.deserialize(data, deserializer)`);}
+if(!(constructor.fromDict instanceof Function)||(constructor.fromDict===Diagnostic.fromDict)||(constructor.fromDict.length!==1)){throw new Error(`Please define ${constructor.name}.fromDict(d)`);}
+if(!(constructor.prototype.serialize instanceof Function)||(constructor.prototype.serialize===Diagnostic.prototype.serialize)||(constructor.prototype.serialize.length!==1)){throw new Error(`Please define ${constructor.name}.serialize(serializer)`);}});return{Diagnostic,};});'use strict';tr.exportTo('tr.v.d',function(){class Breakdown extends tr.v.d.Diagnostic{constructor(){super();this.values_=new Map();this.colorScheme='';}
+truncate(unit){for(const[name,value]of this){this.values_.set(name,unit.truncate(value));}}
clone(){const clone=new Breakdown();clone.colorScheme=this.colorScheme;clone.addDiagnostic(this);return clone;}
+equals(other){if(this.colorScheme!==other.colorScheme)return false;if(this.values_.size!==other.values_.size)return false;for(const[k,v]of this){if(v!==other.get(k))return false;}
+return true;}
canAddDiagnostic(otherDiagnostic){return((otherDiagnostic instanceof Breakdown)&&(otherDiagnostic.colorScheme===this.colorScheme));}
addDiagnostic(otherDiagnostic){for(const[name,value]of otherDiagnostic){this.set(name,this.get(name)+value);}
return this;}
@@ -6996,15 +7159,20 @@ set(name,value){if(typeof name!=='string'||typeof value!=='number'){throw new Er
this.values_.set(name,value);}
get(name){return this.values_.get(name)||0;}*[Symbol.iterator](){for(const pair of this.values_){yield pair;}}
get size(){return this.values_.size;}
+serialize(serializer){const keys=[...this.values_.keys()];keys.sort();return[serializer.getOrAllocateId(this.colorScheme),serializer.getOrAllocateId(keys.map(k=>serializer.getOrAllocateId(k))),...keys.map(k=>this.get(k)),];}
asDictInto_(d){d.values={};for(const[name,value]of this){d.values[name]=tr.b.numberToJson(value);}
if(this.colorScheme){d.colorScheme=this.colorScheme;}}
static fromEntries(entries){const breakdown=new Breakdown();for(const[name,value]of entries){breakdown.set(name,value);}
return breakdown;}
+static deserialize(data,deserializer){const breakdown=new Breakdown();breakdown.colorScheme=deserializer.getObject(data[0]);const keys=deserializer.getObject(data[1]);for(let i=0;i<keys.length;++i){breakdown.set(deserializer.getObject(keys[i]),tr.b.numberFromJson(data[i+2]));}
+return breakdown;}
static fromDict(d){const breakdown=new Breakdown();for(const[name,value]of Object.entries(d.values)){breakdown.set(name,tr.b.numberFromJson(value));}
if(d.colorScheme){breakdown.colorScheme=d.colorScheme;}
return breakdown;}}
tr.v.d.Diagnostic.register(Breakdown,{elementName:'tr-v-ui-breakdown-span'});return{Breakdown,};});'use strict';tr.exportTo('tr.v.d',function(){class CollectedRelatedEventSet extends tr.v.d.Diagnostic{constructor(){super();this.eventSetsByCanonicalUrl_=new Map();}
asDictInto_(d){d.events={};for(const[canonicalUrl,eventSet]of this){d.events[canonicalUrl]=[];for(const event of eventSet){d.events[canonicalUrl].push({stableId:event.stableId,title:event.title,start:event.start,duration:event.duration});}}}
+static deserialize(events,deserializer){return CollectedRelatedEventSet.fromDict({events});}
+serialize(serializer){const d={};this.asDictInto(d);return d.events;}
static fromDict(d){const result=new CollectedRelatedEventSet();for(const[canonicalUrl,events]of Object.entries(d.events)){result.eventSetsByCanonicalUrl_.set(canonicalUrl,events.map(e=>new tr.v.d.EventRef(e)));}
return result;}
get size(){return this.eventSetsByCanonicalUrl_.size;}
@@ -7016,6 +7184,8 @@ addDiagnostic(otherDiagnostic){if(otherDiagnostic instanceof tr.v.d.CollectedRel
return;}
if(!otherDiagnostic.canonicalUrl)return;this.addEventSetForCanonicalUrl(otherDiagnostic.canonicalUrl,otherDiagnostic);}}
tr.v.d.Diagnostic.register(CollectedRelatedEventSet,{elementName:'tr-v-ui-collected-related-event-set-span'});return{CollectedRelatedEventSet,};});'use strict';tr.exportTo('tr.v.d',function(){class DateRange extends tr.v.d.Diagnostic{constructor(ms){super();this.range_=new tr.b.math.Range();this.range_.addValue(ms);}
+get minTimestamp(){return this.range_.min;}
+get maxTimestamp(){return this.range_.max;}
get minDate(){return new Date(this.range_.min);}
get maxDate(){return new Date(this.range_.max);}
get durationMs(){return this.range_.duration;}
@@ -7024,7 +7194,10 @@ equals(other){if(!(other instanceof DateRange))return false;return this.range_.e
canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof DateRange;}
addDiagnostic(other){this.range_.addRange(other.range_);}
toString(){const minDate=tr.b.formatDate(this.minDate);if(this.durationMs===0)return minDate;const maxDate=tr.b.formatDate(this.maxDate);return`${minDate} - ${maxDate}`;}
+serialize(serializer){if(this.durationMs===0)return this.range_.min;return[this.range_.min,this.range_.max];}
asDictInto_(d){d.min=this.range_.min;if(this.durationMs===0)return;d.max=this.range_.max;}
+static deserialize(data,deserializer){if(data instanceof Array){const dr=new DateRange(data[0]);dr.range_.addValue(data[1]);return dr;}
+return new DateRange(data);}
static fromDict(d){const dateRange=new DateRange(d.min);if(d.max!==undefined)dateRange.range_.addValue(d.max);return dateRange;}}
tr.v.d.Diagnostic.register(DateRange,{elementName:'tr-v-ui-date-range-span'});return{DateRange,};});'use strict';tr.exportTo('tr.v.d',function(){class DiagnosticRef{constructor(guid){this.guid=guid;}
asDict(){return this.guid;}
@@ -7042,7 +7215,10 @@ return true;}
get hashKey(){if(this.has_objects_)return undefined;if(this.hash_key_!==undefined){return this.hash_key_;}
let key='';for(const value of Array.from(this.values_.values()).sort()){key+=value;}
this.hash_key_=key;return key;}
+serialize(serializer){const i=[...this].map(x=>serializer.getOrAllocateId(x));return(i.length===1)?i[0]:i;}
asDictInto_(d){d.values=Array.from(this);}
+static deserialize(data,deserializer){if(!(data instanceof Array)){data=[data];}
+return new GenericSet(data.map(datum=>deserializer.getObject(datum)));}
static fromDict(d){return new GenericSet(d.values);}
clone(){return new GenericSet(this.values_);}
canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof GenericSet;}
@@ -7050,98 +7226,55 @@ addDiagnostic(otherDiagnostic){const jsons=new Set();for(const value of this){if
for(const value of otherDiagnostic){if(typeof value==='object'){if(jsons.has(stableStringify(value))){continue;}
this.has_objects_=true;}
this.values_.add(value);}}}
-tr.v.d.Diagnostic.register(GenericSet,{elementName:'tr-v-ui-generic-set-span'});return{GenericSet,};});'use strict';tr.exportTo('tr.v.d',function(){class GroupingPath extends tr.v.d.Diagnostic{constructor(groupingPath){super();this.groupingPath_=groupingPath;}
-clone(){return new GroupingPath(Array.from(this.groupingPath_));}
-addToHistogram(hist){hist.diagnostics.set(tr.v.d.RESERVED_NAMES.GROUPING_PATH,this);}
-static getFromHistogram(hist){return hist.diagnostics.get(tr.v.d.RESERVED_NAMES.GROUPING_PATH);}
-equals(other){return 0===tr.b.compareArrays(this.groupingPath_,other.groupingPath_,(x,y)=>x.localeCompare(y));}
-asDictInto_(d){d.groupingPath=this.groupingPath_;}
-static fromDict(d){return new GroupingPath(d.groupingPath);}}
-tr.v.d.Diagnostic.register(GroupingPath);return{GroupingPath,};});'use strict';tr.exportTo('tr.v.d',function(){class EventRef{constructor(event){this.stableId=event.stableId;this.title=event.title;this.start=event.start;this.duration=event.duration;this.end=this.start+this.duration;this.guid=tr.b.GUID.allocateSimple();}}
+tr.v.d.Diagnostic.register(GenericSet,{elementName:'tr-v-ui-generic-set-span'});return{GenericSet,};});'use strict';tr.exportTo('tr.v.d',function(){class EventRef{constructor(event){this.stableId=event.stableId;this.title=event.title;this.start=event.start;this.duration=event.duration;this.end=this.start+this.duration;this.guid=tr.b.GUID.allocateSimple();}}
return{EventRef,};});'use strict';tr.exportTo('tr.v.d',function(){class RelatedEventSet extends tr.v.d.Diagnostic{constructor(opt_events){super();this.eventsByStableId_=new Map();this.canonicalUrl_=undefined;if(opt_events){if(opt_events instanceof tr.model.EventSet||opt_events instanceof Array){for(const event of opt_events){this.add(event);}}else{this.add(opt_events);}}}
clone(){const clone=new tr.v.d.CollectedRelatedEventSet();clone.addDiagnostic(this);return clone;}
+equals(other){if(this.length!==other.length)return false;for(const event of this){if(!other.has(event))return false;}
+return true;}
add(event){this.eventsByStableId_.set(event.stableId,event);}
has(event){return this.eventsByStableId_.has(event.stableId);}
get length(){return this.eventsByStableId_.size;}*[Symbol.iterator](){for(const event of this.eventsByStableId_.values()){yield event;}}
get canonicalUrl(){return this.canonicalUrl_;}
resolve(model,opt_required){for(const[stableId,value]of this.eventsByStableId_){if(!(value instanceof tr.v.d.EventRef))continue;const event=model.getEventByStableId(stableId);if(event instanceof tr.model.Event){this.eventsByStableId_.set(stableId,event);}else if(opt_required){throw new Error('Unable to find Event '+stableId);}}}
-asDictInto_(d){d.events=[];for(const event of this){d.events.push({stableId:event.stableId,title:event.title,start:event.start,duration:event.duration});}}
+serialize(serializer){return[...this].map(event=>[event.stableId,serializer.getOrAllocateId(event.title),event.start,event.duration,]);}
+asDictInto_(d){d.events=[];for(const event of this){d.events.push({stableId:event.stableId,title:event.title,start:tr.b.Unit.byName.timeStampInMs.truncate(event.start),duration:tr.b.Unit.byName.timeDurationInMs.truncate(event.duration),});}}
+static deserialize(data,deserializer){return new RelatedEventSet(data.map(event=>new tr.v.d.EventRef({stableId:event[0],title:deserializer.getObject(event[1]),start:event[2],duration:event[3],})));}
static fromDict(d){return new RelatedEventSet(d.events.map(event=>new tr.v.d.EventRef(event)));}}
-tr.v.d.Diagnostic.register(RelatedEventSet,{elementName:'tr-v-ui-related-event-set-span'});return{RelatedEventSet,};});'use strict';tr.exportTo('tr.v.d',function(){function HistogramRef(guid){this.guid=guid;}
-return{HistogramRef};});'use strict';tr.exportTo('tr.v.d',function(){class RelatedHistogramMap extends tr.v.d.Diagnostic{constructor(){super();this.histogramsByName_=new Map();}
-canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof RelatedHistogramMap;}
-addDiagnostic(otherDiagnostic){}
-mergeRelationships(otherDiagnostic,parentHist,otherParentHist){const parentGroupingPath=tr.v.d.GroupingPath.getFromHistogram(parentHist);for(const[name,otherRelatedHist]of otherDiagnostic){const mergedTo=otherRelatedHist.diagnostics.get(tr.v.d.RESERVED_NAMES.MERGED_TO);if(mergedTo===undefined)continue;for(const relatedHist of mergedTo.histogramsByName_.values()){const relatedGroupingPath=tr.v.d.GroupingPath.getFromHistogram(relatedHist);if(relatedGroupingPath===undefined)continue;if(!parentGroupingPath.equals(relatedGroupingPath))continue;this.set(name,relatedHist);}}}
-get(name){return this.histogramsByName_.get(name);}
-set(name,hist){if(!(hist instanceof tr.v.Histogram)&&!(hist instanceof tr.v.d.HistogramRef)){throw new Error('Must be instanceof Histogram or HistogramRef: '+
-hist);}
-this.histogramsByName_.set(name,hist);}
-add(hist){this.set(hist.name,hist);}
-get length(){return this.histogramsByName_.size;}*[Symbol.iterator](){for(const pair of this.histogramsByName_){yield pair;}}
-resolve(histograms,opt_required){for(const[name,value]of this){if(!(value instanceof tr.v.d.HistogramRef))continue;const guid=value.guid;const hist=histograms.lookupHistogram(guid);if(hist instanceof tr.v.Histogram){this.histogramsByName_.set(name,hist);}else if(opt_required){throw new Error('Unable to find Histogram '+guid);}}}
-asDictInto_(d){d.values={};for(const[name,hist]of this){d.values[name]=hist.guid;}}
-static fromDict(d){const map=new RelatedHistogramMap();for(const[name,guid]of Object.entries(d.values)){map.set(name,new tr.v.d.HistogramRef(guid));}
-return map;}}
-tr.v.d.Diagnostic.register(RelatedHistogramMap,{elementName:'tr-v-ui-related-histogram-map-span'});return{RelatedHistogramMap,};});'use strict';tr.exportTo('tr.v.d',function(){const COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER='ChromeUserFriendlyCategory';class RelatedHistogramBreakdown extends tr.v.d.RelatedHistogramMap{constructor(){super();this.colorScheme=undefined;}
-clone(){const clone=new RelatedHistogramBreakdown();clone.colorScheme=this.colorScheme;return clone;}
-canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof RelatedHistogramBreakdown&&otherDiagnostic.colorScheme===this.colorScheme;}
-set(name,hist){if(!(hist instanceof tr.v.d.HistogramRef)){if(!(hist instanceof tr.v.Histogram)){throw new Error('RelatedHistogramBreakdown can only contain Histograms');}
-if((this.length>0)&&(hist.unit!==tr.b.getFirstElement(this)[1].unit)){throw new Error('Units mismatch',tr.b.getFirstElement(this)[1].unit,hist.unit);}}
-tr.v.d.RelatedHistogramMap.prototype.set.call(this,name,hist);}
-asDictInto_(d){tr.v.d.RelatedHistogramMap.prototype.asDictInto_.call(this,d);if(this.colorScheme)d.colorScheme=this.colorScheme;}
-static fromDict(d){const diagnostic=new RelatedHistogramBreakdown();for(const[name,guid]of Object.entries(d.values)){diagnostic.set(name,new tr.v.d.HistogramRef(guid));}
-if(d.colorScheme)diagnostic.colorScheme=d.colorScheme;return diagnostic;}
-static buildFromEvents(histograms,namePrefix,events,categoryForEvent,unit,opt_sampleForEvent,opt_binBoundaries,opt_this){const sampleForEvent=opt_sampleForEvent||((event)=>event.cpuSelfTime);const diagnostic=new RelatedHistogramBreakdown();for(const event of events){const sample=sampleForEvent.call(opt_this,event);if(sample===undefined)continue;const eventCategory=categoryForEvent.call(opt_this,event);let hist=diagnostic.get(eventCategory);if(hist===undefined){hist=new tr.v.Histogram(namePrefix+eventCategory,unit,opt_binBoundaries);histograms.addHistogram(hist);diagnostic.set(eventCategory,hist);}
-hist.addSample(sample,{relatedEvents:new tr.v.d.RelatedEventSet([event])});}
-return diagnostic;}}
-tr.v.d.Diagnostic.register(RelatedHistogramBreakdown,{elementName:'tr-v-ui-breakdown-span'});return{COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER,RelatedHistogramBreakdown,};});'use strict';tr.exportTo('tr.v.d',function(){class RelatedNameMap extends tr.v.d.Diagnostic{constructor(opt_info){super();this.map_=new Map();}
+tr.v.d.Diagnostic.register(RelatedEventSet,{elementName:'tr-v-ui-related-event-set-span'});return{RelatedEventSet,};});'use strict';tr.exportTo('tr.v.d',function(){class RelatedNameMap extends tr.v.d.Diagnostic{constructor(opt_info){super();this.map_=new Map();if(opt_info){for(const[key,name]of Object.entries(opt_info)){this.set(key,name);}}}
clone(){const clone=new RelatedNameMap();clone.addDiagnostic(this);return clone;}
equals(other){if(!(other instanceof RelatedNameMap))return false;const keys1=new Set(this.map_.keys());const keys2=new Set(other.map_.keys());if(!tr.b.setsEqual(keys1,keys2))return false;for(const[key,name]of this){if(name!==other.get(key))return false;}
return true;}
canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof RelatedNameMap;}
addDiagnostic(otherDiagnostic){for(const[key,name]of otherDiagnostic){const existing=this.get(key);if(existing===undefined){this.set(key,name);}else if(existing!==name){throw new Error('Histogram names differ: '+`"${existing}" != "${name}"`);}}}
+serialize(serializer){const keys=[...this.map_.keys()];keys.sort();const names=keys.map(k=>serializer.getOrAllocateId(this.get(k)));const keysId=serializer.getOrAllocateId(keys.map(k=>serializer.getOrAllocateId(k)));return[keysId,...names];}
asDictInto_(d){d.names={};for(const[key,name]of this)d.names[key]=name;}
set(key,name){this.map_.set(key,name);}
get(key){return this.map_.get(key);}*[Symbol.iterator](){for(const pair of this.map_)yield pair;}*values(){for(const value of this.map_.values())yield value;}
static fromEntries(entries){const names=new RelatedNameMap();for(const[key,name]of entries){names.set(key,name);}
return names;}
+static deserialize(data,deserializer){const names=new RelatedNameMap();const keys=deserializer.getObject(data[0]);for(let i=0;i<keys.length;++i){names.set(deserializer.getObject(keys[i]),deserializer.getObject(data[i+1]));}
+return names;}
static fromDict(d){return RelatedNameMap.fromEntries(Object.entries(d.names||{}));}}
tr.v.d.Diagnostic.register(RelatedNameMap,{elementName:'tr-v-ui-related-name-map-span',});return{RelatedNameMap,};});'use strict';tr.exportTo('tr.v.d',function(){class Scalar extends tr.v.d.Diagnostic{constructor(value){super();if(!(value instanceof tr.b.Scalar)){throw new Error('expected Scalar');}
this.value=value;}
clone(){return new Scalar(this.value);}
+serialize(serializer){return this.value.asDict();}
asDictInto_(d){d.value=this.value.asDict();}
+static deserialize(value,deserializer){return Scalar.fromDict({value});}
static fromDict(d){return new Scalar(tr.b.Scalar.fromDict(d.value));}}
-tr.v.d.Diagnostic.register(Scalar,{elementName:'tr-v-ui-scalar-diagnostic-span'});return{Scalar,};});'use strict';tr.exportTo('tr.v.d',function(){class TagMap extends tr.v.d.Diagnostic{constructor(opt_info){super();this.tagsToStoryNames_=new Map();if(opt_info){for(const[tag,storyDisplayNames]of Object.entries(opt_info.tagsToStoryNames||{})){this.tagsToStoryNames.set(tag,new Set(storyDisplayNames));}}}
-clone(){const clone=new TagMap();clone.addDiagnostic(this);return clone;}
-addToHistogram(hist){hist.diagnostics.set(tr.v.d.RESERVED_NAMES.TAG_MAP,this);}
-equals(other){if(!(other instanceof TagMap))return false;const keys1=new Set(this.tagsToStoryNames.keys());const keys2=new Set(other.tagsToStoryNames.keys());if(!tr.b.setsEqual(keys1,keys2)){return false;}
-for(const key of keys1){if(!tr.b.setsEqual(this.tagsToStoryNames.get(key),other.tagsToStoryNames.get(key))){return false;}}
-return true;}
-canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof TagMap;}
-addDiagnostic(otherDiagnostic){for(const[name,storyDisplayNames]of
-otherDiagnostic.tagsToStoryNames){if(!this.tagsToStoryNames.has(name)){this.tagsToStoryNames.set(name,new Set());}
-for(const t of storyDisplayNames){this.tagsToStoryNames.get(name).add(t);}}
-return this;}
-asDictInto_(d){d.tagsToStoryNames={};for(const[name,value]of this.tagsToStoryNames){d.tagsToStoryNames[name]=Array.from(value);}}
-get tagsToStoryNames(){return this.tagsToStoryNames_;}
-static fromDict(d){const info=new TagMap();for(const[name,values]of
-Object.entries(d.tagsToStoryNames||{})){info.tagsToStoryNames.set(name,new Set(values));}
-return info;}}
-tr.v.d.Diagnostic.register(TagMap,{elementName:'tr-v-ui-tag-map-span'});return{TagMap,};});'use strict';tr.exportTo('tr.v.d',function(){class UnmergeableDiagnosticSet extends tr.v.d.Diagnostic{constructor(diagnostics){super();this._diagnostics=diagnostics;}
+tr.v.d.Diagnostic.register(Scalar,{elementName:'tr-v-ui-scalar-diagnostic-span'});return{Scalar,};});'use strict';tr.exportTo('tr.v.d',function(){class UnmergeableDiagnosticSet extends tr.v.d.Diagnostic{constructor(diagnostics){super();this._diagnostics=diagnostics;}
clone(){const clone=new tr.v.d.UnmergeableDiagnosticSet();clone.addDiagnostic(this);return clone;}
canAddDiagnostic(otherDiagnostic){return true;}
addDiagnostic(otherDiagnostic){if(otherDiagnostic instanceof UnmergeableDiagnosticSet){for(const subOtherDiagnostic of otherDiagnostic){const clone=subOtherDiagnostic.clone();this.addDiagnostic(clone);}
return;}
for(let i=0;i<this._diagnostics.length;++i){if(this._diagnostics[i].canAddDiagnostic(otherDiagnostic)){this._diagnostics[i].addDiagnostic(otherDiagnostic);return;}}
const clone=otherDiagnostic.clone();this._diagnostics.push(clone);}
-mergeRelationships(otherDiagnostic,parentHist,otherParentHist){if(otherDiagnostic instanceof UnmergeableDiagnosticSet){for(const subDiagnostic of otherDiagnostic){this.mergeRelationships(subDiagnostic,parentHist,otherParentHist);}
-return;}
-for(const subDiagnostic of this){if(!(subDiagnostic instanceof tr.v.d.RelatedHistogramMap)&&!(subDiagnostic instanceof tr.v.d.RelatedHistogramBreakdown)){continue;}
-subDiagnostic.mergeRelationships(otherDiagnostic,parentHist,otherParentHist);}}
get length(){return this._diagnostics.length;}*[Symbol.iterator](){for(const diagnostic of this._diagnostics)yield diagnostic;}
asDictInto_(d){d.diagnostics=this._diagnostics.map(d=>d.asDictOrReference());}
+static deserialize(data,deserializer){return new UnmergeableDiagnosticSet(d.map(i=>deserializer.getDiagnostic(i).diagnostic));}
+serialize(serializer){return this._diagnostics.map(d=>serializer.getOrAllocateDiagnosticId('',d));}
static fromDict(d){return new UnmergeableDiagnosticSet(d.diagnostics.map(d=>((typeof d==='string')?new tr.v.d.DiagnosticRef(d):tr.v.d.Diagnostic.fromDict(d))));}}
-tr.v.d.Diagnostic.register(UnmergeableDiagnosticSet,{elementName:'tr-v-ui-unmergeable-diagnostic-set-span'});return{UnmergeableDiagnosticSet,};});'use strict';tr.exportTo('tr.v.d',function(){const RESERVED_INFOS={ANGLE_REVISIONS:{name:'angleRevisions',type:tr.v.d.GenericSet},ARCHITECTURES:{name:'architectures',type:tr.v.d.GenericSet},BENCHMARKS:{name:'benchmarks',type:tr.v.d.GenericSet},BENCHMARK_START:{name:'benchmarkStart',type:tr.v.d.DateRange},BENCHMARK_DESCRIPTIONS:{name:'benchmarkDescriptions',type:tr.v.d.GenericSet},BOTS:{name:'bots',type:tr.v.d.GenericSet},BUG_COMPONENTS:{name:'bugComponents',type:tr.v.d.GenericSet},BUILDS:{name:'builds',type:tr.v.d.GenericSet},CATAPULT_REVISIONS:{name:'catapultRevisions',type:tr.v.d.GenericSet},CHROMIUM_COMMIT_POSITIONS:{name:'chromiumCommitPositions',type:tr.v.d.GenericSet},CHROMIUM_REVISIONS:{name:'chromiumRevisions',type:tr.v.d.GenericSet},DEVICE_IDS:{name:'deviceIds',type:tr.v.d.GenericSet},DOCUMENTATION_URLS:{name:'documentationUrls',type:tr.v.d.GenericSet},FUCHSIA_GARNET_REVISIONS:{name:'fuchsiaGarnetRevisions',type:tr.v.d.GenericSet},FUCHSIA_PERIDOT_REVISIONS:{name:'fuchsiaPeridotRevisions',type:tr.v.d.GenericSet},FUCHSIA_TOPAZ_REVISIONS:{name:'fuchsiaTopazRevisions',type:tr.v.d.GenericSet},FUCHSIA_ZIRCON_REVISIONS:{name:'fuchsiaZirconRevisions',type:tr.v.d.GenericSet},GPUS:{name:'gpus',type:tr.v.d.GenericSet},GROUPING_PATH:{name:'groupingPath',type:tr.v.d.GroupingPath},IS_REFERENCE_BUILD:{name:'isReferenceBuild',type:tr.v.d.GenericSet},LABELS:{name:'labels',type:tr.v.d.GenericSet},LOG_URLS:{name:'logUrls',type:tr.v.d.GenericSet},MASTERS:{name:'masters',type:tr.v.d.GenericSet},MEMORY_AMOUNTS:{name:'memoryAmounts',type:tr.v.d.GenericSet},MERGED_FROM:{name:'mergedFrom',type:tr.v.d.RelatedHistogramMap},MERGED_TO:{name:'mergedTo',type:tr.v.d.RelatedHistogramMap},OS_NAMES:{name:'osNames',type:tr.v.d.GenericSet},OS_VERSIONS:{name:'osVersions',type:tr.v.d.GenericSet},OWNERS:{name:'owners',type:tr.v.d.GenericSet},POINT_ID:{name:'pointId',type:tr.v.d.GenericSet},PRODUCT_VERSIONS:{name:'productVersions',type:tr.v.d.GenericSet},RELATED_NAMES:{name:'relatedNames',type:tr.v.d.GenericSet},REVISION_TIMESTAMPS:{name:'revisionTimestamps',type:tr.v.d.DateRange},SKIA_REVISIONS:{name:'skiaRevisions',type:tr.v.d.GenericSet},STORIES:{name:'stories',type:tr.v.d.GenericSet},STORYSET_REPEATS:{name:'storysetRepeats',type:tr.v.d.GenericSet},STORY_TAGS:{name:'storyTags',type:tr.v.d.GenericSet},SUMMARY_KEYS:{name:'summaryKeys',type:tr.v.d.GenericSet},TAG_MAP:{name:'tagmap',type:tr.v.d.TagMap},TEST_PATH:{name:'testPath',type:tr.v.d.GenericSet},TRACE_START:{name:'traceStart',type:tr.v.d.DateRange},TRACE_URLS:{name:'traceUrls',type:tr.v.d.GenericSet},V8_COMMIT_POSITIONS:{name:'v8CommitPositions',type:tr.v.d.DateRange},V8_REVISIONS:{name:'v8Revisions',type:tr.v.d.GenericSet},WEBRTC_REVISIONS:{name:'webrtcRevisions',type:tr.v.d.GenericSet},};const RESERVED_NAMES={};const RESERVED_NAMES_TO_TYPES=new Map();for(const[codename,info]of Object.entries(RESERVED_INFOS)){RESERVED_NAMES[codename]=info.name;if(RESERVED_NAMES_TO_TYPES.has(info.name)){throw new Error(`Duplicate reserved name "${info.name}"`);}
+tr.v.d.Diagnostic.register(UnmergeableDiagnosticSet,{elementName:'tr-v-ui-unmergeable-diagnostic-set-span'});return{UnmergeableDiagnosticSet,};});'use strict';tr.exportTo('tr.v.d',function(){const RESERVED_INFOS={ANGLE_REVISIONS:{name:'angleRevisions',type:tr.v.d.GenericSet},ARCHITECTURES:{name:'architectures',type:tr.v.d.GenericSet},BENCHMARKS:{name:'benchmarks',type:tr.v.d.GenericSet},BENCHMARK_START:{name:'benchmarkStart',type:tr.v.d.DateRange},BENCHMARK_DESCRIPTIONS:{name:'benchmarkDescriptions',type:tr.v.d.GenericSet},BOTS:{name:'bots',type:tr.v.d.GenericSet},BUG_COMPONENTS:{name:'bugComponents',type:tr.v.d.GenericSet},BUILDS:{name:'builds',type:tr.v.d.GenericSet},CATAPULT_REVISIONS:{name:'catapultRevisions',type:tr.v.d.GenericSet},CHROMIUM_COMMIT_POSITIONS:{name:'chromiumCommitPositions',type:tr.v.d.GenericSet},CHROMIUM_REVISIONS:{name:'chromiumRevisions',type:tr.v.d.GenericSet},DESCRIPTION:{name:'description',type:tr.v.d.GenericSet},DEVICE_IDS:{name:'deviceIds',type:tr.v.d.GenericSet},DOCUMENTATION_URLS:{name:'documentationUrls',type:tr.v.d.GenericSet},FUCHSIA_GARNET_REVISIONS:{name:'fuchsiaGarnetRevisions',type:tr.v.d.GenericSet},FUCHSIA_PERIDOT_REVISIONS:{name:'fuchsiaPeridotRevisions',type:tr.v.d.GenericSet},FUCHSIA_TOPAZ_REVISIONS:{name:'fuchsiaTopazRevisions',type:tr.v.d.GenericSet},FUCHSIA_ZIRCON_REVISIONS:{name:'fuchsiaZirconRevisions',type:tr.v.d.GenericSet},GPUS:{name:'gpus',type:tr.v.d.GenericSet},IS_REFERENCE_BUILD:{name:'isReferenceBuild',type:tr.v.d.GenericSet},LABELS:{name:'labels',type:tr.v.d.GenericSet},LOG_URLS:{name:'logUrls',type:tr.v.d.GenericSet},MASTERS:{name:'masters',type:tr.v.d.GenericSet},MEMORY_AMOUNTS:{name:'memoryAmounts',type:tr.v.d.GenericSet},OS_NAMES:{name:'osNames',type:tr.v.d.GenericSet},OS_VERSIONS:{name:'osVersions',type:tr.v.d.GenericSet},OWNERS:{name:'owners',type:tr.v.d.GenericSet},POINT_ID:{name:'pointId',type:tr.v.d.GenericSet},PRODUCT_VERSIONS:{name:'productVersions',type:tr.v.d.GenericSet},REVISION_TIMESTAMPS:{name:'revisionTimestamps',type:tr.v.d.DateRange},SKIA_REVISIONS:{name:'skiaRevisions',type:tr.v.d.GenericSet},STATISTICS_NAMES:{name:'statisticsNames',type:tr.v.d.GenericSet},STORIES:{name:'stories',type:tr.v.d.GenericSet},STORYSET_REPEATS:{name:'storysetRepeats',type:tr.v.d.GenericSet},STORY_TAGS:{name:'storyTags',type:tr.v.d.GenericSet},SUMMARY_KEYS:{name:'summaryKeys',type:tr.v.d.GenericSet},TEST_PATH:{name:'testPath',type:tr.v.d.GenericSet},TRACE_START:{name:'traceStart',type:tr.v.d.DateRange},TRACE_URLS:{name:'traceUrls',type:tr.v.d.GenericSet},V8_COMMIT_POSITIONS:{name:'v8CommitPositions',type:tr.v.d.DateRange},V8_REVISIONS:{name:'v8Revisions',type:tr.v.d.GenericSet},WEBRTC_REVISIONS:{name:'webrtcRevisions',type:tr.v.d.GenericSet},};const RESERVED_NAMES={};const RESERVED_NAMES_TO_TYPES=new Map();for(const[codename,info]of Object.entries(RESERVED_INFOS)){RESERVED_NAMES[codename]=info.name;if(RESERVED_NAMES_TO_TYPES.has(info.name)){throw new Error(`Duplicate reserved name "${info.name}"`);}
RESERVED_NAMES_TO_TYPES.set(info.name,info.type);}
const RESERVED_NAMES_SET=new Set(Object.values(RESERVED_NAMES));return{RESERVED_INFOS,RESERVED_NAMES,RESERVED_NAMES_SET,RESERVED_NAMES_TO_TYPES,};});'use strict';tr.exportTo('tr.v.d',function(){class DiagnosticMap extends Map{constructor(opt_allowReservedNames){super();if(opt_allowReservedNames===undefined){opt_allowReservedNames=true;}
this.allowReservedNames_=opt_allowReservedNames;}
@@ -7150,23 +7283,22 @@ if(!(diagnostic instanceof tr.v.d.Diagnostic)&&!(diagnostic instanceof tr.v.d.Di
if(!this.allowReservedNames_&&tr.v.d.RESERVED_NAMES_SET.has(name)&&!(diagnostic instanceof tr.v.d.UnmergeableDiagnosticSet)&&!(diagnostic instanceof tr.v.d.DiagnosticRef)){const type=tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);if(type&&!(diagnostic instanceof type)){throw new Error(`Diagnostics named "${name}" must be ${type.name}, `+`not ${diagnostic.constructor.name}`);}}
Map.prototype.set.call(this,name,diagnostic);}
delete(name){if(name===undefined)throw new Error('missing name');Map.prototype.delete.call(this,name);}
-addDicts(dict){for(const[name,diagnosticDict]of Object.entries(dict)){if(typeof diagnosticDict==='string'){this.set(name,new tr.v.d.DiagnosticRef(diagnosticDict));}else{this.set(name,tr.v.d.Diagnostic.fromDict(diagnosticDict));}}}
+deserializeAdd(data,deserializer){for(const id of data){const{name,diagnostic}=deserializer.getDiagnostic(id);this.set(name,diagnostic);}}
+addDicts(dict){for(const[name,diagnosticDict]of Object.entries(dict)){if(name==='tagmap')continue;if(typeof diagnosticDict==='string'){this.set(name,new tr.v.d.DiagnosticRef(diagnosticDict));}else if(diagnosticDict.type!=='RelatedHistogramMap'&&diagnosticDict.type!=='RelatedHistogramBreakdown'&&diagnosticDict.type!=='TagMap'){this.set(name,tr.v.d.Diagnostic.fromDict(diagnosticDict));}}}
resolveSharedDiagnostics(histograms,opt_required){for(const[name,value]of this){if(!(value instanceof tr.v.d.DiagnosticRef)){continue;}
const guid=value.guid;const diagnostic=histograms.lookupDiagnostic(guid);if(diagnostic instanceof tr.v.d.Diagnostic){this.set(name,diagnostic);}else if(opt_required){throw new Error('Unable to find shared Diagnostic '+guid);}}}
+serialize(serializer){const data=[];for(const[name,diagnostic]of this){data.push(serializer.getOrAllocateDiagnosticId(name,diagnostic));}
+return data;}
asDict(){const dict={};for(const[name,diagnostic]of this){dict[name]=diagnostic.asDictOrReference();}
return dict;}
+static deserialize(data,deserializer){const diagnostics=new DiagnosticMap();diagnostics.deserializeAdd(data,deserializer);return diagnostics;}
static fromDict(d){const diagnostics=new DiagnosticMap();diagnostics.addDicts(d);return diagnostics;}
-static fromObject(obj){const diagnostics=new DiagnosticMap();if(!(obj instanceof Map))obj=Object.entries(obj);for(const[name,diagnostic]of obj){diagnostics.set(name,diagnostic);}
+static fromObject(obj){const diagnostics=new DiagnosticMap();if(!(obj instanceof Map))obj=Object.entries(obj);for(const[name,diagnostic]of obj){if(!diagnostic)continue;diagnostics.set(name,diagnostic);}
return diagnostics;}
-addDiagnostics(other){for(const[name,otherDiagnostic]of other){if(name===tr.v.d.RESERVED_NAMES.MERGED_FROM||name===tr.v.d.RESERVED_NAMES.MERGED_TO||name===tr.v.d.RESERVED_NAMES.GROUPING_PATH){continue;}
-const myDiagnostic=this.get(name);if(myDiagnostic!==undefined&&myDiagnostic.canAddDiagnostic(otherDiagnostic)){myDiagnostic.addDiagnostic(otherDiagnostic);continue;}
+addDiagnostics(other){for(const[name,otherDiagnostic]of other){const myDiagnostic=this.get(name);if(myDiagnostic!==undefined&&myDiagnostic.canAddDiagnostic(otherDiagnostic)){myDiagnostic.addDiagnostic(otherDiagnostic);continue;}
const clone=otherDiagnostic.clone();if(myDiagnostic===undefined){this.set(name,clone);continue;}
-this.set(name,new tr.v.d.UnmergeableDiagnosticSet([myDiagnostic,clone]));}}
-mergeRelationships(parentHist){for(const[name,diagnostic]of this){if(!(diagnostic instanceof tr.v.d.RelatedHistogramMap)&&!(diagnostic instanceof tr.v.d.RelatedHistogramBreakdown)&&!(diagnostic instanceof tr.v.d.UnmergeableDiagnosticSet)){continue;}
-for(const[unusedName,otherHist]of
-this.get(tr.v.d.RESERVED_NAMES.MERGED_FROM)){const otherDiagnostic=otherHist.diagnostics.get(name);if(!(otherDiagnostic instanceof tr.v.d.RelatedHistogramMap)&&!(otherDiagnostic instanceof tr.v.d.RelatedHistogramBreakdown)&&!(otherDiagnostic instanceof tr.v.d.UnmergeableDiagnosticSet)){continue;}
-diagnostic.mergeRelationships(otherDiagnostic,parentHist,otherHist);}}}}
-return{DiagnosticMap,};});'use strict';tr.exportTo('tr.v',function(){const MAX_DIAGNOSTIC_MAPS=16;const DEFAULT_SAMPLE_VALUES_PER_BIN=10;const DEFAULT_REBINNED_COUNT=40;const DEFAULT_BOUNDARIES_FOR_UNIT=new Map();const DELTA=String.fromCharCode(916);const Z_SCORE_NAME='z-score';const P_VALUE_NAME='p-value';const U_STATISTIC_NAME='U';function percentToString(percent,opt_force3){if(percent<0||percent>1){throw new Error('percent must be in [0,1]');}
+this.set(name,new tr.v.d.UnmergeableDiagnosticSet([myDiagnostic,clone]));}}}
+return{DiagnosticMap};});'use strict';tr.exportTo('tr.v',function(){const MAX_DIAGNOSTIC_MAPS=16;const DEFAULT_SAMPLE_VALUES_PER_BIN=10;const DEFAULT_REBINNED_COUNT=40;const DEFAULT_BOUNDARIES_FOR_UNIT=new Map();const DEFAULT_ITERATION_FOR_BOOTSTRAP_RESAMPLING=500;const DELTA=String.fromCharCode(916);const Z_SCORE_NAME='z-score';const P_VALUE_NAME='p-value';const U_STATISTIC_NAME='U';function percentToString(percent,opt_force3){if(percent<0||percent>1){throw new Error('percent must be in [0,1]');}
if(percent===0)return'000';if(percent===1)return'100';let str=percent.toString();if(str[1]!=='.'){throw new Error('Unexpected percent');}
str=str+'0'.repeat(Math.max(4-str.length,0));if(str.length>4){if(opt_force3){str=str.slice(0,4);}else{str=str.slice(0,4)+'_'+str.slice(4);}}
return'0'+str.slice(2);}
@@ -7176,15 +7308,20 @@ addSample(value){this.count+=1;}
addDiagnosticMap(diagnostics){tr.b.math.Statistics.uniformlySampleStream(this.diagnosticMaps,this.count,diagnostics,MAX_DIAGNOSTIC_MAPS);}
addBin(other){if(!this.range.equals(other.range)){throw new Error('Merging incompatible Histogram bins.');}
tr.b.math.Statistics.mergeSampledStreams(this.diagnosticMaps,this.count,other.diagnosticMaps,other.count,MAX_DIAGNOSTIC_MAPS);this.count+=other.count;}
+deserialize(data,deserializer){if(!(data instanceof Array)){this.count=data;return;}
+this.count=data[0];for(const sample of data.slice(1)){if(!(sample instanceof Array))continue;this.diagnosticMaps.push(tr.v.d.DiagnosticMap.deserialize(sample.slice(1),deserializer));}}
fromDict(dict){this.count=dict[0];if(dict.length>1){for(const map of dict[1]){this.diagnosticMaps.push(tr.v.d.DiagnosticMap.fromDict(map));}}}
+serialize(serializer){if(!this.diagnosticMaps.length){return this.count;}
+return[this.count,...this.diagnosticMaps.map(d=>[undefined,...d.serialize(serializer)])];}
asDict(){if(!this.diagnosticMaps.length){return[this.count];}
return[this.count,this.diagnosticMaps.map(d=>d.asDict())];}}
-const DEFAULT_SUMMARY_OPTIONS=new Map([['avg',true],['count',true],['geometricMean',false],['max',true],['min',true],['nans',false],['std',true],['sum',true],]);class Histogram{constructor(name,unit,opt_binBoundaries){let binBoundaries=opt_binBoundaries;if(!binBoundaries){const baseUnit=unit.baseUnit?unit.baseUnit:unit;binBoundaries=DEFAULT_BOUNDARIES_FOR_UNIT.get(baseUnit.unitName);}
-this.guid_=undefined;this.binBoundariesDict_=binBoundaries.asDict();this.allBins=binBoundaries.bins.slice();this.description='';const allowReservedNames=false;this.diagnostics_=new tr.v.d.DiagnosticMap(allowReservedNames);this.maxNumSampleValues_=this.defaultMaxNumSampleValues_;this.name_=name;this.nanDiagnosticMaps=[];this.numNans=0;this.running_=undefined;this.sampleValues_=[];this.shortName=undefined;this.summaryOptions=new Map(DEFAULT_SUMMARY_OPTIONS);this.summaryOptions.set('percentile',[]);this.summaryOptions.set('iprs',[]);this.unit=unit;}
-static create(name,unit,samples,opt_options){const options=opt_options||{};const hist=new Histogram(name,unit,options.binBoundaries);if(options.description)hist.description=options.description;if(options.shortName)hist.shortName=options.shortName;if(options.summaryOptions){let summaryOptions=options.summaryOptions;if(!(summaryOptions instanceof Map)){summaryOptions=Object.entries(summaryOptions);}
+const DEFAULT_SUMMARY_OPTIONS=new Map([['avg',true],['count',true],['geometricMean',false],['max',true],['min',true],['nans',false],['std',true],['sum',true],]);class Histogram{constructor(name,unit,opt_binBoundaries){if(!(unit instanceof tr.b.Unit)){throw new Error('unit must be a Unit: '+unit);}
+let binBoundaries=opt_binBoundaries;if(!binBoundaries){const baseUnit=unit.baseUnit?unit.baseUnit:unit;binBoundaries=DEFAULT_BOUNDARIES_FOR_UNIT.get(baseUnit.unitName);}
+this.binBoundariesDict_=binBoundaries.asDict();this.allBins=binBoundaries.bins.slice();this.description='';const allowReservedNames=false;this.diagnostics_=new tr.v.d.DiagnosticMap(allowReservedNames);this.maxNumSampleValues_=this.defaultMaxNumSampleValues_;this.name_=name;this.nanDiagnosticMaps=[];this.numNans=0;this.running_=undefined;this.sampleValues_=[];this.sampleMeans_=[];this.summaryOptions=new Map(DEFAULT_SUMMARY_OPTIONS);this.summaryOptions.set('percentile',[]);this.summaryOptions.set('iprs',[]);this.summaryOptions.set('ci',[]);this.unit=unit;}
+static create(name,unit,samples,opt_options){const options=opt_options||{};const hist=new Histogram(name,unit,options.binBoundaries);if(options.description)hist.description=options.description;if(options.summaryOptions){let summaryOptions=options.summaryOptions;if(!(summaryOptions instanceof Map)){summaryOptions=Object.entries(summaryOptions);}
for(const[name,value]of summaryOptions){hist.summaryOptions.set(name,value);}}
if(options.diagnostics!==undefined){let diagnostics=options.diagnostics;if(!(diagnostics instanceof Map)){diagnostics=Object.entries(diagnostics);}
-for(const[name,diagnostic]of diagnostics){hist.diagnostics.set(name,diagnostic);}}
+for(const[name,diagnostic]of diagnostics){if(!diagnostic)continue;hist.diagnostics.set(name,diagnostic);}}
if(!(samples instanceof Array))samples=[samples];for(const sample of samples){if(typeof sample==='object'){hist.addSample(sample.value,sample.diagnostics);}else{hist.addSample(sample);}}
return hist;}
get diagnostics(){return this.diagnostics_;}
@@ -7192,14 +7329,21 @@ get running(){return this.running_;}
get maxNumSampleValues(){return this.maxNumSampleValues_;}
set maxNumSampleValues(n){this.maxNumSampleValues_=n;tr.b.math.Statistics.uniformlySampleArray(this.sampleValues_,this.maxNumSampleValues_);}
get name(){return this.name_;}
-get guid(){if(this.guid_===undefined){this.guid_=tr.b.GUID.allocateUUID4();}
-return this.guid_;}
-set guid(guid){if(this.guid_!==undefined){throw new Error('Cannot reset guid');}
-this.guid_=guid;}
-static fromDict(dict){const hist=new Histogram(dict.name,tr.b.Unit.fromJSON(dict.unit),HistogramBinBoundaries.fromDict(dict.binBoundaries));hist.guid=dict.guid;if(dict.shortName){hist.shortName=dict.shortName;}
-if(dict.description){hist.description=dict.description;}
+deserializeStatistics_(){const statisticsNames=this.diagnostics.get(tr.v.d.RESERVED_NAMES.STATISTICS_NAMES);if(!statisticsNames)return;for(const statName of statisticsNames){if(statName.startsWith('pct_')){const percent=percentFromString(statName.substr(4));this.summaryOptions.get('percentile').push(percent);}else if(statName.startsWith('ipr_')){const lower=percentFromString(statName.substr(4,3));const upper=percentFromString(statName.substr(8));this.summaryOptions.get('iprs').push(tr.b.math.Range.fromExplicitRange(lower,upper));}else if(statName.startsWith('ci_')){const percent=percentFromString(statName.replace('_lower','').replace('_upper','').substr(3));if(!this.summaryOptions.get('ci').includes(percent)){this.summaryOptions.get('ci').push(percent);}}}
+for(const statName of this.summaryOptions.keys()){if(statName==='percentile'||statName==='iprs'||statName==='ci'){continue;}
+this.summaryOptions.set(statName,statisticsNames.has(statName));}}
+deserializeBin_(i,bin,deserializer){this.allBins[i]=new HistogramBin(this.allBins[i].range);this.allBins[i].deserialize(bin,deserializer);if(!(bin instanceof Array))return;for(let sample of bin.slice(1)){if(sample instanceof Array){sample=sample[0];}
+this.sampleValues_.push(sample);}}
+deserializeBins_(bins,deserializer){if(bins instanceof Array){for(let i=0;i<bins.length;++i){this.deserializeBin_(i,bins[i],deserializer);}}else{for(const[i,binData]of Object.entries(bins)){this.deserializeBin_(i,binData,deserializer);}}}
+static deserialize(data,deserializer){const[name,unit,boundaries,diagnostics,running,bins,nanBin]=data;const hist=new Histogram(deserializer.getObject(name),tr.b.Unit.fromJSON(unit),HistogramBinBoundaries.fromDict(deserializer.getObject(boundaries)));hist.diagnostics.deserializeAdd(diagnostics,deserializer);const description=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.DESCRIPTION);if(description&&description.length){hist.description=[...description][0];}
+hist.deserializeStatistics_();if(running){hist.running_=tr.b.math.RunningStatistics.fromDict(running);}
+if(bins){hist.deserializeBins_(bins,deserializer);}
+if(nanBin){if(!(nanBin instanceof Array)){hist.numNans=nanBin;}else{hist.numNans=nanBin[0];for(const sample of nanBin.slice(1)){if(!(sample instanceof Array))continue;hist.nanDiagnosticMaps.push(tr.v.d.DiagnosticMap.deserialize(sample.slice(1),deserializer));}}}
+return hist;}
+static fromDict(dict){const hist=new Histogram(dict.name,tr.b.Unit.fromJSON(dict.unit),HistogramBinBoundaries.fromDict(dict.binBoundaries));if(dict.description){hist.description=dict.description;}
if(dict.diagnostics){hist.diagnostics.addDicts(dict.diagnostics);}
-if(dict.allBins){if(dict.allBins.length!==undefined){for(let i=0;i<dict.allBins.length;++i){hist.allBins[i]=new HistogramBin(hist.allBins[i].range);hist.allBins[i].fromDict(dict.allBins[i]);}}else{for(const[i,binDict]of Object.entries(dict.allBins)){hist.allBins[i]=new HistogramBin(hist.allBins[i].range);hist.allBins[i].fromDict(binDict);}}}
+if(dict.allBins){if(dict.allBins.length!==undefined){for(let i=0;i<dict.allBins.length;++i){hist.allBins[i]=new HistogramBin(hist.allBins[i].range);hist.allBins[i].fromDict(dict.allBins[i]);}}else{for(const[i,binDict]of Object.entries(dict.allBins)){if(i>=hist.allBins.length||i<0){throw new Error('Invalid index "'+i+'" out of bounds of [0..'+hist.allBins.length+')');}
+hist.allBins[i]=new HistogramBin(hist.allBins[i].range);hist.allBins[i].fromDict(binDict);}}}
if(dict.running){hist.running_=tr.b.math.RunningStatistics.fromDict(dict.running);}
if(dict.summaryOptions){if(dict.summaryOptions.iprs){dict.summaryOptions.iprs=dict.summaryOptions.iprs.map(r=>tr.b.math.Range.fromExplicitRange(r[0],r[1]));}
hist.customizeSummaryOptions(dict.summaryOptions);}
@@ -7227,28 +7371,35 @@ return bin.range.center;}
return this.allBins[this.allBins.length-1].range.min;}
getBinIndexForValue(value){const i=tr.b.findFirstTrueIndexInSortedArray(this.allBins,b=>value<b.range.max);if(0<=i&&i<this.allBins.length)return i;return this.allBins.length-1;}
getBinForValue(value){return this.allBins[this.getBinIndexForValue(value)];}
-addSample(value,opt_diagnostics){if(opt_diagnostics&&!(opt_diagnostics instanceof tr.v.d.DiagnosticMap)){opt_diagnostics=tr.v.d.DiagnosticMap.fromObject(opt_diagnostics);}
+addSample(value,opt_diagnostics){if(opt_diagnostics){if(!(opt_diagnostics instanceof tr.v.d.DiagnosticMap)){opt_diagnostics=tr.v.d.DiagnosticMap.fromObject(opt_diagnostics);}
+for(const[name,diag]of opt_diagnostics){if(diag instanceof tr.v.d.Breakdown){diag.truncate(this.unit);}}}
if(typeof(value)!=='number'||isNaN(value)){this.numNans++;if(opt_diagnostics){tr.b.math.Statistics.uniformlySampleStream(this.nanDiagnosticMaps,this.numNans,opt_diagnostics,MAX_DIAGNOSTIC_MAPS);}}else{if(this.running_===undefined){this.running_=new tr.b.math.RunningStatistics();}
-this.running_.add(value);const binIndex=this.getBinIndexForValue(value);let bin=this.allBins[binIndex];if(bin.count===0){bin=new HistogramBin(bin.range);this.allBins[binIndex]=bin;}
+this.sampleMeans_=[];this.running_.add(value);value=this.unit.truncate(value);const binIndex=this.getBinIndexForValue(value);let bin=this.allBins[binIndex];if(bin.count===0){bin=new HistogramBin(bin.range);this.allBins[binIndex]=bin;}
bin.addSample(value);if(opt_diagnostics){bin.addDiagnosticMap(opt_diagnostics);}}
tr.b.math.Statistics.uniformlySampleStream(this.sampleValues_,this.numValues+this.numNans,value,this.maxNumSampleValues);}
+resampleMean_(percent){const filteredSamples=this.sampleValues_.filter(value=>typeof(value)==='number'&&!isNaN(value));const sampleCount=filteredSamples.length;if(sampleCount===0||percent<=0.0||percent>=1.0){return[undefined,undefined];}else if(sampleCount===1){return[filteredSamples[0],filteredSamples[0]];}
+const iterations=DEFAULT_ITERATION_FOR_BOOTSTRAP_RESAMPLING;if(this.sampleMeans_.length!==iterations){this.sampleMeans_=[];for(let i=0;i<iterations;i++){let tempSum=0.0;for(let j=0;j<sampleCount;j++){tempSum+=filteredSamples[Math.floor(Math.random()*sampleCount)];}
+this.sampleMeans_.push(tempSum/sampleCount);}
+this.sampleMeans_.sort((a,b)=>a-b);}
+return[this.sampleMeans_[Math.floor((iterations-1)*(0.5-percent/2))],this.sampleMeans_[Math.ceil((iterations-1)*(0.5+percent/2))],];}
sampleValuesInto(samples){for(const sampleValue of this.sampleValues){samples.push(sampleValue);}}
canAddHistogram(other){if(this.unit!==other.unit){return false;}
if(this.binBoundariesDict_===other.binBoundariesDict_){return true;}
+if(!this.binBoundariesDict_||!other.binBoundariesDict_){return true;}
if(this.binBoundariesDict_.length!==other.binBoundariesDict_.length){return false;}
for(let i=0;i<this.binBoundariesDict_.length;++i){const slice=this.binBoundariesDict_[i];const otherSlice=other.binBoundariesDict_[i];if(slice instanceof Array){if(!(otherSlice instanceof Array)){return false;}
if(slice[0]!==otherSlice[0]||!tr.b.math.approximately(slice[1],otherSlice[1])||slice[2]!==otherSlice[2]){return false;}}else{if(otherSlice instanceof Array){return false;}
if(!tr.b.math.approximately(slice,otherSlice)){return false;}}}
return true;}
addHistogram(other){if(!this.canAddHistogram(other)){throw new Error('Merging incompatible Histograms');}
+if(!!this.binBoundariesDict_===!!other.binBoundariesDict_){for(let i=0;i<this.allBins.length;++i){let bin=this.allBins[i];if(bin.count===0){bin=new HistogramBin(bin.range);this.allBins[i]=bin;}
+bin.addBin(other.allBins[i]);}}else{const[multiBin,singleBin]=this.binBoundariesDict_?[this,other]:[other,this];for(const value of singleBin.sampleValues){if(typeof(value)!=='number'||isNaN(value)){continue;}
+const binIndex=multiBin.getBinIndexForValue(value);let bin=multiBin.allBins[binIndex];if(bin.count===0){bin=new HistogramBin(bin.range);multiBin.allBins[binIndex]=bin;}
+bin.addSample(value);}}
tr.b.math.Statistics.mergeSampledStreams(this.nanDiagnosticMaps,this.numNans,other.nanDiagnosticMaps,other.numNans,MAX_DIAGNOSTIC_MAPS);tr.b.math.Statistics.mergeSampledStreams(this.sampleValues,this.numValues+this.numNans,other.sampleValues,other.numValues+other.numNans,(this.maxNumSampleValues+other.maxNumSampleValues)/2);this.numNans+=other.numNans;if(other.running_!==undefined){if(this.running_===undefined){this.running_=new tr.b.math.RunningStatistics();}
this.running_=this.running_.merge(other.running_);}
-for(let i=0;i<this.allBins.length;++i){let bin=this.allBins[i];if(bin.count===0){bin=new HistogramBin(bin.range);this.allBins[i]=bin;}
-bin.addBin(other.allBins[i]);}
-let mergedFrom=this.diagnostics.get(tr.v.d.RESERVED_NAMES.MERGED_FROM);if(!mergedFrom){mergedFrom=new tr.v.d.RelatedHistogramMap();this.diagnostics.set(tr.v.d.RESERVED_NAMES.MERGED_FROM,mergedFrom);}
-mergedFrom.set(mergedFrom.length,other);let mergedTo=other.diagnostics.get(tr.v.d.RESERVED_NAMES.MERGED_TO);if(!mergedTo){mergedTo=new tr.v.d.RelatedHistogramMap();other.diagnostics.set(tr.v.d.RESERVED_NAMES.MERGED_TO,mergedTo);}
-mergedTo.set(mergedTo.length,this);this.diagnostics.addDiagnostics(other.diagnostics);for(const[stat,option]of other.summaryOptions){if(stat==='percentile'){const percentiles=this.summaryOptions.get(stat);for(const percent of option){if(!percentiles.includes(percent))percentiles.push(percent);}}else if(stat==='iprs'){const thisIprs=this.summaryOptions.get(stat);for(const ipr of option){let found=false;for(const thisIpr of thisIprs){found=ipr.equals(thisIpr);if(found)break;}
-if(!found)thisIprs.push(ipr);}}else if(option&&!this.summaryOptions.get(stat)){this.summaryOptions.set(stat,true);}}}
+this.sampleMeans_=[];this.diagnostics.addDiagnostics(other.diagnostics);for(const[stat,option]of other.summaryOptions){if(stat==='percentile'){const percentiles=this.summaryOptions.get(stat);for(const percent of option){if(!percentiles.includes(percent))percentiles.push(percent);}}else if(stat==='iprs'){const thisIprs=this.summaryOptions.get(stat);for(const ipr of option){let found=false;for(const thisIpr of thisIprs){found=ipr.equals(thisIpr);if(found)break;}
+if(!found)thisIprs.push(ipr);}}else if(stat==='ci'){const CIs=this.summaryOptions.get(stat);for(const CI of option){if(!CIs.includes(CI))CIs.push(CI);}}else if(option&&!this.summaryOptions.get(stat)){this.summaryOptions.set(stat,true);}}}
customizeSummaryOptions(summaryOptions){for(const[key,value]of Object.entries(summaryOptions)){this.summaryOptions.set(key,value);}}
getStatisticScalar(statName,opt_referenceHistogram,opt_mwu){if(statName==='avg'){if(typeof(this.average)!=='number')return undefined;return new tr.b.Scalar(this.unit,this.average);}
if(statName==='std'){if(typeof(this.standardDeviation)!=='number')return undefined;return new tr.b.Scalar(this.unit,this.standardDeviation);}
@@ -7257,7 +7408,10 @@ if(statName==='min'||statName==='max'||statName==='sum'){if(this.running_===unde
if(typeof(this.running_[statName])!=='number')return undefined;return new tr.b.Scalar(this.unit,this.running_[statName]);}
if(statName==='nans'){return new tr.b.Scalar(tr.b.Unit.byName.count_smallerIsBetter,this.numNans);}
if(statName==='count'){return new tr.b.Scalar(tr.b.Unit.byName.count_smallerIsBetter,this.numValues);}
-if(statName.substr(0,4)==='pct_'){const percent=percentFromString(statName.substr(4));if(this.numValues===0)return undefined;const percentile=this.getApproximatePercentile(percent);if(typeof(percentile)!=='number')return undefined;return new tr.b.Scalar(this.unit,percentile);}
+if(statName.substr(0,4)==='pct_'){if(this.numValues===0)return undefined;const percent=percentFromString(statName.substr(4));const percentile=this.getApproximatePercentile(percent);if(typeof(percentile)!=='number')return undefined;return new tr.b.Scalar(this.unit,percentile);}
+if(statName.substr(0,3)==='ci_'){const percent=percentFromString(statName.substr(3,3));const[lowCI,highCI]=this.resampleMean_(percent);if(statName.substr(7)==='lower'){if(typeof(lowCI)!=='number')return undefined;return new tr.b.Scalar(this.unit,lowCI);}else if(statName.substr(7)==='upper'){if(typeof(highCI)!=='number')return undefined;return new tr.b.Scalar(this.unit,highCI);}
+if(typeof(highCI)!=='number'||typeof(lowCI)!=='number'){return undefined;}
+return new tr.b.Scalar(this.unit,highCI-lowCI);}
if(statName.substr(0,4)==='ipr_'){let lower=percentFromString(statName.substr(4,3));let upper=percentFromString(statName.substr(8));if(lower>=upper){throw new Error('Invalid inter-percentile range: '+statName);}
lower=this.getApproximatePercentile(lower);upper=this.getApproximatePercentile(upper);const ipr=upper-lower;if(typeof(ipr)!=='number')return undefined;return new tr.b.Scalar(this.unit,ipr);}
if(!this.canCompare(opt_referenceHistogram)){throw new Error('Cannot compute '+statName+' when histograms are not comparable');}
@@ -7267,7 +7421,7 @@ if(statName===Z_SCORE_NAME){return new tr.b.Scalar(tr.b.Unit.byName['sigmaDelta'
const mwu=opt_mwu||tr.b.math.Statistics.mwu(this.sampleValues,opt_referenceHistogram.sampleValues);if(statName===P_VALUE_NAME){return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber,mwu.p);}
if(statName===U_STATISTIC_NAME){return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber,mwu.U);}
throw new Error('Unrecognized statistic name: '+statName);}
-get statisticsNames(){const statisticsNames=new Set();for(const[statName,option]of this.summaryOptions){if(statName==='percentile'){for(const pctile of option){statisticsNames.add('pct_'+tr.v.percentToString(pctile));}}else if(statName==='iprs'){for(const range of option){statisticsNames.add('ipr_'+tr.v.percentToString(range.min,true)+'_'+tr.v.percentToString(range.max,true));}}else if(option){statisticsNames.add(statName);}}
+get statisticsNames(){const statisticsNames=new Set();for(const[statName,option]of this.summaryOptions){if(statName==='percentile'){for(const pctile of option){statisticsNames.add('pct_'+tr.v.percentToString(pctile));}}else if(statName==='iprs'){for(const range of option){statisticsNames.add('ipr_'+tr.v.percentToString(range.min,true)+'_'+tr.v.percentToString(range.max,true));}}else if(statName==='ci'){for(const CIpctile of option){const CIpctStr=tr.v.percentToString(CIpctile);statisticsNames.add('ci_'+CIpctStr+'_lower');statisticsNames.add('ci_'+CIpctStr+'_upper');statisticsNames.add('ci_'+CIpctStr);}}else if(option){statisticsNames.add(statName);}}
return statisticsNames;}
canCompare(other){return other instanceof Histogram&&this.unit===other.unit&&this.numValues>0&&other.numValues>0;}
getAvailableStatisticName(statName,opt_referenceHist){if(this.canCompare(opt_referenceHist))return statName;if(statName===Z_SCORE_NAME||statName===P_VALUE_NAME||statName===U_STATISTIC_NAME){return'avg';}
@@ -7277,24 +7431,31 @@ return deltaNames.concat([Z_SCORE_NAME,P_VALUE_NAME,U_STATISTIC_NAME]);}
get statisticsScalars(){const results=new Map();for(const statName of this.statisticsNames){const scalar=this.getStatisticScalar(statName);if(scalar===undefined)continue;results.set(statName,scalar);}
return results;}
get sampleValues(){return this.sampleValues_;}
-clone(){const binBoundaries=HistogramBinBoundaries.fromDict(this.binBoundariesDict_);const hist=new Histogram(this.name,this.unit,binBoundaries);for(const[stat,option]of this.summaryOptions){if(stat==='percentile'||stat==='iprs'){hist.summaryOptions.set(stat,Array.from(option));}else{hist.summaryOptions.set(stat,option);}}
+clone(){const binBoundaries=HistogramBinBoundaries.fromDict(this.binBoundariesDict_);const hist=new Histogram(this.name,this.unit,binBoundaries);for(const[stat,option]of this.summaryOptions){if(stat==='percentile'||stat==='iprs'||stat==='ci'){hist.summaryOptions.set(stat,Array.from(option));}else{hist.summaryOptions.set(stat,option);}}
hist.addHistogram(this);return hist;}
rebin(newBoundaries){const rebinned=new tr.v.Histogram(this.name,this.unit,newBoundaries);rebinned.description=this.description;for(const sample of this.sampleValues){rebinned.addSample(sample);}
rebinned.running_=this.running_;for(const[name,diagnostic]of this.diagnostics){rebinned.diagnostics.set(name,diagnostic);}
-for(const[stat,option]of this.summaryOptions){if(stat==='percentile'){rebinned.summaryOptions.set(stat,Array.from(option));}else{rebinned.summaryOptions.set(stat,option);}}
+for(const[stat,option]of this.summaryOptions){if(stat==='percentile'||stat==='ci'){rebinned.summaryOptions.set(stat,Array.from(option));}else{rebinned.summaryOptions.set(stat,option);}}
return rebinned;}
-asDict(){const dict={};dict.name=this.name;dict.unit=this.unit.asJSON();dict.guid=this.guid;if(this.binBoundariesDict_!==undefined){dict.binBoundaries=this.binBoundariesDict_;}
-if(this.shortName){dict.shortName=this.shortName;}
+serialize(serializer){let nanBin=this.numNans;if(this.nanDiagnosticMaps.length){nanBin=[nanBin,...this.nanDiagnosticMaps.map(dm=>[undefined,...dm.serialize(serializer)])];}
+this.diagnostics.set(tr.v.d.RESERVED_NAMES.STATISTICS_NAMES,new tr.v.d.GenericSet([...this.statisticsNames].sort()));this.diagnostics.set(tr.v.d.RESERVED_NAMES.DESCRIPTION,new tr.v.d.GenericSet([this.description].sort()));return[serializer.getOrAllocateId(this.name),this.unit.asJSON2(),serializer.getOrAllocateId(this.binBoundariesDict_),this.diagnostics.serialize(serializer),this.running_?this.running_.asDict():0,this.serializeBins_(serializer),nanBin,];}
+asDict(){const dict={};dict.name=this.name;dict.unit=this.unit.asJSON();if(this.binBoundariesDict_!==undefined){dict.binBoundaries=this.binBoundariesDict_;}
if(this.description){dict.description=this.description;}
if(this.diagnostics.size){dict.diagnostics=this.diagnostics.asDict();}
if(this.maxNumSampleValues!==this.defaultMaxNumSampleValues_){dict.maxNumSampleValues=this.maxNumSampleValues;}
if(this.numNans){dict.numNans=this.numNans;}
if(this.nanDiagnosticMaps.length){dict.nanDiagnostics=this.nanDiagnosticMaps.map(dm=>dm.asDict());}
-if(this.numValues){dict.sampleValues=this.sampleValues.slice();dict.running=this.running_.asDict();dict.allBins=this.allBinsAsDict_();}
-const summaryOptions={};let anyOverriddenSummaryOptions=false;for(const[name,value]of this.summaryOptions){let option;if(name==='percentile'){if(value.length===0)continue;option=Array.from(value);}else if(name==='iprs'){if(value.length===0)continue;option=value.map(r=>[r.min,r.max]);}else if(value===DEFAULT_SUMMARY_OPTIONS.get(name)){continue;}else{option=value;}
+if(this.numValues){dict.sampleValues=this.sampleValues.slice();this.running.truncate(this.unit);dict.running=this.running_.asDict();dict.allBins=this.allBinsAsDict_();}
+const summaryOptions={};let anyOverriddenSummaryOptions=false;for(const[name,value]of this.summaryOptions){let option;if(name==='percentile'){if(value.length===0)continue;option=Array.from(value);}else if(name==='iprs'){if(value.length===0)continue;option=value.map(r=>[r.min,r.max]);}else if(name==='ci'){if(value.length===0)continue;option=Array.from(value);}else if(value===DEFAULT_SUMMARY_OPTIONS.get(name)){continue;}else{option=value;}
summaryOptions[name]=option;anyOverriddenSummaryOptions=true;}
if(anyOverriddenSummaryOptions){dict.summaryOptions=summaryOptions;}
return dict;}
+serializeBins_(serializer){const numBins=this.allBins.length;let emptyBins=0;for(let i=0;i<numBins;++i){if(this.allBins[i].count===0){++emptyBins;}}
+if(emptyBins===numBins){return 0;}
+if(emptyBins>(numBins/2)){const allBinsDict={};for(let i=0;i<numBins;++i){const bin=this.allBins[i];if(bin.count>0){allBinsDict[i]=bin.serialize(serializer);}}
+return allBinsDict;}
+const allBinsArray=[];for(let i=0;i<numBins;++i){allBinsArray.push(this.allBins[i].serialize(serializer));}
+return allBinsArray;}
allBinsAsDict_(){const numBins=this.allBins.length;let emptyBins=0;for(let i=0;i<numBins;++i){if(this.allBins[i].count===0){++emptyBins;}}
if(emptyBins===numBins){return undefined;}
if(emptyBins>(numBins/2)){const allBinsDict={};for(let i=0;i<numBins;++i){const bin=this.allBins[i];if(bin.count>0){allBinsDict[i]=bin.asDict();}}
@@ -7797,7 +7958,7 @@ return this.seriesByKey_.get(key);},decorate(){Polymer.dom(this).classList.add('
this.addEventListener(DataSeriesEnableChangeEventType,this.onDataSeriesEnableChange_.bind(this));},get hideLegend(){return this.hideLegend_;},set hideLegend(h){this.hideLegend_=h;this.updateContents_();},get showTitleInLegend(){return this.showTitleInLegend_;},set showTitleInLegend(s){this.showTitleInLegend_=s;this.updateContents_();},isSeriesEnabled(key){return this.getDataSeries(key).enabled;},onDataSeriesEnableChange_(event){this.getDataSeries(event.key).enabled=event.enabled;this.updateContents_();},get chartTitle(){return this.chartTitle_;},set chartTitle(chartTitle){this.chartTitle_=chartTitle;this.updateContents_();},get chartAreaElement(){return Polymer.dom(this).querySelector('#chart-area');},get graphWidth(){if(this.graphWidth_===undefined)return this.defaultGraphWidth;return this.graphWidth_;},set graphWidth(width){this.graphWidth_=width;this.updateContents_();},get defaultGraphWidth(){return 0;},get graphHeight(){if(this.graphHeight_===undefined)return this.defaultGraphHeight;return this.graphHeight_;},set graphHeight(height){this.graphHeight_=height;this.updateContents_();},get titleHeight(){return this.titleHeight_;},set titleHeight(height){this.titleHeight_=height;this.updateContents_();},get defaultGraphHeight(){return 0;},get totalWidth(){return this.margin.left+this.graphWidth+this.margin.right;},get totalHeight(){return this.margin.top+this.graphHeight+this.margin.bottom;},updateMargins_(){const legendSize=this.computeLegendSize_();this.margin.right=Math.max(this.margin.right,legendSize.width);this.margin.bottom=Math.max(this.margin.bottom,legendSize.height-this.graphHeight);if(this.chartTitle_){const titleSize=getSVGTextSize(this,this.chartTitle_,textNode=>{textNode.style.fontSize='16pt';});this.margin.top=Math.max(this.margin.top,titleSize.height+15);const horizontalOverhangPx=(titleSize.width-this.graphWidth)/2;this.margin.left=Math.max(this.margin.left,horizontalOverhangPx);this.margin.right=Math.max(this.margin.right,horizontalOverhangPx);}},computeLegendSize_(){let width=0;let height=0;if(this.hideLegend)return{width,height};let series=[...this.seriesByKey_.values()];if(this.showTitleInLegend){series=series.filter(series=>series.title!=='');}
for(const seriesEntry of series){const legendText=this.showTitleInLegend?seriesEntry.title:seriesEntry.key;const textSize=getSVGTextSize(this,legendText);width=Math.max(width,textSize.width+30);height+=textSize.height;}
return{width,height};},updateDimensions_(){const thisSel=d3.select(this);thisSel.attr('width',this.totalWidth);thisSel.attr('height',this.totalHeight);d3.select(this.chartAreaElement).attr('transform','translate('+this.margin.left+', '+this.margin.top+')');},updateContents_(){this.updateMargins_();this.updateDimensions_();this.updateTitle_();this.updateLegend_();},updateTitle_(){const titleSel=d3.select(this.chartAreaElement).select('#title');if(!this.chartTitle_){titleSel.style('display','none');return;}
-titleSel.attr('transform','translate('+this.graphWidth*0.5+',-15)').style('display',undefined).style('text-anchor','middle').style('font-size',this.titleHeight).attr('class','title').attr('width',this.graphWidth).text(this.chartTitle_);},updateLegend_(){const chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.selectAll('.legend').remove();if(this.hideLegend)return;let series;let seriesText;if(this.showTitleInLegend){series=[...this.seriesByKey_.values()].filter(series=>series.title!=='').reverse();seriesText=series=>series.title;}else{series=[...this.seriesByKey_.values()].reverse();seriesText=series=>series.key;}
+titleSel.attr('transform','translate('+this.graphWidth*0.5+',-15)').style('display',undefined).style('text-anchor','middle').style('font-size',this.titleHeight).attr('class','title').attr('width',this.graphWidth).text(this.chartTitle_);},updateLegend_(){const chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.selectAll('.legend').remove();if(this.hideLegend)return;let series;let seriesText;if(this.showTitleInLegend){series=[...this.seriesByKey_.values()].filter(series=>series.title!=='').filter(series=>series.color!=='transparent').reverse();seriesText=series=>series.title;}else{series=[...this.seriesByKey_.values()].filter(series=>series.color!=='transparent').reverse();seriesText=series=>series.key;}
const legendEntriesSel=chartAreaSel.selectAll('.legend').data(series);legendEntriesSel.enter().append('foreignObject').attr('class','legend').attr('x',this.graphWidth+2).attr('width',this.margin.right).attr('height',18).attr('transform',(series,i)=>'translate(0,'+i*18+')').append('xhtml:body').style('margin',0).append('tr-ui-b-chart-legend-key').property('color',series=>((this.currentHighlightedLegendKey===series.key)?series.highlightedColor:series.color)).property('width',this.margin.right).property('target',series=>series.target).property('title',series=>series.title).property('optional',series=>series.optional).property('enabled',series=>series.enabled).text(seriesText);legendEntriesSel.exit().remove();},get highlightedLegendKey(){return this.highlightedLegendKey_;},set highlightedLegendKey(highlightedLegendKey){this.highlightedLegendKey_=highlightedLegendKey;this.updateHighlight_();},get currentHighlightedLegendKey(){if(this.tempHighlightedLegendKey_){return this.tempHighlightedLegendKey_;}
return this.highlightedLegendKey_;},pushTempHighlightedLegendKey(key){if(this.tempHighlightedLegendKey_){throw new Error('push cannot nest');}
this.tempHighlightedLegendKey_=key;this.updateHighlight_();},popTempHighlightedLegendKey(key){if(this.tempHighlightedLegendKey_!==key){throw new Error('pop cannot happen');}
@@ -7933,7 +8094,7 @@ return currentY;},drawStatNames_(leftView,height,currentY,prefix,maxStats){const
ctx.fillText(fullname,leftView-10,currentY-height/4);currentY+=height;}}
return currentY;}};tr.ui.tracks.ObjectInstanceTrack.register(SystemStatsInstanceTrack,{typeName:'base::TraceEventSystemStatsMonitor::SystemStats'});return{SystemStatsInstanceTrack,};});'use strict';tr.exportTo('tr.ui.e.system_stats',function(){const SystemStatsSnapshotView=tr.ui.b.define('tr-ui-e-system-stats-snapshot-view',tr.ui.analysis.ObjectSnapshotView);SystemStatsSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){Polymer.dom(this).classList.add('tr-ui-e-system-stats-snapshot-view');},updateContents(){const snapshot=this.objectSnapshot_;if(!snapshot||!snapshot.getStats()){Polymer.dom(this).textContent='No system stats snapshot found.';return;}
Polymer.dom(this).textContent='';const stats=snapshot.getStats();Polymer.dom(this).appendChild(this.buildList_(stats));},isFloat(n){return typeof n==='number'&&n%1!==0;},buildList_(stats){const statList=document.createElement('ul');for(const statName in stats){const statText=document.createElement('li');Polymer.dom(statText).textContent=''+statName+': ';Polymer.dom(statList).appendChild(statText);if(stats[statName]instanceof Object){Polymer.dom(statList).appendChild(this.buildList_(stats[statName]));}else{if(this.isFloat(stats[statName])){Polymer.dom(statText).textContent+=stats[statName].toFixed(2);}else{Polymer.dom(statText).textContent+=stats[statName];}}}
-return statList;}};tr.ui.analysis.ObjectSnapshotView.register(SystemStatsSnapshotView,{typeName:'base::TraceEventSystemStatsMonitor::SystemStats'});return{SystemStatsSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.v8',function(){const IGNORED_ENTRIES={match:full=>full.startsWith('*CODE_AGE_')};const INSTANCE_TYPE_GROUPS={FIXED_ARRAY_TYPE:{match:full=>full.startsWith('*FIXED_ARRAY_'),realEntry:'FIXED_ARRAY_TYPE',keyToName:key=>key.slice('*FIXED_ARRAY_'.length).slice(0,-('_SUB_TYPE'.length)),nameToKey:name=>'*FIXED_ARRAY_'+name+'_SUB_TYPE'},CODE_TYPE:{match:full=>full.startsWith('*CODE_'),realEntry:'CODE_TYPE',keyToName:key=>key.slice('*CODE_'.length),nameToKey:name=>'*CODE_'+name},JS_OBJECTS:{match:full=>full.startsWith('JS_'),keyToName:key=>key,nameToKey:name=>name},Strings:{match:full=>full.endsWith('STRING_TYPE'),keyToName:key=>key,nameToKey:name=>name}};const DIFF_COLOR={GREEN:'#64DD17',RED:'#D50000'};function computePercentage(valueA,valueB){if(valueA===0)return 0;return valueA/valueB*100;}
+return statList;}};tr.ui.analysis.ObjectSnapshotView.register(SystemStatsSnapshotView,{typeName:'base::TraceEventSystemStatsMonitor::SystemStats'});return{SystemStatsSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.v8',function(){const IGNORED_ENTRIES={match:full=>full.startsWith('*CODE_AGE_')};const INSTANCE_TYPE_GROUPS={FIXED_ARRAY_TYPE:{match:full=>full.startsWith('*FIXED_ARRAY_'),realEntry:'FIXED_ARRAY_TYPE',keyToName:key=>key.slice('*FIXED_ARRAY_'.length).slice(0,-('_SUB_TYPE'.length)),nameToKey:name=>'*FIXED_ARRAY_'+name+'_SUB_TYPE'},CODE_TYPE:{match:full=>full.startsWith('*CODE_'),realEntry:'CODE_TYPE',keyToName:key=>key.slice('*CODE_'.length),nameToKey:name=>'*CODE_'+name},JS_OBJECTS:{match:full=>full.startsWith('JS_'),keyToName:key=>key,nameToKey:name=>name},Strings:{match:full=>full.endsWith('STRING_TYPE'),keyToName:key=>key,nameToKey:name=>name},Maps:{match:full=>full.startsWith('MAP_')&&full.endsWith('_TYPE'),keyToName:key=>key,nameToKey:name=>name},DescriptorArrays:{match:full=>full.endsWith('DESCRIPTOR_ARRAY_TYPE'),keyToName:key=>key,nameToKey:name=>name}};const DIFF_COLOR={GREEN:'#64DD17',RED:'#D50000'};function computePercentage(valueA,valueB){if(valueA===0)return 0;return valueA/valueB*100;}
class DiffEntry{constructor(originalEntry,diffEntry){this.originalEntry_=originalEntry;this.diffEntry_=diffEntry;}
get title(){return this.diffEntry_.title;}
get overall(){return this.diffEntry_.overall;}
@@ -8077,7 +8238,7 @@ function getPathsFromStack(stack){return stack.split('\n').map(line=>{line=line.
MetricRegistry.checkFilename=function(metricName,opt_metricPathForTest){if(metricName==='runtimeStatsTotalMetric'||metricName==='v8AndMemoryMetrics'){return;}
const expectedFilename=camelCaseToHackerString(metricName)+'.html';const stack=getCallStack();let metricPath=opt_metricPathForTest;if(metricPath===undefined){const paths=getPathsFromStack(stack);const METRIC_STACK_INDEX=5;if(paths.length<=METRIC_STACK_INDEX||paths[METRIC_STACK_INDEX].join('/')===paths[0].join('/')){return;}
metricPath=paths[METRIC_STACK_INDEX].slice(paths[METRIC_STACK_INDEX].length-2);}
-if(!metricPath[1].endsWith('_test.html')&&metricPath[1]!==expectedFilename&&metricPath.join('_')!==expectedFilename){throw new Error('Expected '+metricName+' to be in a file named '+
+if(!metricPath[1].endsWith('_test.html')&&!metricPath[1].endsWith('_test.html.js')&&metricPath[1]!==expectedFilename&&metricPath[1]!==expectedFilename+'.js'&&metricPath.join('_')!==expectedFilename&&metricPath.join('_')!==expectedFilename+'.js'){throw new Error('Expected '+metricName+' to be in a file named '+
expectedFilename+'; actual: '+metricPath.join('/')+'; stack: '+stack.replace(/\n/g,'\n '));}};MetricRegistry.addEventListener('will-register',function(e){const metric=e.typeInfo.constructor;if(!(metric instanceof Function)){throw new Error('Metrics must be functions.');}
if(!metric.name.endsWith('Metric')&&!metric.name.endsWith('Metrics')){throw new Error('Metric names must end with "Metric" or "Metrics".');}
if(metric.length<2){throw new Error('Metrics take a HistogramSet and a Model and '+'optionally an options dictionary.');}
@@ -8085,14 +8246,21 @@ MetricRegistry.checkFilename(metric.name);});return{MetricRegistry,};});'use str
if(slice.title==='RenderAccessibilityImpl::SendLocationChanges'){renderAccessibilityLocationsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}}}
for(const browserHelper of Object.values(chromeHelper.browserHelpers)){const mainThread=browserHelper.mainThread;if(mainThread===undefined)continue;for(const slice of mainThread.getDescendantEvents()){if(slice.title==='BrowserAccessibilityManager::OnAccessibilityEvents'){browserAccessibilityEventsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}}}
histograms.addHistogram(browserAccessibilityEventsHist);histograms.addHistogram(renderAccessibilityEventsHist);histograms.addHistogram(renderAccessibilityLocationsHist);}
-tr.metrics.MetricRegistry.register(accessibilityMetric);return{accessibilityMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MESSAGE_LOOP_EVENT_NAME='Startup.BrowserMessageLoopStartTimeFromMainEntry3';const FIRST_CONTENTFUL_PAINT_EVENT_NAME='firstContentfulPaint';function androidStartupMetric(histograms,model){let messageLoopStartEvents=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;for(const helper of chromeHelper.browserHelpers){for(const ev of helper.mainThread.asyncSliceGroup.childEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}}}
-let firstContentfulPaintEvents=[];const rendererHelpers=chromeHelper.rendererHelpers;const pids=Object.keys(rendererHelpers);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(!rendererHelper.mainThread)continue;for(const ev of rendererHelper.mainThread.sliceGroup.childEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}}}
-let totalBrowserStarts=messageLoopStartEvents.length;let totalFcpEvents=firstContentfulPaintEvents.length;if(totalFcpEvents!==totalBrowserStarts||totalBrowserStarts===0){messageLoopStartEvents=[];firstContentfulPaintEvents=[];for(const proc of Object.values(model.processes)){for(const ev of proc.getDescendantEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}}
+tr.metrics.MetricRegistry.register(accessibilityMetric);return{accessibilityMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MESSAGE_LOOP_EVENT_NAME='Startup.BrowserMessageLoopStartTimeFromMainEntry3';const CONTENT_START_EVENT_NAME='content::Start';const NAVIGATION_EVENT_NAME='Navigation StartToCommit';const FIRST_CONTENTFUL_PAINT_EVENT_NAME='firstContentfulPaint';function androidStartupMetric(histograms,model){let messageLoopStartEvents=[];let navigationEvents=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;for(const helper of chromeHelper.browserHelpers){for(const ev of helper.mainThread.asyncSliceGroup.childEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}}}
+let contentStartEvents=[];let firstContentfulPaintEvents=[];const rendererHelpers=chromeHelper.rendererHelpers;const pids=Object.keys(rendererHelpers);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(!rendererHelper.mainThread)continue;for(const ev of rendererHelper.mainThread.sliceGroup.childEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}}
+let totalBrowserStarts=messageLoopStartEvents.length;let totalContentStartEvents=contentStartEvents.length;let totalFcpEvents=firstContentfulPaintEvents.length;let totalNavigations=navigationEvents.length;if(totalFcpEvents!==totalBrowserStarts||totalNavigations!==totalBrowserStarts||totalContentStartEvents!==totalBrowserStarts||totalBrowserStarts===0){messageLoopStartEvents=[];contentStartEvents=[];navigationEvents=[];firstContentfulPaintEvents=[];for(const proc of Object.values(model.processes)){for(const ev of proc.getDescendantEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}
for(const ev of proc.getDescendantEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}}}
-totalBrowserStarts=messageLoopStartEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;}
-if(totalFcpEvents!==totalBrowserStarts){throw new Error('Number of FCP events ('+totalFcpEvents+') differs from number of browser starts ('+totalBrowserStarts+')');}
-const messageLoopStartHistogram=histograms.createHistogram('messageloop_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const firstContentfulPaintHistogram=histograms.createHistogram('first_contentful_paint_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);function orderEvents(event1,event2){return event1.start-event2.start;}
-messageLoopStartEvents.sort(orderEvents);firstContentfulPaintEvents.sort(orderEvents);for(let i=2;i<totalBrowserStarts;i++){const startEvent=messageLoopStartEvents[i];messageLoopStartHistogram.addSample(startEvent.duration,{events:new tr.v.d.RelatedEventSet([startEvent])});const fcpEvent=firstContentfulPaintEvents[i];firstContentfulPaintHistogram.addSample(fcpEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,fcpEvent])});}}
+totalBrowserStarts=messageLoopStartEvents.length;totalContentStartEvents=contentStartEvents.length;totalNavigations=navigationEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;}
+function orderEvents(event1,event2){return event1.start-event2.start;}
+messageLoopStartEvents.sort(orderEvents);contentStartEvents.sort(orderEvents);navigationEvents.sort(orderEvents);firstContentfulPaintEvents.sort(orderEvents);if(totalFcpEvents<totalBrowserStarts){throw new Error('Found fewer FCP events ('+totalFcpEvents+') than browser starts ('+totalBrowserStarts+')');}
+const messageLoopStartHistogram=histograms.createHistogram('messageloop_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const contentStartHistogram=histograms.createHistogram('experimental_content_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationStartHistogram=histograms.createHistogram('experimental_navigation_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationCommitHistogram=histograms.createHistogram('navigation_commit_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const firstContentfulPaintHistogram=histograms.createHistogram('first_contentful_paint_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);let contentIndex=0;let navIndex=0;let fcpIndex=0;for(let loopStartIndex=0;loopStartIndex<totalBrowserStarts;){const startEvent=messageLoopStartEvents[loopStartIndex];if(fcpIndex===totalFcpEvents){break;}
+const contentStartEvent=contentIndex<contentStartEvents.length?contentStartEvents[contentIndex]:null;if(contentStartEvent&&contentStartEvent.start<startEvent.start){contentIndex++;continue;}
+const navEvent=navIndex<navigationEvents.length?navigationEvents[navIndex]:null;if(navEvent&&navEvent.start<startEvent.start){navIndex++;continue;}
+const fcpEvent=firstContentfulPaintEvents[fcpIndex];if(fcpEvent.start<startEvent.start){fcpIndex++;continue;}
+loopStartIndex++;if(fcpIndex<2){continue;}
+messageLoopStartHistogram.addSample(startEvent.duration,{events:new tr.v.d.RelatedEventSet([startEvent])});if(contentStartEvent){contentStartHistogram.addSample(contentStartEvent.start-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,contentStartEvent])});}
+if(navEvent){navigationStartHistogram.addSample(navEvent.start-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,navEvent])});navigationCommitHistogram.addSample(navEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,navEvent])});}
+firstContentfulPaintHistogram.addSample(fcpEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,fcpEvent])});}}
tr.metrics.MetricRegistry.register(androidStartupMetric);return{androidStartupMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MAX_INPUT_EVENT_TO_STARTUP_DELAY_IN_MS=2000;const MIN_DRAW_DELAY_IN_MS=80;const MAX_DRAW_DELAY_IN_MS=2000;function findProcess(processName,model){for(const pid in model.processes){const process=model.processes[pid];if(process.name===processName){return process;}}
return undefined;}
function findThreads(process,threadPrefix){if(process===undefined)return undefined;const threads=[];for(const tid in process.threads){const thread=process.threads[tid];if(thread.name.startsWith(threadPrefix)){threads.push(thread);}}
@@ -8151,8 +8319,10 @@ function forcedGCEventName(){return LOW_MEMORY_EVENT;}
function topGarbageCollectionEventName(event){if(event.title===FULL_GC_EVENT){if(findParent(event,isLowMemoryEvent)){return LOW_MEMORY_MARK_COMPACTOR;}}
return TOP_GC_EVENTS[event.title];}
function subGarbageCollectionEventName(event){const topEvent=findParent(event,isTopGarbageCollectionEvent);const prefix=topEvent?topGarbageCollectionEventName(topEvent):'unknown';const name=event.title.replace('V8.GC_MC_','').replace('V8.GC_SCAVENGER_','').replace('V8.GC_','').replace(/_/g,'-').toLowerCase();return prefix+'-'+name;}
-function groupAndProcessEvents(model,filterCallback,nameCallback,processCallback){const nameToEvents={};for(const event of model.getDescendantEvents()){if(!filterCallback(event))continue;const name=nameCallback(event);nameToEvents[name]=nameToEvents[name]||[];nameToEvents[name].push(event);}
-for(const[name,events]of Object.entries(nameToEvents)){processCallback(name,events);}}
+function jsExecutionThreads(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let threads=[];for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;threads.push(rendererHelper.mainThread);threads=threads.concat(rendererHelper.dedicatedWorkerThreads);threads=threads.concat(rendererHelper.foregroundWorkerThreads);}
+return threads;}
+function groupAndProcessEvents(model,filterCallback,groupCallback,processCallback){const groupToEvents={};const threads=jsExecutionThreads(model);for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;const group=groupCallback(event);groupToEvents[group]=groupToEvents[group]||[];groupToEvents[group].push(event);}}
+for(const[group,events]of Object.entries(groupToEvents)){processCallback(group,events);}}
function unionOfIntervals(intervals){if(intervals.length===0)return[];return tr.b.math.mergeRanges(intervals.map(x=>{return{min:x.start,max:x.end};}),1e-6,function(ranges){return{start:ranges.reduce((acc,x)=>Math.min(acc,x.min),ranges[0].min),end:ranges.reduce((acc,x)=>Math.max(acc,x.max),ranges[0].max)};});}
function hasV8Stats(globalMemoryDump){let v8stats=undefined;globalMemoryDump.iterateContainerDumps(function(dump){v8stats=v8stats||dump.getMemoryAllocatorDumpByFullName('v8');});return!!v8stats;}
function rangeForMemoryDumps(model){const startOfFirstDumpWithV8=model.globalMemoryDumps.filter(hasV8Stats).reduce((start,dump)=>Math.min(start,dump.start),Infinity);if(startOfFirstDumpWithV8===Infinity)return new tr.b.math.Range();return tr.b.math.Range.fromExplicitRange(startOfFirstDumpWithV8,Infinity);}
@@ -8161,31 +8331,32 @@ advance(delta){if(delta<this.distanceUntilNextPoint){this.position+=delta;this.c
function mutatorUtilization(start,end,timeWindow,intervals){const mu=new tr.b.math.PiecewiseLinearFunction();if(end-start<=timeWindow){return mu;}
if(intervals.length===0){mu.push(start,1.0,end-timeWindow,1.0);return mu;}
intervals=unionOfIntervals(intervals);const points=[];for(const interval of intervals){points.push({position:interval.start,delta:1});points.push({position:interval.end,delta:-1});}
-points.sort((a,b)=>a.position-b.position);points.push({position:end,delta:0});const left=new WindowEndpoint(start,points);const right=new WindowEndpoint(start,points);while(right.position-left.position<timeWindow){right.advance(timeWindow-(right.position-left.position));}
+points.sort((a,b)=>a.position-b.position);points.push({position:end,delta:0});const left=new WindowEndpoint(start,points);const right=new WindowEndpoint(start,points);const EPSILON=1e-6;while(right.position-left.position<timeWindow-EPSILON){right.advance(timeWindow-(right.position-left.position));}
while(right.lastIndex<points.length){const distanceUntilNextPoint=Math.min(left.distanceUntilNextPoint,right.distanceUntilNextPoint);const position1=left.position;const value1=right.cummulativePause-left.cummulativePause;left.advance(distanceUntilNextPoint);right.advance(distanceUntilNextPoint);if(distanceUntilNextPoint>0){const position2=left.position;const value2=right.cummulativePause-left.cummulativePause;mu.push(position1,1.0-value1/timeWindow,position2,1.0-value2/timeWindow);}}
return mu;}
-function addMutatorUtilization(metricName,eventFilter,timeWindows,rendererHelpers,histograms){const histogramMap=new Map();for(const timeWindow of timeWindows){const histogramOptions={avg:false,count:false,max:false,min:true,std:false,sum:false};const histogram=histograms.createHistogram(`${metricName}-${timeWindow}ms_window`,tr.b.Unit.byName.normalizedPercentage_biggerIsBetter,[],histogramOptions);histogramMap.set(timeWindow,histogram);}
+function addMutatorUtilization(metricName,eventFilter,timeWindows,rendererHelpers,histograms){const histogramMap=new Map();for(const timeWindow of timeWindows){const summaryOptions={avg:false,count:false,max:false,min:true,std:false,sum:false};const description=`The minimum mutator utilization in ${timeWindow}ms time window`;const histogram=histograms.createHistogram(`${metricName}-${timeWindow}ms_window`,tr.b.Unit.byName.normalizedPercentage_biggerIsBetter,[],{summaryOptions,description});histogramMap.set(timeWindow,histogram);}
for(const rendererHelper of rendererHelpers){if(rendererHelper.isChromeTracingUI)continue;const pauses=[];for(const event of rendererHelper.mainThread.sliceGroup.childEvents()){if(eventFilter(event)&&event.end>event.start){pauses.push({start:event.start,end:event.end});}}
pauses.sort((a,b)=>a.start-b.start);const start=rendererHelper.mainThread.bounds.min;const end=rendererHelper.mainThread.bounds.max;for(const timeWindow of timeWindows){const mu=mutatorUtilization(start,end,timeWindow,pauses);histogramMap.get(timeWindow).addSample(mu.min);}}}
-return{addMutatorUtilization,findParent,forcedGCEventName,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_TOP_GC_EVENTS={'BlinkGC.AtomicPhase':'blink-gc-atomic-phase','BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step','BlinkGC.LazySweepInIdle':'blink-gc-lazy-sweep-idle','BlinkGC.LazySweepOnAllocation':'blink-gc-lazy-sweep-allocation'};function blinkGarbageCollectionEventName(event){return BLINK_TOP_GC_EVENTS[event.title];}
-function isNonForcedBlinkGarbageCollectionEvent(event){return event.title in BLINK_TOP_GC_EVENTS&&(!event.args||!event.args.forced)&&!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);}
+return{addMutatorUtilization,findParent,forcedGCEventName,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS={'BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation'};const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS={'BlinkGC.ConcurrentSweep':'blink-gc-sweep-task-background'};const BLINK_TOP_GC_EVENTS=Object.assign({'BlinkGC.AtomicPauseMarkEpilogue':'blink-gc-atomic-pause-mark-epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink-gc-atomic-pause-mark-prologue','BlinkGC.AtomicPauseMarkRoots':'blink-gc-atomic-pause-mark-roots','BlinkGC.AtomicPauseMarkTransitiveClosure':'blink-gc-atomic-pause-mark-transitive-closure','BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact','BlinkGC.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step'},BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_TOP_GC_EVENTS[event.title];}
+function isNonForcedEvent(event){return(!event.args||!event.args.forced)&&!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);}
+function isNonForcedBlinkGarbageCollectionEvent(event){return event.title in BLINK_TOP_GC_EVENTS&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionAtomicPauseEvent(event){return ATOMIC_PAUSE_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionForegroundSweepingEvent(event){return event.title in BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent(event){return event.title in BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS&&isNonForcedEvent(event);}
function isNonNestedNonForcedBlinkGarbageCollectionEvent(event){return isNonForcedBlinkGarbageCollectionEvent(event)&&!tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isGarbageCollectionEvent);}
-function blinkGcMetric(histograms,model){addDurationOfTopEvents(histograms,model);addTotalDurationOfTopEvents(histograms,model);addIdleTimesOfTopEvents(histograms,model);addTotalIdleTimesOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);}
-tr.metrics.MetricRegistry.register(blinkGcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
+function blinkGcMetric(histograms,model){addDurationOfTopEvents(histograms,model);addDurationOfAtomicPause(histograms,model);addTotalDurationOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);addTotalDurationOfForegroundSweeping(histograms,model);addTotalDurationOfBackgroundSweeping(histograms,model);}
+tr.metrics.MetricRegistry.register(blinkGcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
function createNumericForTotalEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:true,max:false,min:false,std:false,sum:true,percentile:[0.90]});return n;}
function createNumericForUnifiedEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:true,max:true,min:false,std:false,sum:true,percentile:[0.90]});return n;}
-function createNumericForIdleTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:false,std:false,sum:true,percentile:[]});return n;}
-function createPercentage(name,numerator,denominator){const histogram=new tr.v.Histogram(name,percentage_biggerIsBetter);if(denominator===0){histogram.addSample(0);}else{histogram.addSample(numerator/denominator);}
-return histogram;}
function addDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionEvent,blinkGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForTopEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
histograms.addHistogram(cpuDuration);});}
+function addDurationOfAtomicPause(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionAtomicPauseEvent,event=>event.args.epoch,function(group,events){const cpuDuration=createNumericForTopEventTime('blink-gc-atomic-pause');cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));histograms.addHistogram(cpuDuration);});}
function addTotalDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionEvent,event=>'blink-gc-total',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
histograms.addHistogram(cpuDuration);});}
-function addIdleTimesOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionEvent,blinkGarbageCollectionEventName,function(name,events){addIdleTimes(histograms,model,name,events);});}
-function addTotalIdleTimesOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionEvent,event=>'blink-gc-total',function(name,events){addIdleTimes(histograms,model,name,events);});}
-function addIdleTimes(histograms,model,name,events){const cpuDuration=createNumericForIdleTime(name+'_cpu');const insideIdle=createNumericForIdleTime(name+'_inside_idle');const outsideIdle=createNumericForIdleTime(name+'_outside_idle');const idleDeadlineOverrun=createNumericForIdleTime(name+'_idle_deadline_overrun');for(const event of events){const idleTask=tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isIdleTask);let inside=0;let overrun=0;if(idleTask){const allottedTime=idleTask.args.allotted_time_ms;if(event.duration>allottedTime){overrun=event.duration-allottedTime;inside=event.cpuDuration*allottedTime/event.duration;}else{inside=event.cpuDuration;}}
-cpuDuration.addSample(event.cpuDuration);insideIdle.addSample(inside);outsideIdle.addSample(event.cpuDuration-inside);idleDeadlineOverrun.addSample(overrun);}
-histograms.addHistogram(idleDeadlineOverrun);histograms.addHistogram(outsideIdle);const percentage=createPercentage(name+'_percentage_idle',insideIdle.sum,cpuDuration.sum);histograms.addHistogram(percentage);}
+function addTotalDurationOfForegroundSweeping(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForegroundSweepingEvent,event=>'blink-gc-sweep-foreground',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);});}
+function addTotalDurationOfBackgroundSweeping(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent,event=>'blink-gc-sweep-background',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);});}
function isV8OrBlinkTopLevelGarbageCollectionEvent(event){return tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent(event)||isNonNestedNonForcedBlinkGarbageCollectionEvent(event);}
function addTotalDurationOfBlinkAndV8TopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8OrBlinkTopLevelGarbageCollectionEvent,event=>'unified-gc-total',function(name,events){const cpuDuration=createNumericForUnifiedEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
histograms.addHistogram(cpuDuration);});}
@@ -8214,18 +8385,19 @@ return processNumerics;}
function cpuProcessMetric(histograms,model){const snapshots=getCpuSnapshotsFromModel(model);const processNumerics=buildNumericsFromSnapshots(snapshots);for(const[processName,processData]of processNumerics){const numeric=processData.numeric;const missingSnapshotCount=snapshots.length-numeric.numValues;for(let i=0;i<missingSnapshotCount;i++){numeric.addSample(0);}
numeric.diagnostics.set('paths',new
tr.v.d.GenericSet([...processData.paths]));histograms.addHistogram(numeric);}}
-tr.metrics.MetricRegistry.register(cpuProcessMetric);return{cpuProcessMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function mediaMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(chromeHelper===undefined)return;for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){const mainThread=rendererHelper.mainThread;if(mainThread===undefined)continue;const compositorThread=rendererHelper.compositorThread;const audioThreads=rendererHelper.process.findAllThreadsNamed('AudioOutputDevice');if(compositorThread===undefined&&audioThreads.length===0)continue;const processData=new PerProcessData();processData.recordPlayStarts(mainThread);if(!processData.hasPlaybacks)continue;if(compositorThread!==undefined){processData.calculateTimeToVideoPlays(compositorThread);processData.calculateDroppedFrameCounts(compositorThread);}
+tr.metrics.MetricRegistry.register(cpuProcessMetric);return{cpuProcessMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function mediaMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(chromeHelper===undefined)return;for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){const mainThread=rendererHelper.mainThread;if(mainThread===undefined)continue;const videoThreads=rendererHelper.process.findAllThreadsMatching(thread=>(thread.name?thread.name.startsWith('ThreadPoolSingleThreadSharedForegroundBlocking'):false));const compositorThread=rendererHelper.compositorThread;if(compositorThread!==undefined){videoThreads.push(compositorThread);}
+const audioThreads=rendererHelper.process.findAllThreadsNamed('AudioOutputDevice');if(audioThreads.length===0&&videoThreads.length===0)continue;const processData=new PerProcessData();processData.recordPlayStarts(mainThread);if(!processData.hasPlaybacks)continue;if(videoThreads.length!==0){processData.calculateTimeToVideoPlays(videoThreads);processData.calculateDroppedFrameCounts(videoThreads);}
if(audioThreads.length!==0){processData.calculateTimeToAudioPlays(audioThreads);}
processData.calculateSeekTimes(mainThread);processData.calculateBufferingTimes(mainThread);processData.addMetricToHistograms(histograms);}}
class PerProcessData{constructor(){this.playbackIdToDataMap_=new Map();}
recordPlayStarts(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::DoLoad'){const id=event.args.id;if(this.playbackIdToDataMap_.has(id)){throw new Error('Unexpected multiple initialization of a media playback');}
this.playbackIdToDataMap_.set(id,new PerPlaybackData(event.start));}}}
get hasPlaybacks(){return this.playbackIdToDataMap_.size>0;}
-calculateTimeToVideoPlays(compositorThread){for(const event of compositorThread.sliceGroup.getDescendantEvents()){if(event.title==='VideoRendererImpl::Render'){this.getPerPlaybackObject_(event.args.id).processVideoRenderTime(event.start);}}}
+calculateTimeToVideoPlays(videoThreads){for(const thread of videoThreads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoRendererImpl::Render'){this.getPerPlaybackObject_(event.args.id).processVideoRenderTime(event.start);}}}}
calculateTimeToAudioPlays(audioThreads){for(const audioThread of audioThreads){for(const event of audioThread.sliceGroup.getDescendantEvents()){if(event.title==='AudioRendererImpl::Render'){this.getPerPlaybackObject_(event.args.id).processAudioRenderTime(event.start);}}}}
calculateSeekTimes(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::DoSeek'){this.getPerPlaybackObject_(event.args.id).processDoSeek(event.args.target,event.start);}else if(event.title==='WebMediaPlayerImpl::OnPipelineSeeked'){this.getPerPlaybackObject_(event.args.id).processOnPipelineSeeked(event.args.target,event.start);}else if(event.title==='WebMediaPlayerImpl::BufferingHaveEnough'){this.getPerPlaybackObject_(event.args.id).processBufferingHaveEnough(event.start);}}}
calculateBufferingTimes(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::OnEnded'){this.getPerPlaybackObject_(event.args.id).processOnEnded(event.start,event.args.duration);}}}
-calculateDroppedFrameCounts(compositorThread){for(const event of compositorThread.sliceGroup.getDescendantEvents()){if(event.title==='VideoFramesDropped'){this.getPerPlaybackObject_(event.args.id).processVideoFramesDropped(event.args.count);}}}
+calculateDroppedFrameCounts(videoThreads){for(const thread of videoThreads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoFramesDropped'){this.getPerPlaybackObject_(event.args.id).processVideoFramesDropped(event.args.count);}}}}
addMetricToHistograms(histograms){for(const[id,playbackData]of this.playbackIdToDataMap_){playbackData.addMetricToHistograms(histograms);}}
getPerPlaybackObject_(playbackId){let perPlaybackObject=this.playbackIdToDataMap_.get(playbackId);if(perPlaybackObject===undefined){perPlaybackObject=new PerPlaybackData(undefined);this.playbackIdToDataMap_.set(playbackId,perPlaybackObject);}
return perPlaybackObject;}}
@@ -8251,40 +8423,62 @@ processOnEnded(playEndTime,duration){if(this.playStart_===undefined)return;if(th
addMetricToHistograms(histograms){this.addSample_(histograms,'time_to_video_play',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.timeToVideoPlay);this.addSample_(histograms,'time_to_audio_play',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.timeToAudioPlay);this.addSample_(histograms,'dropped_frame_count',tr.b.Unit.byName.count_smallerIsBetter,this.droppedFrameCount);for(const[key,value]of this.seekTimes.entries()){const keyString=key.toString().replace('.','_');this.addSample_(histograms,'pipeline_seek_time_'+keyString,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value.pipelineSeekTime);this.addSample_(histograms,'seek_time_'+keyString,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value.seekTime);}
this.addSample_(histograms,'buffering_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.bufferingTime);}
addSample_(histograms,name,unit,sample){if(sample===undefined)return;const histogram=histograms.getHistogramNamed(name);if(histogram===undefined){histograms.createHistogram(name,unit,sample);}else{histogram.addSample(sample);}}}
-tr.metrics.MetricRegistry.register(mediaMetric);return{mediaMetric,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const UNKNOWN_THREAD_NAME='Unknown';const CATEGORY_THREAD_MAP=new Map();CATEGORY_THREAD_MAP.set('all',[/.*/]);CATEGORY_THREAD_MAP.set('browser',[/^Browser Compositor$/,/^CrBrowserMain$/]);CATEGORY_THREAD_MAP.set('display_compositor',[/^VizCompositorThread$/]);CATEGORY_THREAD_MAP.set('fast_path',[/^Browser Compositor$/,/^Chrome_InProcGpuThread$/,/^Compositor$/,/^CrBrowserMain$/,/^CrGpuMain$/,/IOThread/,/^VizCompositorThread$/]);CATEGORY_THREAD_MAP.set('gpu',[/^Chrome_InProcGpuThread$/,/^CrGpuMain$/]);CATEGORY_THREAD_MAP.set('io',[/IOThread/]);CATEGORY_THREAD_MAP.set('raster',[/CompositorTileWorker/]);CATEGORY_THREAD_MAP.set('renderer_compositor',[/^Compositor$/]);CATEGORY_THREAD_MAP.set('renderer_main',[/^CrRendererMain$/]);const ALL_CATEGORIES=[...CATEGORY_THREAD_MAP.keys(),'other'];function addValueToMap_(map,key,value){const oldValue=map.get(key)||0;map.set(key,oldValue+value);}
-function*getCategories_(threadName){let isOther=true;for(const[category,regexps]of CATEGORY_THREAD_MAP){for(const regexp of regexps){if(regexp.test(threadName)){if(category!=='all')isOther=false;yield category;break;}}}
+tr.metrics.MetricRegistry.register(mediaMetric);return{mediaMetric,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const UNKNOWN_THREAD_NAME='Unknown';const CATEGORY_THREAD_MAP=new Map();CATEGORY_THREAD_MAP.set('total_all',[/.*/]);CATEGORY_THREAD_MAP.set('browser',[/^Browser Compositor$/,/^CrBrowserMain$/]);CATEGORY_THREAD_MAP.set('display_compositor',[/^VizCompositorThread$/]);CATEGORY_THREAD_MAP.set('GPU',[/^Chrome_InProcGpuThread$/,/^CrGpuMain$/]);CATEGORY_THREAD_MAP.set('IO',[/IOThread/]);CATEGORY_THREAD_MAP.set('raster',[/CompositorTileWorker/]);CATEGORY_THREAD_MAP.set('renderer_compositor',[/^Compositor$/]);CATEGORY_THREAD_MAP.set('renderer_main',[/^CrRendererMain$/]);CATEGORY_THREAD_MAP.set('total_rendering',[/^Browser Compositor$/,/^Chrome_InProcGpuThread$/,/^Compositor$/,/CompositorTileWorker/,/^CrBrowserMain$/,/^CrGpuMain$/,/^CrRendererMain$/,/IOThread/,/^VizCompositorThread$/]);const ALL_CATEGORIES=[...CATEGORY_THREAD_MAP.keys(),'other'];function addValueToMap_(map,key,value){const oldValue=map.get(key)||0;map.set(key,oldValue+value);}
+function categoryShouldHaveBreakdown(category){return category==='total_all'||category==='total_rendering';}
+function*getCategories_(threadName){let isOther=true;for(const[category,regexps]of CATEGORY_THREAD_MAP){for(const regexp of regexps){if(regexp.test(threadName)){if(category!=='total_all')isOther=false;yield category;break;}}}
if(isOther)yield'other';}
function isSubset_(regexps1,regexps2){for(const r1 of regexps1){if(regexps2.find(r2=>r2.toString()===r1.toString())===undefined){return false;}}
return true;}
-function addCpuUtilizationHistograms(histograms,model,segments,segmentName,shouldNormalize){const histogramMap=new Map();for(const category of ALL_CATEGORIES){const histogram=histograms.createHistogram(`thread_${category}_cpu_time_per_${segmentName}_tbmv2`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(1,50,20),description:`CPU cores per ${segmentName} of a thread group`,summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histogramMap.set(category,histogram);}
+function addCpuUtilizationHistograms(histograms,model,segments,shouldNormalize,segmentCostFunc,histogramNameFunc,description,unit){if(!unit)unit=tr.b.Unit.byName.unitlessNumber;const histogramMap=new Map();for(const category of ALL_CATEGORIES){const histogram=histograms.createHistogram(histogramNameFunc(category),unit,[],{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(1,50,20),description,summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histogramMap.set(category,histogram);}
for(const[category,regexps]of CATEGORY_THREAD_MAP){const relatedCategories=new tr.v.d.RelatedNameMap();const histogram=histogramMap.get(category);for(const[otherCategory,otherRegexps]of CATEGORY_THREAD_MAP){if(otherCategory===category)continue;if(category!=='all'&&!isSubset_(otherRegexps,regexps))continue;const otherHistogram=histogramMap.get(otherCategory);relatedCategories.set(otherCategory,otherHistogram.name);}
if([...relatedCategories.values()].length>0){histogram.diagnostics.set('breakdown',relatedCategories);}}
-for(const segment of segments){const threadValues=new Map();for(const thread of model.getAllThreads()){addValueToMap_(threadValues,thread.name||UNKNOWN_THREAD_NAME,thread.getCpuTimeForRange(segment.boundsRange));}
-const categoryValues=new Map();const breakdowns=new Map();for(const[threadName,coresPerSec]of threadValues){for(const category of getCategories_(threadName)){addValueToMap_(categoryValues,category,coresPerSec);if(!breakdowns.has(category)){breakdowns.set(category,new tr.v.d.Breakdown());}
+for(const segment of segments){const threadValues=new Map();for(const thread of model.getAllThreads()){addValueToMap_(threadValues,thread.name||UNKNOWN_THREAD_NAME,segmentCostFunc(thread,segment));}
+const categoryValues=new Map();const breakdowns=new Map();for(const[threadName,coresPerSec]of threadValues){for(const category of getCategories_(threadName)){addValueToMap_(categoryValues,category,coresPerSec);if(!categoryShouldHaveBreakdown(category))continue;if(!breakdowns.has(category)){breakdowns.set(category,new tr.v.d.Breakdown());}
breakdowns.get(category).set(threadName,coresPerSec);}}
for(const category of ALL_CATEGORIES){let value=categoryValues.get(category)||0;if(shouldNormalize)value/=segment.duration;const diagnostics=new tr.v.d.DiagnosticMap();const breakdown=breakdowns.get(category);if(breakdown)diagnostics.set('breakdown',breakdown);const histogram=histogramMap.get(category);histogram.addSample(value,diagnostics);}}}
-const SUMMARY_OPTIONS={percentile:[0.90,0.95],};return{addCpuUtilizationHistograms,SUMMARY_OPTIONS,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const DISPLAY_EVENT='BenchmarkInstrumentation::DisplayRenderingStats';const DRM_EVENT='DrmEventFlipComplete';const SURFACE_FLINGER_EVENT='vsync_before';const COMPOSITOR_FRAME_PRESENTED_EVENT='FramePresented';const MIN_FRAME_LENGTH=0.5;const PAUSE_THRESHOLD=20;const ASH_ENVIRONMENT='ash';const BROWSER_ENVIRONMENT='browser';function getDisplayCompositorPresentationEvents_(modelHelper){if(!modelHelper||!modelHelper.browserProcess)return[];let events=[];if(modelHelper.surfaceFlingerProcess){events=[...modelHelper.surfaceFlingerProcess.findTopmostSlicesNamed(SURFACE_FLINGER_EVENT)];if(events.length>0)return events;}
+const SUMMARY_OPTIONS={percentile:[0.90,0.95],ci:[0.95],};return{addCpuUtilizationHistograms,SUMMARY_OPTIONS,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const PRESENT_EVENT='Display::FrameDisplayed';const DISPLAY_EVENT='BenchmarkInstrumentation::DisplayRenderingStats';const DRM_EVENT='DrmEventFlipComplete';const SURFACE_FLINGER_EVENT='vsync_before';const COMPOSITOR_FRAME_PRESENTED_EVENT='FramePresented';const MIN_FRAME_LENGTH=0.5;const MIN_FRAME_COUNT=10;const PAUSE_THRESHOLD=20;const ASH_ENVIRONMENT='ash';const BROWSER_ENVIRONMENT='browser';class FrameEvent{constructor(event){this.event_=event;}
+get eventStart(){return this.event_.start;}
+get frameStart(){if(this.event_.title!==DRM_EVENT)return this.event_.start;const data=this.event_.args.data;const TIME=tr.b.UnitScale.TIME;return tr.b.convertUnit(data['vblank.tv_sec'],TIME.SEC,TIME.MILLI_SEC)+
+tr.b.convertUnit(data['vblank.tv_usec'],TIME.MICRO_SEC,TIME.MILLI_SEC);}
+get event(){return this.event_;}}
+class FrameSegment{constructor(frameEvent,duration){this.frameEvent_=frameEvent;this.duration_=duration;this.segment_=new tr.model.um.Segment(frameEvent.eventStart,duration);this.length_=undefined;}
+updateLength(refreshPeriod){this.length_=this.duration_/refreshPeriod;}
+get segment(){return this.segment_;}
+get boundsRange(){return this.segment_.boundsRange;}
+get length(){return this.length_;}
+get duration(){return this.duration_;}
+get event(){return this.frameEvent_.event;}}
+function getDisplayCompositorPresentationEventsExp_(modelHelper){if(!modelHelper)return[];function findEventsFromProcess(process){const events=[];for(const event of process.findTopmostSlicesNamed(PRESENT_EVENT)){events.push(event);}
+return events;}
+if(modelHelper.gpuHelper){const events=findEventsFromProcess(modelHelper.gpuHelper.process);if(events.length>0)return events;}
+if(!modelHelper.browserProcess)return[];return findEventsFromProcess(modelHelper.browserProcess);}
+function getDisplayCompositorPresentationEvents_(modelHelper){if(!modelHelper||!modelHelper.browserProcess)return[];let events=[];if(modelHelper.surfaceFlingerProcess){events=[...modelHelper.surfaceFlingerProcess.findTopmostSlicesNamed(SURFACE_FLINGER_EVENT)];if(events.length>0)return events;}
if(modelHelper.gpuHelper){const gpuProcess=modelHelper.gpuHelper.process;events=[...gpuProcess.findTopmostSlicesNamed(DRM_EVENT)];if(events.length>0)return events;events=[...gpuProcess.findTopmostSlicesNamed(DISPLAY_EVENT)];if(events.length>0)return events;}
return[...modelHelper.browserProcess.findTopmostSlicesNamed(DISPLAY_EVENT)];}
function getUIPresentationEvents_(modelHelper){if(!modelHelper||!modelHelper.browserProcess)return[];const legacyEvents=[];const eventsByEnvironment={};eventsByEnvironment[ASH_ENVIRONMENT]=[];eventsByEnvironment[BROWSER_ENVIRONMENT]=[];for(const event of modelHelper.browserProcess.findTopmostSlicesNamed(COMPOSITOR_FRAME_PRESENTED_EVENT)){if(!('environment'in event.args)){legacyEvents.push(event);}else{eventsByEnvironment[event.args.environment].push(event);}}
if(eventsByEnvironment[ASH_ENVIRONMENT].length>0){return eventsByEnvironment[ASH_ENVIRONMENT];}
if(eventsByEnvironment[BROWSER_ENVIRONMENT].length>0){return eventsByEnvironment[BROWSER_ENVIRONMENT];}
return legacyEvents;}
-function addSurfaceFlingerHistograms_(histograms,frameSegments,refreshPeriod){let frameLengths=frameSegments.map(x=>x.duration/refreshPeriod);frameLengths=frameLengths.filter(length=>length>=MIN_FRAME_LENGTH);histograms.createHistogram('frame_lengths',tr.b.Unit.byName.unitlessNumber_smallerIsBetter,frameLengths,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,5,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Frame times in vsyncs.'});histograms.createHistogram('avg_surface_fps',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,frameLengths.length/tr.b.convertUnit(tr.b.math.Statistics.sum(frameSegments,x=>x.duration),tr.b.UnitScale.TIME.MILLI_SEC,tr.b.UnitScale.TIME.SEC),{description:'Average frames per second.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});let jankCount=0;for(let i=1;i<frameLengths.length;i++){const change=Math.round(frameLengths[i]-frameLengths[i-1]);if(change>0&&change<PAUSE_THRESHOLD)jankCount++;}
-histograms.createHistogram('jank_count',tr.b.Unit.byName.unitlessNumber_smallerIsBetter,jankCount,{description:'Number of changes in frame rate.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
-function computeFrameSegments_(timestamps,segments){const frameSegments=[];for(const segment of segments){const filtered=segment.boundsRange.filterArray(timestamps,x=>x[0]);for(let i=1;i<filtered.length;i++){const duration=filtered[i][1]-filtered[i-1][1];frameSegments.push(new tr.model.um.Segment(filtered[i-1][0],duration));}}
+function computeFrameSegments_(events,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const frameEvents=events.map(e=>new FrameEvent(e));const frameSegments=[];for(const segment of segments){const filtered=segment.boundsRange.filterArray(frameEvents,x=>x.eventStart);if(filtered.length<minFrameCount)continue;for(let i=1;i<filtered.length;i++){const duration=filtered[i].frameStart-filtered[i-1].frameStart;frameSegments.push(new FrameSegment(filtered[i-1],duration));}}
return frameSegments;}
-function addBasicFrameTimeHistograms_(histograms,frameSegments,prefix){const frameTimes=frameSegments.map(x=>x.duration);histograms.createHistogram(`${prefix}frame_times`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,frameTimes,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),description:'Raw frame times.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram(`${prefix}percentage_smooth`,tr.b.Unit.byName.unitlessNumber_biggerIsBetter,100*tr.b.math.Statistics.sum(frameTimes,(x=>(x<17?1:0)))/frameTimes.length,{description:'Percentage of frames that were hitting 60 FPS.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
-function addFrameTimeHistograms(histograms,model,segments){const events=getDisplayCompositorPresentationEvents_(model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper));if(!events)return;const timestamps=events.map(event=>[event.start,event.title!==DRM_EVENT?event.start:(tr.b.convertUnit(event.args.data['vblank.tv_sec'],tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)+
-tr.b.convertUnit(event.args.data['vblank.tv_usec'],tr.b.UnitScale.TIME.MICRO_SEC,tr.b.UnitScale.TIME.MILLI_SEC))]);const frameSegments=computeFrameSegments_(timestamps,segments);addBasicFrameTimeHistograms_(histograms,frameSegments,'');tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,'frame',false);for(const metadata of model.metadata){if(metadata.value&&metadata.value.surface_flinger){addSurfaceFlingerHistograms_(histograms,frameSegments,metadata.value.surface_flinger.refresh_period);return;}}}
-function addUIFrameTimeHistograms(histograms,model,segments){const events=getUIPresentationEvents_(model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper));if(!events)return;const timestamps=events.map(event=>[event.start,event.start]);const frameSements=computeFrameSegments_(timestamps,segments);addBasicFrameTimeHistograms_(histograms,frameSements,'ui_');}
-return{addFrameTimeHistograms,addUIFrameTimeHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const BEGIN_SCROLL_UPDATE_COMP_NAME='LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT';const END_COMP_NAME='INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT';function*iterAsyncEvents_(processHelpers,ranges,processEventFn){for(const processHelper of processHelpers){const process=processHelper.process;for(const event of process.getDescendantEventsInSortedRanges(ranges,container=>container instanceof tr.model.AsyncSliceGroup)){yield*processEventFn(event);}}}
-function*processInputLatencyEvent(event){if(!(event instanceof tr.e.cc.InputLatencyAsyncSlice))return;const latency=event.inputLatency;if(latency===undefined)return;yield tr.b.Unit.timestampFromUs(latency);}
+function addBasicFrameTimeHistograms_(histograms,frameSegments,prefix){const frameTimes=(frameSegments.length===0)?[0]:frameSegments.map(x=>x.duration);histograms.createHistogram(`${prefix}frame_times`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,frameTimes,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),description:'Raw frame times.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram(`${prefix}percentage_smooth`,tr.b.Unit.byName.unitlessNumber_biggerIsBetter,100*tr.b.math.Statistics.sum(frameTimes,(x=>(x<17?1:0)))/frameTimes.length,{description:'Percentage of frames that were hitting 60 FPS.',summaryOptions:{},});}
+function addFrameTimeHistograms(histograms,model,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const events=getDisplayCompositorPresentationEvents_(modelHelper);if(!events)return;addFrameTimeHistogramsHelper(histograms,model,segments,events,'',true,minFrameCount);const eventsExp=getDisplayCompositorPresentationEventsExp_(modelHelper);if(eventsExp&&eventsExp.length>0){addFrameTimeHistogramsHelper(histograms,model,segments,eventsExp,'exp_',minFrameCount);}}
+function addFrameTimeHistogramsHelper(histograms,model,segments,events,prefix,addCpuMetrics,minFrameCount){const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,prefix+'');if(addCpuMetrics){tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,false,(thread,segment)=>thread.getCpuTimeForRange(segment.boundsRange),category=>`thread_${category}_cpu_time_per_frame`,'CPU cores of a thread group per frame',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,false,(thread,segment)=>thread.getNumToplevelSlicesForRange(segment.boundsRange),category=>`tasks_per_frame_${category}`,'Number of tasks of a thread group per frame',tr.b.Unit.byName.unitlessNumber_smallerIsBetter);}
+const refreshPeriod=getRefreshPeriod(model,frameSegments.map(fs=>fs.boundsRange));frameSegments.forEach(fs=>fs.updateLength(refreshPeriod));const validFrames=frameSegments.filter(fs=>fs.length>=MIN_FRAME_LENGTH);const totalFrameDuration=tr.b.math.Statistics.sum(frameSegments,fs=>fs.duration);addJankCountHistograms(histograms,validFrames,prefix);const frameLengths=validFrames.map(frame=>frame.length);histograms.createHistogram(prefix+'frame_lengths',tr.b.Unit.byName.unitlessNumber_smallerIsBetter,frameLengths,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,5,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Frame times in vsyncs.'});histograms.createHistogram(prefix+'avg_surface_fps',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,frameLengths.length/tr.b.convertUnit(totalFrameDuration,tr.b.UnitScale.TIME.MILLI_SEC,tr.b.UnitScale.TIME.SEC),{description:'Average frames per second.',summaryOptions:{},});}
+function addUIFrameTimeHistograms(histograms,model,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const events=getUIPresentationEvents_(model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper));if(events.length===0)return;const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,'ui_');}
+function addJankCountHistograms(histograms,validFrames,prefix){const jankEvents=[];for(let i=1;i<validFrames.length;i++){const change=Math.round((validFrames[i].length-validFrames[i-1].length));if(change>0&&change<PAUSE_THRESHOLD){jankEvents.push(validFrames[i].event);}}
+const jankCount=jankEvents.length;const diagnostics=new tr.v.d.DiagnosticMap();diagnostics.set('events',new tr.v.d.RelatedEventSet(jankEvents));diagnostics.set('timestamps',new tr.v.d.GenericSet(jankEvents.map(e=>e.start)));const histogram=histograms.createHistogram(prefix+'jank_count',tr.b.Unit.byName.count_smallerIsBetter,{value:jankCount,diagnostics},{description:'Number of changes in frame rate.',summaryOptions:{},});}
+function getRefreshPeriod(model,ranges){for(const metadata of model.metadata){if(metadata.value&&metadata.value.surface_flinger){return metadata.value.surface_flinger.refresh_period;}}
+const FRAME_LENGTH=1000.0/60;const BEGIN_FRAME_ARGS='Scheduler::BeginFrame';const FRAME_INTERVAL='interval_us';const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.compositorThread===undefined)continue;const slices=rendererHelper.compositorThread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==BEGIN_FRAME_ARGS)continue;const data=slice.args.args;if(!(FRAME_INTERVAL in data)){throw new Error(`${FRAME_INTERVAL} is missing`);}
+return tr.b.convertUnit(data[FRAME_INTERVAL],tr.b.UnitScale.TIME.MICRO_SEC,tr.b.UnitScale.TIME.MILLI_SEC);}}
+return FRAME_LENGTH;}
+return{addFrameTimeHistograms,addUIFrameTimeHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const RGB_DECODE_EVENT='ImageFrameGenerator::decode';const YUV_DECODE_EVENT='ImageFrameGenerator::decodeToYUV';const BLINK_GPU_RASTER_DECODE_EVENT='GpuImageDecodeCache::DecodeImage';const BLINK_SOFTWARE_RASTER_DECODE_EVENT='SoftwareImageDecodeCache::'+'DecodeImageInTask';function getImageDecodingEvents_(modelHelper,ranges){if(!modelHelper||!modelHelper.rendererHelpers)return[];const events=[];for(const renderer of Object.values(modelHelper.rendererHelpers)){for(const thread of renderer.rasterWorkerThreads){const slices=thread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title===RGB_DECODE_EVENT||slice.title===YUV_DECODE_EVENT||slice.title===BLINK_GPU_RASTER_DECODE_EVENT||slice.title===BLINK_SOFTWARE_RASTER_DECODE_EVENT){events.push(slice);}}}}
+return events;}
+function addImageDecodeTimeHistograms(histograms,model,segments){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const decodeEvents=getImageDecodingEvents_(modelHelper,segments.map(s=>s.boundsRange));if(!decodeEvents)return;histograms.createHistogram('rgb_decode_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===RGB_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of the Blink RGB decoding path for a chunk '+'of image data (possibly the whole image).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('yuv_decode_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===YUV_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of the Blink YUV decoding path for a '+'chunk of image data (possibly the whole image).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('blink_decode_time_gpu_rasterization',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===BLINK_GPU_RASTER_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of decoding and scaling within the '+'GpuImageDecodeCache for a chunk of image data '+'(possibly the whole image)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('blink_decode_time_software_rasterization',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===BLINK_SOFTWARE_RASTER_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of decoding and scaling within the '+'SoftwareImageDecodeCache for a chunk of image data '+'(possibly the whole image)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
+return{addImageDecodeTimeHistograms};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const BEGIN_SCROLL_UPDATE_COMP_NAME='LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT';const END_COMP_NAME='INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT';function*iterAsyncEvents_(processHelpers,ranges,processEventFn){for(const processHelper of processHelpers){const process=processHelper.process;for(const event of process.getDescendantEventsInSortedRanges(ranges,container=>container instanceof tr.model.AsyncSliceGroup)){yield*processEventFn(event);}}}
function*processLatencyEvent(event){if(event.title!=='Latency::ScrollUpdate'||!('data'in event.args)||!(END_COMP_NAME in event.args.data)){return;}
const data=event.args.data;const endTime=data[END_COMP_NAME].time;if(BEGIN_SCROLL_UPDATE_COMP_NAME in data){yield tr.b.Unit.timestampFromUs(endTime-data[BEGIN_SCROLL_UPDATE_COMP_NAME].time);}else{throw new Error('LatencyInfo has no begin component');}}
-function*processGestureScrollUpdateLatencyEvent(event){if(event.title!=='InputLatency::GestureScrollUpdate')return;if(!(event instanceof tr.e.cc.InputLatencyAsyncSlice)){throw new Error('Gesture scroll update latency event is not an '+'instance of tr.e.cc.InputLatencyAsyncSlice');}
-const latency=event.inputLatency;if(latency===undefined)return;yield[event.start,tr.b.Unit.timestampFromUs(latency)];}
-function addLatencyHistograms(histograms,model,segments){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper)return;const ranges=segments.map(s=>s.boundsRange);const inputEventLatencies=[...iterAsyncEvents_(modelHelper.browserHelpers,ranges,processInputLatencyEvent)];histograms.createHistogram('input_event_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,inputEventLatencies,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Input event latencies.'});const mainThreadScrollLatencies=[...iterAsyncEvents_(Object.values(modelHelper.rendererHelpers),ranges,processLatencyEvent)];histograms.createHistogram('main_thread_scroll_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,mainThreadScrollLatencies,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,50),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Main thread scroll latencies.'});const gestureScrollUpdateLatencies=[...iterAsyncEvents_(modelHelper.browserHelpers,ranges,processGestureScrollUpdateLatencyEvent)].sort();if(gestureScrollUpdateLatencies.length){histograms.createHistogram('first_gesture_scroll_update_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,gestureScrollUpdateLatencies[0][1],{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Latency of the first gesture scroll update.'});}}
+function addLatencyHistograms(histograms,model,segments){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper)return;const ranges=segments.map(s=>s.boundsRange);const mainThreadScrollLatencies=[...iterAsyncEvents_(Object.values(modelHelper.rendererHelpers),ranges,processLatencyEvent)];histograms.createHistogram('main_thread_scroll_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,mainThreadScrollLatencies,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,50),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Main thread scroll latencies.'});}
return{addLatencyHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){function eventIsValidGraphicsEvent_(event,eventMap){if(event.title!=='Graphics.Pipeline'||!event.bindId||!event.args||!event.args.step){return false;}
const bindId=event.bindId;if(eventMap.has(bindId)&&event.args.step in eventMap.get(bindId)){if(event.args.step==='IssueBeginFrame'||event.args.step==='ReceiveBeginFrame'){throw new Error('Unexpected duplicate step: '+event.args.step);}
return false;}
@@ -8295,25 +8489,31 @@ function generateBreakdownForDraw_(drawEvent){const breakdown=new tr.v.d.Breakdo
return breakdown;}
function getDisplayCompositorThread_(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const gpuHelper=chromeHelper.gpuHelper;if(gpuHelper){const thread=gpuHelper.process.findAtMostOneThreadNamed('VizCompositorThread');if(thread){return thread;}}
if(!chromeHelper.browserProcess)return null;return chromeHelper.browserProcess.findAtMostOneThreadNamed('CrBrowserMain');}
+function getRasterTaskTimes(sourceFrameNumber,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const renderers=modelHelper.telemetryHelper.renderersWithIR;if(renderers.length===0)return;const rasterThreads=renderers[0].rasterWorkerThreads;let earliestStart=undefined;let lastEnd=undefined;for(const rasterThread of rasterThreads){for(const slice of[...rasterThread.findTopmostSlicesNamed('TaskGraphRunner::RunTask')]){if(slice.args&&slice.args.source_frame_number_&&slice.args.source_frame_number_===sourceFrameNumber){if(earliestStart===undefined||slice.start<earliestStart){earliestStart=slice.start;}
+if(lastEnd===undefined||slice.end>lastEnd){lastEnd=slice.end;}}}}
+return{start:earliestStart,end:lastEnd};}
function addPipelineHistograms(histograms,model,segments){const ranges=segments.map(s=>s.boundsRange);const bindEvents=new Map();for(const thread of model.getAllThreads()){for(const event of thread.sliceGroup.childEvents()){if(!eventIsValidGraphicsEvent_(event,bindEvents))continue;for(const range of ranges){if(range.containsExplicitRangeInclusive(event.start,event.end)){if(!bindEvents.has(event.bindId))bindEvents.set(event.bindId,{});break;}}
if(bindEvents.has(event.bindId)){bindEvents.get(event.bindId)[event.args.step]=event;}}}
const dcThread=getDisplayCompositorThread_(model);const drawEvents={};if(dcThread){const events=[...dcThread.findTopmostSlicesNamed('Graphics.Pipeline.DrawAndSwap')];for(const segment of segments){const filteredEvents=segment.boundsRange.filterArray(events,evt=>evt.start);for(const event of filteredEvents){if((event.args&&event.args.status==='canceled')||!event.id.startsWith(':ptr:')){continue;}
const id=parseInt(event.id.substring(5),16);if(id in drawEvents){throw new Error('Duplicate draw events: '+id);}
drawEvents[id]=event;}}}
-const issueToReceipt=histograms.createHistogram('pipeline:begin_frame_transport',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency of begin-frame message from the display '+'compositor to the client, including the IPC latency and task-'+'queue time in the client.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const receiptToSubmit=histograms.createHistogram('pipeline:begin_frame_to_frame_submission',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame reception and '+'CompositorFrame submission in the renderer.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const submitToAggregate=histograms.createHistogram('pipeline:frame_submission_to_display',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between CompositorFrame submission in the '+'renderer to display in the display-compositor, including IPC '+'latency, task-queue time in the display-compositor, and '+'additional processing (e.g. surface-sync etc.)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const aggregateToDraw=histograms.createHistogram('pipeline:draw',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'How long it takes for the gpu-swap step.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});for(const flow of bindEvents.values()){if(!flow.IssueBeginFrame||!flow.ReceiveBeginFrame||!flow.SubmitCompositorFrame||!flow.SurfaceAggregation){continue;}
+const issueToReceipt=histograms.createHistogram('pipeline:begin_frame_transport',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency of begin-frame message from the display '+'compositor to the client, including the IPC latency and task-'+'queue time in the client.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const issueToRasterStart=histograms.createHistogram('pipeline:begin_frame_to_raster_start',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame message and '+'the beginning of the first CompositorTask run in the compositor.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const issueToRasterEnd=histograms.createHistogram('pipeline:begin_frame_to_raster_end',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame message and '+'the end of the last CompositorTask run in the compositor.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const receiptToSubmit=histograms.createHistogram('pipeline:begin_frame_to_frame_submission',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame reception and '+'CompositorFrame submission in the renderer.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const submitToAggregate=histograms.createHistogram('pipeline:frame_submission_to_display',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between CompositorFrame submission in the '+'renderer to display in the display-compositor, including IPC '+'latency, task-queue time in the display-compositor, and '+'additional processing (e.g. surface-sync etc.)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const aggregateToDraw=histograms.createHistogram('pipeline:draw',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'How long it takes for the gpu-swap step.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});for(const flow of bindEvents.values()){if(!flow.IssueBeginFrame||!flow.ReceiveBeginFrame||!flow.SubmitCompositorFrame||!flow.SurfaceAggregation){continue;}
issueToReceipt.addSample(flow.ReceiveBeginFrame.start-
-flow.IssueBeginFrame.start);receiptToSubmit.addSample(flow.SubmitCompositorFrame.end-flow.ReceiveBeginFrame.start,{breakdown:generateBreakdownForCompositorPipelineInClient_(flow)});submitToAggregate.addSample(flow.SurfaceAggregation.end-flow.SubmitCompositorFrame.end,{breakdown:generateBreakdownForCompositorPipelineInService_(flow)});if(flow.SurfaceAggregation.args&&flow.SurfaceAggregation.args.display_trace){const displayTrace=flow.SurfaceAggregation.args.display_trace;if(!(displayTrace in drawEvents))continue;const drawEvent=drawEvents[displayTrace];aggregateToDraw.addSample(drawEvent.duration,{breakdown:generateBreakdownForDraw_(drawEvent)});}}}
+flow.IssueBeginFrame.start);receiptToSubmit.addSample(flow.SubmitCompositorFrame.end-flow.ReceiveBeginFrame.start,{breakdown:generateBreakdownForCompositorPipelineInClient_(flow)});submitToAggregate.addSample(flow.SurfaceAggregation.end-flow.SubmitCompositorFrame.end,{breakdown:generateBreakdownForCompositorPipelineInService_(flow)});if(flow.SubmitCompositorFrame.parentSlice){const sourceFrameNumber=flow.SubmitCompositorFrame.parentSlice.args.source_frame_number_;const rasterDuration=getRasterTaskTimes(sourceFrameNumber,model);if(rasterDuration&&rasterDuration.start&&rasterDuration.end){const receiveToStart=rasterDuration.start-
+flow.ReceiveBeginFrame.start;const receiveToEnd=rasterDuration.end-flow.ReceiveBeginFrame.end;if(receiveToEnd>0){issueToRasterStart.addSample(receiveToStart>0?receiveToStart:0);issueToRasterEnd.addSample(receiveToEnd);}}}
+if(flow.SurfaceAggregation.args&&flow.SurfaceAggregation.args.display_trace){const displayTrace=flow.SurfaceAggregation.args.display_trace;if(!(displayTrace in drawEvents))continue;const drawEvent=drawEvents[displayTrace];aggregateToDraw.addSample(drawEvent.duration,{breakdown:generateBreakdownForDraw_(drawEvent)});}}}
return{addPipelineHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const IMPL_THREAD_RENDERING_STATS_EVENT='BenchmarkInstrumentation::ImplThreadRenderingStats';const VISIBLE_CONTENT_DATA='visible_content_area';const APPROXIMATED_VISIBLE_CONTENT_DATA='approximated_visible_content_area';const CHECKERBOARDED_VISIBLE_CONTENT_DATA='checkerboarded_visible_content_area';function addPixelsHistograms(histograms,model,segments){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;const approximatedPixelPercentages=[];const checkerboardedPixelPercentages=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.compositorThread===undefined)continue;const slices=rendererHelper.compositorThread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==IMPL_THREAD_RENDERING_STATS_EVENT)continue;const data=slice.args.data;if(!(VISIBLE_CONTENT_DATA in data)){throw new Error(`${VISIBLE_CONTENT_DATA} is missing`);}
const visibleContentArea=data[VISIBLE_CONTENT_DATA];if(visibleContentArea===0){continue;}
if(APPROXIMATED_VISIBLE_CONTENT_DATA in data){approximatedPixelPercentages.push(data[APPROXIMATED_VISIBLE_CONTENT_DATA]/visibleContentArea);}
if(CHECKERBOARDED_VISIBLE_CONTENT_DATA in data){checkerboardedPixelPercentages.push(data[CHECKERBOARDED_VISIBLE_CONTENT_DATA]/visibleContentArea);}}}
-histograms.createHistogram('mean_pixels_approximated',tr.b.Unit.byName.normalizedPercentage_smallerIsBetter,100*tr.b.math.Statistics.mean(approximatedPixelPercentages),{description:'Percentage of pixels that were approximated '+'(checkerboarding, low-resolution tiles, etc.).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('mean_pixels_checkerboarded',tr.b.Unit.byName.normalizedPercentage_smallerIsBetter,100*tr.b.math.Statistics.mean(checkerboardedPixelPercentages),{description:'Percentage of pixels that were checkerboarded.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
+histograms.createHistogram('mean_pixels_approximated',tr.b.Unit.byName.normalizedPercentage_smallerIsBetter,100*tr.b.math.Statistics.mean(approximatedPixelPercentages),{description:'Percentage of pixels that were approximated '+'(checkerboarding, low-resolution tiles, etc.).',summaryOptions:{},});histograms.createHistogram('mean_pixels_checkerboarded',tr.b.Unit.byName.normalizedPercentage_smallerIsBetter,100*tr.b.math.Statistics.mean(checkerboardedPixelPercentages),{description:'Percentage of pixels that were checkerboarded.',summaryOptions:{},});}
return{addPixelsHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const BEGIN_MAIN_FRAME_EVENT='ThreadProxy::BeginMainFrame';const SEND_BEGIN_FRAME_EVENT='ThreadProxy::ScheduledActionSendBeginMainFrame';function getEventTimesByBeginFrameId_(thread,title,ranges){const out=new Map();const slices=thread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==title)continue;const id=slice.args.begin_frame_id;if(id===undefined)throw new Error('Event is missing begin_frame_id');if(out.has(id))throw new Error(`There must be exactly one ${title}`);out.set(id,slice.start);}
return out;}
function addQueueingDurationHistograms(histograms,model,segments){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;let targetRenderers=chromeHelper.telemetryHelper.renderersWithIR;if(targetRenderers.length===0){targetRenderers=Object.values(chromeHelper.rendererHelpers);}
const queueingDurations=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of targetRenderers){const mainThread=rendererHelper.mainThread;const compositorThread=rendererHelper.compositorThread;if(mainThread===undefined||compositorThread===undefined)continue;const beginMainFrameTimes=getEventTimesByBeginFrameId_(mainThread,BEGIN_MAIN_FRAME_EVENT,ranges);const sendBeginFrameTimes=getEventTimesByBeginFrameId_(compositorThread,SEND_BEGIN_FRAME_EVENT,ranges);for(const[id,time]of sendBeginFrameTimes){queueingDurations.push(beginMainFrameTimes.get(id)-time);}}
histograms.createHistogram('queueing_durations',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,queueingDurations,{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(0.01,2,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Time between ScheduledActionSendBeginMainFrame in '+'the compositor thread and the corresponding '+'BeginMainFrame in the main thread.'});}
-return{addQueueingDurationHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const GESTURE_EVENT='SyntheticGestureController::running';function renderingMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;const segments=chromeHelper.telemetryHelper.segments;if(segments.length>0){tr.metrics.rendering.addFrameTimeHistograms(histograms,model,segments);tr.metrics.rendering.addLatencyHistograms(histograms,model,segments);tr.metrics.rendering.addPipelineHistograms(histograms,model,segments);tr.metrics.rendering.addPixelsHistograms(histograms,model,segments);tr.metrics.rendering.addQueueingDurationHistograms(histograms,model,segments);}
+return{addQueueingDurationHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const GESTURE_EVENT='SyntheticGestureController::running';function renderingMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;let segments=chromeHelper.telemetryHelper.irSegments;if(segments.length===0){segments=chromeHelper.telemetryHelper.animationSegments;}
+if(segments.length>0){tr.metrics.rendering.addFrameTimeHistograms(histograms,model,segments);tr.metrics.rendering.addImageDecodeTimeHistograms(histograms,model,segments);tr.metrics.rendering.addLatencyHistograms(histograms,model,segments);tr.metrics.rendering.addPipelineHistograms(histograms,model,segments);tr.metrics.rendering.addPixelsHistograms(histograms,model,segments);tr.metrics.rendering.addQueueingDurationHistograms(histograms,model,segments);}
const uiSegments=chromeHelper.telemetryHelper.uiSegments;if(uiSegments.length>0){tr.metrics.rendering.addUIFrameTimeHistograms(histograms,model,chromeHelper.telemetryHelper.uiSegments);}}
tr.metrics.MetricRegistry.register(renderingMetric,{requiredCategories:['benchmark','toplevel'],});return{renderingMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function sampleExceptionMetric(histograms,model){const hist=new tr.v.Histogram('foo',tr.b.Unit.byName.sizeInBytes_smallerIsBetter);hist.addSample(9);hist.addSample(91,{bar:new tr.v.d.GenericSet([{hello:42}])});for(const expectation of model.userModel.expectations){if(expectation instanceof tr.model.um.ResponseExpectation){}else if(expectation instanceof tr.model.um.AnimationExpectation){}else if(expectation instanceof tr.model.um.IdleExpectation){}else if(expectation instanceof tr.model.um.LoadExpectation){}}
const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const[pid,process]of Object.entries(model.processes)){}
@@ -8355,39 +8555,83 @@ function addIdleAndBlockByNetworkBreakdown_(breakdownTree,mainThreadEvents,netwo
breakdownTree.blocked_on_network={total:Math.max(totalBlockedDuration,0),events:{}};}
function generateWallClockTimeBreakdownTree(mainThread,networkEvents,rangeOfInterest){const breakdownTree=generateTimeBreakdownTree(mainThread,rangeOfInterest,getWallClockSelfTime_);const mainThreadEventsInRange=tr.model.helpers.getSlicesIntersectingRange(rangeOfInterest,mainThread.sliceGroup.topLevelSlices);addIdleAndBlockByNetworkBreakdown_(breakdownTree,mainThreadEventsInRange,networkEvents,rangeOfInterest);return breakdownTree;}
function generateCpuTimeBreakdownTree(mainThread,rangeOfInterest){return generateTimeBreakdownTree(mainThread,rangeOfInterest,getCPUSelfTime_);}
-return{generateTimeBreakdownTree,generateWallClockTimeBreakdownTree,generateCpuTimeBreakdownTree,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LONG_TASK_THRESHOLD_MS=50;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const RelatedEventSet=tr.v.d.RelatedEventSet;const hasCategoryAndName=tr.metrics.sh.hasCategoryAndName;const EventFinderUtils=tr.e.chrome.EventFinderUtils;function getNetworkEventsInRange(process,range){const networkEvents=[];for(const thread of Object.values(process.threads)){const threadHelper=new tr.model.helpers.ChromeThreadHelper(thread);const events=threadHelper.getNetworkEvents();for(const event of events){if(range.intersectsExplicitRangeInclusive(event.start,event.end)){networkEvents.push(event);}}}
-return networkEvents;}
-function createBreakdownDiagnostic(breakdownTree){const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownTree){breakdownDiagnostic.set(label,breakdownTree[label].total);}
+return{generateTimeBreakdownTree,generateWallClockTimeBreakdownTree,generateCpuTimeBreakdownTree,};});'use strict';tr.exportTo('tr.e.chrome',function(){const LCP_CANDIDATE_EVENT_TITLE='NavStartToLargestContentfulPaint::Candidate::AllFrames::UKM';const LCP_INVALIDATE_EVENT_TITLE='NavStartToLargestContentfulPaint::Invalidate::AllFrames::UKM';class LcpEvent{constructor(event){if(!LcpInvalidateEvent.isLcpInvalidateEvent(event)&&!LcpCandidateEvent.isLcpCandidateEvent(event)){throw new Error('The LCP event should be either a candidate event or'+'an invalidate event.');}
+if(event.start===undefined||event.args.main_frame_tree_node_id===undefined){throw new Error('The LCP event is in unexpected format.');}
+this.start=event.start;this.mainFrameTreeNodeId=event.args.main_frame_tree_node_id;}}
+class LcpCandidateEvent extends LcpEvent{constructor(event){super(event);const{durationInMilliseconds,size,type,inMainFrame}=event.args.data;if(durationInMilliseconds===undefined||size===undefined||type===undefined||inMainFrame===undefined||event.args.main_frame_tree_node_id===undefined||!LcpCandidateEvent.isLcpCandidateEvent(event)){throw new Error('The LCP candidate event is in unexpected format.');}
+this.durationInMilliseconds=durationInMilliseconds;this.size=size;this.type=type;this.inMainFrame=inMainFrame;}
+static isLcpCandidateEvent(event){return event.title===LCP_CANDIDATE_EVENT_TITLE;}}
+class LcpInvalidateEvent extends LcpEvent{constructor(event){super(event);if(!LcpInvalidateEvent.isLcpInvalidateEvent(event)){throw new Error('The LCP invalidate event is in unexpected format.');}}
+static isLcpInvalidateEvent(event){return event.title===LCP_INVALIDATE_EVENT_TITLE;}}
+class LargestContentfulPaint{constructor(allBrowserEvents){this.allBrowserEvents=allBrowserEvents;}
+findCandidates(){const finalLcpEvents=this.findFinalLcpEventOfEachNavigation(this.allBrowserEvents);const finalCandidates=finalLcpEvents.filter(finalLcpEvent=>!LcpInvalidateEvent.isLcpInvalidateEvent(finalLcpEvent));return finalCandidates;}
+findFinalLcpEventOfEachNavigation(allBrowserEvents){const lcpEvents=[];for(const lcpEvent of allBrowserEvents){if(LcpCandidateEvent.isLcpCandidateEvent(lcpEvent)){lcpEvents.push(new LcpCandidateEvent(lcpEvent));}else if(LcpInvalidateEvent.isLcpInvalidateEvent(lcpEvent)){lcpEvents.push(new LcpInvalidateEvent(lcpEvent));}}
+const lcpEventsGroupedByNavigation=new Map();for(const e of lcpEvents){const key=e.mainFrameTreeNodeId;if(!lcpEventsGroupedByNavigation.has(key)){lcpEventsGroupedByNavigation[key]=[];}
+lcpEventsGroupedByNavigation[key].push(e);}
+const finalLcpEventOfEachNaivgation=[];for(const lcpEventList of Object.values(lcpEventsGroupedByNavigation)){lcpEventList.sort((a,b)=>a.start-b.start);finalLcpEventOfEachNaivgation.push(lcpEventList[lcpEventList.length-1]);}
+return finalLcpEventOfEachNaivgation;}}
+return{LCP_CANDIDATE_EVENT_TITLE,LCP_INVALIDATE_EVENT_TITLE,LargestContentfulPaint,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LONG_TASK_THRESHOLD_MS=50;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const RelatedEventSet=tr.v.d.RelatedEventSet;const hasCategoryAndName=tr.metrics.sh.hasCategoryAndName;const EventFinderUtils=tr.e.chrome.EventFinderUtils;function createBreakdownDiagnostic(breakdownTree){const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownTree){breakdownDiagnostic.set(label,breakdownTree[label].total);}
return breakdownDiagnostic;}
-const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const TIME_TO_INTERACTIVE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,40e3,35).addExponentialBins(80e3,15);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
+const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const TIME_TO_INTERACTIVE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,40e3,35).addExponentialBins(80e3,15);const LAYOUT_SHIFT_SCORE_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,50,25);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
return snapshot;}
function findAllEvents(rendererHelper,category,title){const targetEvents=[];for(const ev of rendererHelper.process.getDescendantEvents()){if(!hasCategoryAndName(ev,category,title))continue;targetEvents.push(ev);}
return targetEvents;}
+function getMostRecentValidEvent(rendererHelper,category,title){const targetEvents=findAllEvents(rendererHelper,category,title);let validEvent;for(const targetEvent of targetEvents){if(rendererHelper.isTelemetryInternalEvent(targetEvent))continue;if(validEvent===undefined){validEvent=targetEvent;}else{if(validEvent.start<targetEvent.start){validEvent=targetEvent;}}}
+return validEvent;}
+function getFirstViewportReadySamples(rendererHelper,navIdToNavStartEvents){const samples=[];const pcEvent=getMostRecentValidEvent(rendererHelper,'blink.user_timing','pc');if(pcEvent===undefined)return samples;if(rendererHelper.isTelemetryInternalEvent(pcEvent))return samples;const navigationStartEvent=navIdToNavStartEvents.get(pcEvent.args.data.navigationId);if(navigationStartEvent===undefined)return samples;const navStartToEventRange=tr.b.math.Range.fromExplicitRange(navigationStartEvent.start,pcEvent.start);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventRange);samples.push({value:navStartToEventRange.duration,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),Start:new RelatedEventSet(navigationStartEvent),End:new RelatedEventSet(pcEvent)}});return samples;}
+function getAboveTheFoldLoadedToVisibleSamples(rendererHelper){const samples=[];const pcEvent=getMostRecentValidEvent(rendererHelper,'blink.user_timing','pc');const visibleEvent=getMostRecentValidEvent(rendererHelper,'blink.user_timing','visible');if(pcEvent!==undefined&&visibleEvent!==undefined){samples.push({value:Math.max(0.0,pcEvent.start-visibleEvent.start),diagnostics:{Start:new RelatedEventSet(visibleEvent),End:new RelatedEventSet(pcEvent)}});}
+return samples;}
function findTimeToXEntries(category,eventName,rendererHelper,frameToNavStartEvents,navIdToNavStartEvents){const targetEvents=findAllEvents(rendererHelper,category,eventName);const entries=[];for(const targetEvent of targetEvents){if(rendererHelper.isTelemetryInternalEvent(targetEvent))continue;const frameIdRef=targetEvent.args.frame;const snapshot=findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,targetEvent.start);if(snapshot===undefined||!snapshot.args.isLoadingMainFrame)continue;const url=snapshot.args.documentLoaderURL;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(url))continue;let navigationStartEvent;if(targetEvent.args.data===undefined||targetEvent.args.data.navigationId===undefined){navigationStartEvent=EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(frameToNavStartEvents.get(frameIdRef)||[],targetEvent.start);}else{navigationStartEvent=navIdToNavStartEvents.get(targetEvent.args.data.navigationId);}
if(navigationStartEvent===undefined)continue;entries.push({navigationStartEvent,targetEvent,url,});}
return entries;}
-function collectTimeToEvent(rendererHelper,timeToXEntries){const samples=[];for(const{targetEvent,navigationStartEvent,url}of timeToXEntries){const navStartToEventRange=tr.b.math.Range.fromExplicitRange(navigationStartEvent.start,targetEvent.start);const networkEvents=getNetworkEventsInRange(rendererHelper.process,navStartToEventRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventRange);samples.push({value:navStartToEventRange.duration,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),url:new tr.v.d.GenericSet([url]),Start:new RelatedEventSet(navigationStartEvent),End:new RelatedEventSet(targetEvent)}});}
+function collectTimeToEvent(rendererHelper,timeToXEntries){const samples=[];for(const{targetEvent,navigationStartEvent,url}of timeToXEntries){const navStartToEventRange=tr.b.math.Range.fromExplicitRange(navigationStartEvent.start,targetEvent.start);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventRange);samples.push({value:navStartToEventRange.duration,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),url:new tr.v.d.GenericSet([url]),Start:new RelatedEventSet(navigationStartEvent),End:new RelatedEventSet(targetEvent)}});}
return samples;}
function collectTimeToEventInCpuTime(rendererHelper,timeToXEntries){const samples=[];for(const{targetEvent,navigationStartEvent,url}of timeToXEntries){const navStartToEventRange=tr.b.math.Range.fromExplicitRange(navigationStartEvent.start,targetEvent.start);const mainThreadCpuTime=rendererHelper.mainThread.getCpuTimeForRange(navStartToEventRange);const breakdownTree=tr.metrics.sh.generateCpuTimeBreakdownTree(rendererHelper.mainThread,navStartToEventRange);samples.push({value:mainThreadCpuTime,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStartEvent),end:new RelatedEventSet(targetEvent),infos:new tr.v.d.GenericSet([{pid:rendererHelper.pid,start:navigationStartEvent.start,event:targetEvent.start,}]),}});}
return samples;}
-function addFirstMeaningfulPaintSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const networkEvents=getNetworkEventsInRange(rendererHelper.process,navStartToFMPRange);const timeToFirstMeaningfulPaint=navStartToFMPRange.duration;const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToFMPRange);samples.push({value:timeToFirstMeaningfulPaint,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
+function findLayoutShiftSamples(rendererHelper){let sample;EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'LayoutShift','loading').forEach((events)=>{const evData=events.pop().args.data;if(evData.is_main_frame){sample={value:evData.cumulative_score};}});return sample?[sample]:[];}
+function lineSweep(lineSweepRects,viewport){const verticalSweepRects=[];const horizontalSweepRects=[];for(let i=0;i<lineSweepRects.length;i++){const rect=lineSweepRects[i];let left=rect.left;let right=rect.right;let top=rect.top;let bottom=rect.bottom;if(left>viewport.x+viewport.width)continue;if(right<viewport.x)continue;if(top>viewport.y+viewport.height)continue;if(bottom<viewport.y)continue;left=Math.max(left,viewport.y);right=Math.min(right,viewport.y+viewport.width);top=Math.max(top,viewport.y);bottom=Math.min(bottom,viewport.y+viewport.height);verticalSweepRects.push({id:i,value:left,type:'left'},{id:i,value:right,type:'right'});horizontalSweepRects.push({id:i,value:top,type:'top'},{id:i,value:bottom,type:'bottom'});}
+verticalSweepRects.sort((a,b)=>a.value-b.value);horizontalSweepRects.sort((a,b)=>a.value-b.value);const active=new Array(lineSweepRects.length).fill(0);let area=0;active[verticalSweepRects[0].id]=1;for(let i=1;i<verticalSweepRects.length;i++){const currentLine=verticalSweepRects[i];const previousLine=verticalSweepRects[i-1];const deltaX=currentLine.value-previousLine.value;if(deltaX===0)continue;let count=0;let firstRect;for(let j=0;j<horizontalSweepRects.length;j++){if(active[horizontalSweepRects[j].id]===1){if(horizontalSweepRects[j].type==='top'){if(count===0){firstRect=j;count++;}}else{if(count===1){const deltaY=horizontalSweepRects[j].value-
+horizontalSweepRects[firstRect].value;area+=deltaX*deltaY;count--;}}}}
+active[currentLine.id]=(currentLine.type==='left');}
+return area;}
+function addVisuallyCompleteBeforeSomeTimeSample(samples,rendererHelper,navigationStart,loadDuration,frameID){const someTime=2000;if(loadDuration<someTime)return;let viewport;for(const event of EventFinderUtils.getMainThreadEvents(rendererHelper,'viewport','loading')){if(event.args.data.frameID===frameID&&event.start>navigationStart&&event.start<navigationStart+loadDuration){viewport=event.args.data;break;}}
+if(!viewport)return;const ccDisplayItemListObjects=rendererHelper.process.objects.getAllInstancesNamed('cc::DisplayItemList');if(!ccDisplayItemListObjects||!ccDisplayItemListObjects.length)return;const RectsUpdatedAfterSomeTime=[];for(let i=0;i<ccDisplayItemListObjects.length;i++){const displayItemListSnapshots=ccDisplayItemListObjects[i].snapshots;for(let j=0;j<displayItemListSnapshots.length;j++){const snapshot=displayItemListSnapshots[j];const timestamp=snapshot.ts;if(timestamp<navigationStart||timestamp>navigationStart+loadDuration){continue;}
+if(timestamp-navigationStart>someTime){RectsUpdatedAfterSomeTime.push(snapshot.args.params.layerRect);}}}
+const areaUpdatedAfterSomeTime=RectsUpdatedAfterSomeTime.length?lineSweep(RectsUpdatedAfterSomeTime,viewport):0;const pixelsLastUpdatedBeforeSomeTime=1-
+areaUpdatedAfterSomeTime/(viewport.width*viewport.height);samples.push({value:pixelsLastUpdatedBeforeSomeTime});}
+function addSpeedIndexSample(rendererHelper){const rects=[];let totalArea=0;for(const event of EventFinderUtils.getMainThreadEvents(rendererHelper,'PaintTracker::LayoutObjectPainted','loading')){const rect=event.args.data.visible_new_visual_rect;if(!rect)continue;const area=areaOfQuad(rect);if(!area)continue;rects.push({rect,ts:event.start});totalArea+=area;}
+const sample=[];if(!totalArea)return sample;let areaSoFar=0;const progress=new Array(rects.length);for(let i=0;i<rects.length;i++){const area=areaOfQuad(rects[i].rect);areaSoFar+=(area/totalArea);progress[i]={value:areaSoFar,ts:rects[i].ts};}
+sample.push({value:calculateSpeedIndex(progress)});return sample;}
+function areaOfQuad(quad){const width=Math.max(Math.abs(quad[0]-quad[2]),Math.abs(quad[2]-quad[4]));const height=Math.max(Math.abs(quad[1]-quad[3]),Math.abs(quad[3]-quad[5]));return width*height;}
+function calculateSpeedIndex(progress){let lastMs=0;let lastProgress=0;let speedIndex=0;for(let i=0;i<progress.length;i++){const elapsed=progress[i].ts-lastMs;speedIndex+=elapsed*(1.0-lastProgress);lastMs=progress[i].ts;lastProgress=progress[i].value;}
+return speedIndex;}
+function addFirstMeaningfulPaintSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToFMPRange);const timeToFirstMeaningfulPaint=navStartToFMPRange.duration;const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToFMPRange);samples.push({value:timeToFirstMeaningfulPaint,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
function addFirstMeaningfulPaintCpuTimeSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const mainThreadCpuTime=rendererHelper.mainThread.getCpuTimeForRange(navStartToFMPRange);const breakdownTree=tr.metrics.sh.generateCpuTimeBreakdownTree(rendererHelper.mainThread,navStartToFMPRange);samples.push({value:mainThreadCpuTime,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
-function decorateInteractivitySampleWithDiagnostics_(rendererHelper,eventTimestamp,navigationStartEvent,firstMeaningfulPaintTime,domContentLoadedEndTime,url){if(eventTimestamp===undefined)return undefined;const navigationStartTime=navigationStartEvent.start;const navStartToEventTimeRange=tr.b.math.Range.fromExplicitRange(navigationStartTime,eventTimestamp);const networkEvents=getNetworkEventsInRange(rendererHelper.process,navStartToEventTimeRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventTimeRange);const breakdownDiagnostic=createBreakdownDiagnostic(breakdownTree);return{value:navStartToEventTimeRange.duration,diagnostics:tr.v.d.DiagnosticMap.fromObject({'Start':new RelatedEventSet(navigationStartEvent),'Navigation infos':new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,navigationStartTime,firstMeaningfulPaintTime,domContentLoadedEndTime,eventTimestamp,}]),'Breakdown of [navStart, eventTimestamp]':breakdownDiagnostic,}),};}
-function collectLoadingMetricsForRenderer(rendererHelper){const frameToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const navIdToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByNavId(rendererHelper,'navigationStart','blink.user_timing');const firstPaintSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('loading','firstPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const timeToFCPEntries=findTimeToXEntries('loading','firstContentfulPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const firstContentfulPaintSamples=collectTimeToEvent(rendererHelper,timeToFCPEntries);const firstContentfulPaintCpuTimeSamples=collectTimeToEventInCpuTime(rendererHelper,timeToFCPEntries);const onLoadSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('blink.user_timing','loadEventStart',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));return{frameToNavStartEvents,firstPaintSamples,firstContentfulPaintSamples,firstContentfulPaintCpuTimeSamples,onLoadSamples,};}
-function collectMetricsFromLoadExpectations(model,chromeHelper){const interactiveSamples=[];const firstCpuIdleSamples=[];const firstMeaningfulPaintSamples=[];const firstMeaningfulPaintCpuTimeSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
-const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];if(expectation.fmpEvent!==undefined){addFirstMeaningfulPaintSample(firstMeaningfulPaintSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);addFirstMeaningfulPaintCpuTimeSample(firstMeaningfulPaintCpuTimeSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);}
+function decorateInteractivitySampleWithDiagnostics_(rendererHelper,eventTimestamp,navigationStartEvent,firstMeaningfulPaintTime,domContentLoadedEndTime,url){if(eventTimestamp===undefined)return undefined;const navigationStartTime=navigationStartEvent.start;const navStartToEventTimeRange=tr.b.math.Range.fromExplicitRange(navigationStartTime,eventTimestamp);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventTimeRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventTimeRange);const breakdownDiagnostic=createBreakdownDiagnostic(breakdownTree);return{value:navStartToEventTimeRange.duration,diagnostics:tr.v.d.DiagnosticMap.fromObject({'Start':new RelatedEventSet(navigationStartEvent),'Navigation infos':new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,navigationStartTime,firstMeaningfulPaintTime,domContentLoadedEndTime,eventTimestamp,}]),'Breakdown of [navStart, eventTimestamp]':breakdownDiagnostic,}),};}
+function getCandidateIndex(entry){return entry.targetEvent.args.data.candidateIndex;}
+function findLastCandidateForEachNavigation(timeToXEntries){const entryMap=new Map();for(const e of timeToXEntries){const navStartEvent=e.navigationStartEvent;if(!entryMap.has(navStartEvent)){entryMap.set(navStartEvent,[]);}
+entryMap.get(navStartEvent).push(e);}
+const lastCandidates=[];for(const timeToXEntriesByNavigation of entryMap.values()){let lastCandidate=timeToXEntriesByNavigation.shift();for(const entry of timeToXEntriesByNavigation){if(getCandidateIndex(entry)>getCandidateIndex(lastCandidate)){lastCandidate=entry;}}
+lastCandidates.push(lastCandidate);}
+return lastCandidates;}
+function findLargestTextPaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents){const timeToPaintEntries=findTimeToXEntries('loading','LargestTextPaint::Candidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const timeToPaintBlockingEntries=findTimeToXEntries('loading','LargestTextPaint::NoCandidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const lastCandidateEvents=findLastCandidateForEachNavigation(timeToPaintEntries.concat(timeToPaintBlockingEntries)).filter(event=>event.targetEvent.title!=='LargestTextPaint::NoCandidate');return collectTimeToEvent(rendererHelper,lastCandidateEvents);}
+function findLargestImagePaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents){const timeToPaintEntries=findTimeToXEntries('loading','LargestImagePaint::Candidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const timeToPaintBlockingEntries=findTimeToXEntries('loading','LargestImagePaint::NoCandidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const lastCandidateEvents=findLastCandidateForEachNavigation(timeToPaintEntries.concat(timeToPaintBlockingEntries)).filter(event=>event.targetEvent.title!=='LargestImagePaint::NoCandidate');return collectTimeToEvent(rendererHelper,lastCandidateEvents);}
+function findLargestContentfulPaintHistogramSamples(allBrowserEvents){const lcp=new tr.e.chrome.LargestContentfulPaint(allBrowserEvents);const lcpSamples=lcp.findCandidates().map(candidate=>{const{durationInMilliseconds,size,type,inMainFrame,mainFrameTreeNodeId}=candidate;return{value:durationInMilliseconds,diagnostics:{size:new tr.v.d.GenericSet([size]),type:new tr.v.d.GenericSet([type]),inMainFrame:new tr.v.d.GenericSet([inMainFrame]),mainFrameTreeNodeId:new tr.v.d.GenericSet([mainFrameTreeNodeId]),},};});return lcpSamples;}
+function collectLoadingMetricsForRenderer(rendererHelper){const frameToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const navIdToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByNavId(rendererHelper,'navigationStart','blink.user_timing');const firstPaintSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('loading','firstPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const timeToFCPEntries=findTimeToXEntries('loading','firstContentfulPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const firstContentfulPaintSamples=collectTimeToEvent(rendererHelper,timeToFCPEntries);const firstContentfulPaintCpuTimeSamples=collectTimeToEventInCpuTime(rendererHelper,timeToFCPEntries);const onLoadSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('blink.user_timing','loadEventStart',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const aboveTheFoldLoadedToVisibleSamples=getAboveTheFoldLoadedToVisibleSamples(rendererHelper);const firstViewportReadySamples=getFirstViewportReadySamples(rendererHelper,navIdToNavStartEvents);const largestImagePaintSamples=findLargestImagePaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const largestTextPaintSamples=findLargestTextPaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const layoutShiftSamples=findLayoutShiftSamples(rendererHelper);const speedIndexSamples=addSpeedIndexSample(rendererHelper);return{frameToNavStartEvents,firstPaintSamples,firstContentfulPaintSamples,firstContentfulPaintCpuTimeSamples,onLoadSamples,aboveTheFoldLoadedToVisibleSamples,firstViewportReadySamples,largestImagePaintSamples,largestTextPaintSamples,layoutShiftSamples,speedIndexSamples};}
+function collectMetricsFromLoadExpectations(model,chromeHelper){const interactiveSamples=[];const firstCpuIdleSamples=[];const firstMeaningfulPaintSamples=[];const firstMeaningfulPaintCpuTimeSamples=[];const visuallyCompleteBeforeSomeTimeSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addVisuallyCompleteBeforeSomeTimeSample(visuallyCompleteBeforeSomeTimeSamples,rendererHelper,expectation.navigationStart.start,expectation.duration,expectation.navigationStart.args.frame);if(expectation.fmpEvent!==undefined){addFirstMeaningfulPaintSample(firstMeaningfulPaintSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);addFirstMeaningfulPaintCpuTimeSample(firstMeaningfulPaintCpuTimeSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);}
if(expectation.firstCpuIdleTime!==undefined){firstCpuIdleSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.firstCpuIdleTime,expectation.navigationStart,expectation.fmpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}
if(expectation.timeToInteractive!==undefined){interactiveSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.timeToInteractive,expectation.navigationStart,expectation.fmpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}}
-return{firstMeaningfulPaintSamples,firstMeaningfulPaintCpuTimeSamples,firstCpuIdleSamples,interactiveSamples,};}
+return{firstMeaningfulPaintSamples,firstMeaningfulPaintCpuTimeSamples,firstCpuIdleSamples,interactiveSamples,visuallyCompleteBeforeSomeTimeSamples,};}
function addSamplesToHistogram(samples,histogram,histograms){for(const sample of samples){histogram.addSample(sample.value,sample.diagnostics);if(histogram.name!=='timeToFirstContentfulPaint')continue;if(!sample.breakdownTree)continue;for(const[category,breakdown]of Object.entries(sample.breakdownTree)){const relatedName=`${histogram.name}:${category}`;let relatedHist=histograms.getHistogramsNamed(relatedName)[0];if(!relatedHist){relatedHist=histograms.createHistogram(relatedName,histogram.unit,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,summaryOptions:{count:false,max:false,min:false,sum:false,},});let relatedNames=histogram.diagnostics.get('breakdown');if(!relatedNames){relatedNames=new tr.v.d.RelatedNameMap();histogram.diagnostics.set('breakdown',relatedNames);}
relatedNames.set(category,relatedName);}
relatedHist.addSample(breakdown.total,{breakdown:tr.v.d.Breakdown.fromEntries(Object.entries(breakdown.events)),});}}}
-function loadingMetric(histograms,model){const firstPaintHistogram=histograms.createHistogram('timeToFirstPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintHistogram=histograms.createHistogram('timeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const onLoadHistogram=histograms.createHistogram('timeToOnload',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to onload. '+'This is temporary metric used for PCv1/v2 sanity checking',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintHistogram=histograms.createHistogram('timeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const timeToInteractiveHistogram=histograms.createHistogram('timeToInteractive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to Interactive',summaryOptions:SUMMARY_OPTIONS,});const timeToFirstCpuIdleHistogram=histograms.createHistogram('timeToFirstCpuIdle',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to First CPU Idle',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;const samplesSet=collectLoadingMetricsForRenderer(rendererHelper);addSamplesToHistogram(samplesSet.firstPaintSamples,firstPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintSamples,firstContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintCpuTimeSamples,firstContentfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.onLoadSamples,onLoadHistogram,histograms);}
-const samplesSet=collectMetricsFromLoadExpectations(model,chromeHelper);addSamplesToHistogram(samplesSet.firstMeaningfulPaintSamples,firstMeaningfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstMeaningfulPaintCpuTimeSamples,firstMeaningfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.interactiveSamples,timeToInteractiveHistogram,histograms);addSamplesToHistogram(samplesSet.firstCpuIdleSamples,timeToFirstCpuIdleHistogram,histograms);}
-tr.metrics.MetricRegistry.register(loadingMetric);return{loadingMetric,getNetworkEventsInRange,};});'use strict';tr.exportTo('tr.metrics',function(){const SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY=tr.v.HistogramBinBoundaries.createExponential(1,1000,50);function spaNavigationMetric(histograms,model){const histogram=new tr.v.Histogram('spaNavigationStartToFpDuration',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY);histogram.description='Latency between the input event causing'+' a SPA navigation and the first paint event after it';histogram.customizeSummaryOptions({count:false,sum:false,});const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper){return;}
+function loadingMetric(histograms,model){const firstPaintHistogram=histograms.createHistogram('timeToFirstPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintHistogram=histograms.createHistogram('timeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const onLoadHistogram=histograms.createHistogram('timeToOnload',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to onload. '+'This is temporary metric used for PCv1/v2 sanity checking',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintHistogram=histograms.createHistogram('timeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const timeToInteractiveHistogram=histograms.createHistogram('timeToInteractive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to Interactive',summaryOptions:SUMMARY_OPTIONS,});const timeToFirstCpuIdleHistogram=histograms.createHistogram('timeToFirstCpuIdle',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to First CPU Idle',summaryOptions:SUMMARY_OPTIONS,});const aboveTheFoldLoadedToVisibleHistogram=histograms.createHistogram('aboveTheFoldLoadedToVisible',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from first visible to load for AMP pages only.',summaryOptions:SUMMARY_OPTIONS,});const firstViewportReadyHistogram=histograms.createHistogram('timeToFirstViewportReady',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from navigation to load for AMP pages only. ',summaryOptions:SUMMARY_OPTIONS,});const largestImagePaintHistogram=histograms.createHistogram('largestImagePaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Image Paint',summaryOptions:SUMMARY_OPTIONS,});const largestTextPaintHistogram=histograms.createHistogram('largestTextPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Text Paint',summaryOptions:SUMMARY_OPTIONS,});const largestContentfulPaintHistogram=histograms.createHistogram('largestContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Contentful Paint',summaryOptions:SUMMARY_OPTIONS,});const layoutShiftHistogram=histograms.createHistogram('mainFrameCumulativeLayoutShift',unitlessNumber_smallerIsBetter,[],{binBoundaries:LAYOUT_SHIFT_SCORE_BOUNDARIES,description:'Main Frame Document Cumulative Layout Shift Score',summaryOptions:SUMMARY_OPTIONS,});const visuallyCompleteBeforeSomeTimeHistogram=histograms.createHistogram('visuallyCompleteBeforeSomeTime',unitlessNumber_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Fraction of pixels in the initial viewport reaching '+'final value within some time interval after navigation start.',summaryOptions:SUMMARY_OPTIONS,});const speedIndexHistogram=histograms.createHistogram('speedIndex',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:' the average time at which visible parts of the'+' page are displayed (in ms).',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;const samplesSet=collectLoadingMetricsForRenderer(rendererHelper);const lcpSamples=findLargestContentfulPaintHistogramSamples(chromeHelper.browserHelper.mainThread.sliceGroup.slices);addSamplesToHistogram(lcpSamples,largestContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstPaintSamples,firstPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintSamples,firstContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintCpuTimeSamples,firstContentfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.onLoadSamples,onLoadHistogram,histograms);addSamplesToHistogram(samplesSet.aboveTheFoldLoadedToVisibleSamples,aboveTheFoldLoadedToVisibleHistogram,histograms);addSamplesToHistogram(samplesSet.firstViewportReadySamples,firstViewportReadyHistogram,histograms);addSamplesToHistogram(samplesSet.largestImagePaintSamples,largestImagePaintHistogram,histograms);addSamplesToHistogram(samplesSet.largestTextPaintSamples,largestTextPaintHistogram,histograms);addSamplesToHistogram(samplesSet.layoutShiftSamples,layoutShiftHistogram,histograms);addSamplesToHistogram(samplesSet.speedIndexSamples,speedIndexHistogram,histograms);}
+const samplesSet=collectMetricsFromLoadExpectations(model,chromeHelper);addSamplesToHistogram(samplesSet.firstMeaningfulPaintSamples,firstMeaningfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstMeaningfulPaintCpuTimeSamples,firstMeaningfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.interactiveSamples,timeToInteractiveHistogram,histograms);addSamplesToHistogram(samplesSet.firstCpuIdleSamples,timeToFirstCpuIdleHistogram,histograms);addSamplesToHistogram(samplesSet.visuallyCompleteBeforeSomeTimeSamples,visuallyCompleteBeforeSomeTimeHistogram,histograms);}
+tr.metrics.MetricRegistry.register(loadingMetric);return{loadingMetric,createBreakdownDiagnostic};});'use strict';tr.exportTo('tr.metrics',function(){const SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY=tr.v.HistogramBinBoundaries.createExponential(1,1000,50);function spaNavigationMetric(histograms,model){const histogram=new tr.v.Histogram('spaNavigationStartToFpDuration',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY);histogram.description='Latency between the input event causing'+' a SPA navigation and the first paint event after it';histogram.customizeSummaryOptions({count:false,sum:false,});const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper){return;}
const rendererHelpers=modelHelper.rendererHelpers;if(!rendererHelpers){return;}
const browserHelper=modelHelper.browserHelper;for(const rendererHelper of Object.values(rendererHelpers)){const spaNavigations=tr.metrics.findSpaNavigationsOnRenderer(rendererHelper,browserHelper);for(const spaNav of spaNavigations){let beginTs=0;if(spaNav.navStartCandidates.inputLatencyAsyncSlice){const beginData=spaNav.navStartCandidates.inputLatencyAsyncSlice.args.data;beginTs=model.convertTimestampToModelTime('traceEventClock',beginData.INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT.time);}else{beginTs=spaNav.navStartCandidates.goToIndexSlice.start;}
-const rangeOfInterest=tr.b.math.Range.fromExplicitRange(beginTs,spaNav.firstPaintEvent.start);const networkEvents=tr.metrics.sh.getNetworkEventsInRange(rendererHelper.process,rangeOfInterest);const breakdownDict=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,rangeOfInterest);const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownDict){breakdownDiagnostic.set(label,parseInt(breakdownDict[label].total*1e3)/1e3);}
+const rangeOfInterest=tr.b.math.Range.fromExplicitRange(beginTs,spaNav.firstPaintEvent.start);const networkEvents=tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,rangeOfInterest);const breakdownDict=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,rangeOfInterest);const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownDict){breakdownDiagnostic.set(label,parseInt(breakdownDict[label].total*1e3)/1e3);}
histogram.addSample(rangeOfInterest.duration,{'Breakdown of [navStart, firstPaint]':breakdownDiagnostic,'Start':new tr.v.d.RelatedEventSet(spaNav.navigationStart),'End':new tr.v.d.RelatedEventSet(spaNav.firstPaintEvent),'Navigation infos':new tr.v.d.GenericSet([{url:spaNav.url,pid:rendererHelper.pid,navStart:beginTs,firstPaint:spaNav.firstPaintEvent.start}]),});}}
histograms.addHistogram(histogram);}
tr.metrics.MetricRegistry.register(spaNavigationMetric);return{spaNavigationMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LATENCY_BOUNDS=tr.v.HistogramBinBoundaries.createLinear(0,20,100);function clockSyncLatencyMetric(values,model){const domains=Array.from(model.clockSyncManager.domainsSeen).sort();for(let i=0;i<domains.length;i++){for(let j=i+1;j<domains.length;j++){const latency=model.clockSyncManager.getTimeTransformerError(domains[i],domains[j]);const hist=new tr.v.Histogram('clock_sync_latency_'+
@@ -8398,9 +8642,11 @@ let processCpuTime=0;for(const tid in process.threads){const thread=process.thre
allProcessCpuTime+=processCpuTime;}
let normalizedAllProcessCpuTime=0;if(rangeOfInterest.duration>0){normalizedAllProcessCpuTime=allProcessCpuTime/rangeOfInterest.duration;}
const unit=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const cpuTimeHist=new tr.v.Histogram('cpu_time_percentage',unit,CPU_TIME_PERCENTAGE_BOUNDARIES);cpuTimeHist.description='Percent CPU utilization, normalized against a single core. Can be '+'greater than 100% if machine has multiple cores.';cpuTimeHist.customizeSummaryOptions({avg:true,count:false,max:false,min:false,std:false,sum:false});cpuTimeHist.addSample(normalizedAllProcessCpuTime);histograms.addHistogram(cpuTimeHist);}
-tr.metrics.MetricRegistry.register(cpuTimeMetric,{supportsRangeOfInterest:true});return{cpuTimeMetric,};});'use strict';tr.exportTo('tr.v.d',function(){function addRelatedNames(histograms){for(const hist of histograms){const relatedNames=new Set();for(const[name,diagnostic]of hist.diagnostics){if(diagnostic instanceof tr.v.d.RelatedHistogramMap){for(const[relationshipName,relatedHist]of diagnostic){relatedNames.add(relatedHist.name);}}}
-if(relatedNames.size){hist.diagnostics.set(tr.v.d.RESERVED_NAMES.RELATED_NAMES,new tr.v.d.GenericSet(relatedNames));}}}
-return{addRelatedNames,};});'use strict';tr.exportTo('tr.v',function(){class HistogramGrouping{constructor(key,callback){this.key_=key;this.callback_=callback;HistogramGrouping.BY_KEY.set(key,this);}
+tr.metrics.MetricRegistry.register(cpuTimeMetric,{supportsRangeOfInterest:true});return{cpuTimeMetric,};});'use strict';tr.exportTo('tr.v',function(){class HistogramDeserializer{static deserialize(data){const deserializer=new HistogramDeserializer(data[0],data[1]);return data.slice(2).map(datum=>tr.v.Histogram.deserialize(datum,deserializer));}
+constructor(objects,diagnostics){this.objects_=objects;this.diagnostics_=[];for(const[type,diagnosticsByName]of Object.entries(diagnostics||{})){for(const[name,diagnosticsById]of Object.entries(diagnosticsByName)){for(const[id,data]of Object.entries(diagnosticsById)){const diagnostic=tr.v.d.Diagnostic.deserialize(type,data,this);this.diagnostics_[parseInt(id)]={name,diagnostic};}}}}
+getObject(id){return this.objects_[id];}
+getDiagnostic(id){return this.diagnostics_[parseInt(id)];}}
+return{HistogramDeserializer};});'use strict';tr.exportTo('tr.v',function(){class HistogramGrouping{constructor(key,callback){this.key_=key;this.callback_=callback;HistogramGrouping.BY_KEY.set(key,this);}
get key(){return this.key_;}
get callback(){return this.callback_;}
get label(){return this.key;}
@@ -8421,33 +8667,31 @@ GenericSetGrouping.NAMES=[tr.v.d.RESERVED_NAMES.ARCHITECTURES,tr.v.d.RESERVED_NA
class DateRangeGrouping extends HistogramGrouping{constructor(name){super(name,undefined);this.callback_=this.compute_.bind(this);}
compute_(hist){const diag=hist.diagnostics.get(this.key);if(diag===undefined)return'';return diag.toString();}}
DateRangeGrouping.NAMES=[tr.v.d.RESERVED_NAMES.BENCHMARK_START,tr.v.d.RESERVED_NAMES.TRACE_START,];for(const name of DateRangeGrouping.NAMES){new DateRangeGrouping(name);}
-return{HistogramGrouping,GenericSetGrouping,DateRangeGrouping,};});'use strict';tr.exportTo('tr.v',function(){class HistogramSet{constructor(opt_histograms){this.histogramsByGuid_=new Map();this.sharedDiagnosticsByGuid_=new Map();if(opt_histograms!==undefined){for(const hist of opt_histograms){this.addHistogram(hist);}}}
+return{HistogramGrouping,GenericSetGrouping,DateRangeGrouping,};});'use strict';tr.exportTo('tr.v',function(){class HistogramSet{constructor(opt_histograms){this.histograms_=new Set();this.sharedDiagnosticsByGuid_=new Map();if(opt_histograms!==undefined){for(const hist of opt_histograms){this.addHistogram(hist);}}}
+has(hist){return this.histograms_.has(hist);}
createHistogram(name,unit,samples,opt_options){const hist=tr.v.Histogram.create(name,unit,samples,opt_options);this.addHistogram(hist);return hist;}
-addHistogram(hist,opt_diagnostics){if(this.histogramsByGuid_.has(hist.guid)){throw new Error('Cannot add same Histogram twice');}
+addHistogram(hist,opt_diagnostics){if(this.has(hist)){throw new Error('Cannot add same Histogram twice');}
if(opt_diagnostics!==undefined){if(!(opt_diagnostics instanceof Map)){opt_diagnostics=Object.entries(opt_diagnostics);}
for(const[name,diagnostic]of opt_diagnostics){hist.diagnostics.set(name,diagnostic);}}
-this.histogramsByGuid_.set(hist.guid,hist);}
+this.histograms_.add(hist);}
addSharedDiagnosticToAllHistograms(name,diagnostic){this.addSharedDiagnostic(diagnostic);for(const hist of this){hist.diagnostics.set(name,diagnostic);}}
addSharedDiagnostic(diagnostic){this.sharedDiagnosticsByGuid_.set(diagnostic.guid,diagnostic);}
-get length(){return this.histogramsByGuid_.size;}*[Symbol.iterator](){for(const hist of this.histogramsByGuid_.values()){yield hist;}}
+get length(){return this.histograms_.size;}*[Symbol.iterator](){for(const hist of this.histograms_){yield hist;}}
getHistogramsNamed(name){return[...this].filter(h=>h.name===name);}
getHistogramNamed(name){const histograms=this.getHistogramsNamed(name);if(histograms.length===0)return undefined;if(histograms.length>1){throw new Error(`Unexpectedly found multiple histograms named "${name}"`);}
return histograms[0];}
-lookupHistogram(guid){return this.histogramsByGuid_.get(guid);}
lookupDiagnostic(guid){return this.sharedDiagnosticsByGuid_.get(guid);}
-resolveRelatedHistograms(){const handleDiagnosticMap=dm=>{for(const[name,diagnostic]of dm){if(diagnostic instanceof tr.v.d.RelatedHistogramMap){diagnostic.resolve(this);}}};for(const hist of this){handleDiagnosticMap(hist.diagnostics);for(const dm of hist.nanDiagnosticMaps){handleDiagnosticMap(dm);}
-for(const bin of hist.allBins){for(const dm of bin.diagnosticMaps){handleDiagnosticMap(dm);}}}}
-importDicts(dicts){for(const dict of dicts){this.importDict(dict);}}
-importDict(dict){if(dict.type&&tr.v.d.Diagnostic.findTypeInfoWithName(dict.type)){this.sharedDiagnosticsByGuid_.set(dict.guid,tr.v.d.Diagnostic.fromDict(dict));}else{const hist=tr.v.Histogram.fromDict(dict);this.addHistogram(hist);hist.diagnostics.resolveSharedDiagnostics(this,true);}}
+deserialize(data){for(const hist of tr.v.HistogramDeserializer.deserialize(data)){this.addHistogram(hist);}}
+importDicts(dicts){if((dicts instanceof Array)&&(dicts.length>2)&&(dicts[0]instanceof Array)){this.deserialize(dicts);return;}
+for(const dict of dicts){this.importLegacyDict(dict);}}
+importLegacyDict(dict){if(dict.type!==undefined){if(dict.type==='TagMap')return;if(!tr.v.d.Diagnostic.findTypeInfoWithName(dict.type)){throw new Error('Unrecognized shared diagnostic type '+dict.type);}
+this.sharedDiagnosticsByGuid_.set(dict.guid,tr.v.d.Diagnostic.fromDict(dict));}else{const hist=tr.v.Histogram.fromDict(dict);this.addHistogram(hist);hist.diagnostics.resolveSharedDiagnostics(this,true);}}
asDicts(){const dicts=[];for(const diagnostic of this.sharedDiagnosticsByGuid_.values()){dicts.push(diagnostic.asDict());}
for(const hist of this){dicts.push(hist.asDict());}
return dicts;}
get sourceHistograms(){const diagnosticNames=new Set();for(const hist of this){for(const diagnostic of hist.diagnostics.values()){if(!(diagnostic instanceof tr.v.d.RelatedNameMap))continue;for(const name of diagnostic.values()){diagnosticNames.add(name);}}}
-const sourceHistograms=new Map();for(const hist of this){if(!diagnosticNames.has(hist.name)){sourceHistograms.set(hist.guid,hist);}}
-function deleteSourceHistograms(diagnosticMap){for(const[name,diagnostic]of diagnosticMap){if(diagnostic instanceof tr.v.d.RelatedHistogramMap){for(const[name,relatedHist]of diagnostic){sourceHistograms.delete(relatedHist.guid);}}}}
-for(const hist of this){deleteSourceHistograms(hist.diagnostics);for(const dm of hist.nanDiagnosticMaps){deleteSourceHistograms(dm);}
-for(const b of hist.allBins){for(const dm of b.diagnosticMaps){deleteSourceHistograms(dm);}}}
-return new HistogramSet([...sourceHistograms.values()]);}
+const sourceHistograms=new HistogramSet;for(const hist of this){if(!diagnosticNames.has(hist.name)){sourceHistograms.addHistogram(hist);}}
+return sourceHistograms;}
groupHistogramsRecursively(groupings,opt_skipGroupingCallback){function recurse(histograms,level){if(level===groupings.length){return histograms;}
const grouping=groupings[level];const groupedHistograms=tr.b.groupIntoMap(histograms,grouping.callback);if(opt_skipGroupingCallback&&opt_skipGroupingCallback(grouping,groupedHistograms)){return recurse(histograms,level+1);}
for(const[key,group]of groupedHistograms){groupedHistograms.set(key,recurse(group,level+1));}
@@ -8465,9 +8709,8 @@ if(!found){deduplicatedDiagnostics.add(candidate);}
for(const diagnostic of deduplicatedDiagnostics){this.sharedDiagnosticsByGuid_.set(diagnostic.guid,diagnostic);}}}}
buildGroupingsFromTags(names){const tags=new Map();for(const hist of this){for(const name of names){if(!hist.diagnostics.has(name))continue;if(!tags.has(name))tags.set(name,new Set());for(const tag of hist.diagnostics.get(name)){tags.get(name).add(tag);}}}
const groupings=[];for(const[name,values]of tags){const built=tr.v.HistogramGrouping.buildFromTags(values,name);for(const grouping of built){groupings.push(grouping);}}
-return groupings;}
-mergeRelationships(){for(const hist of this){hist.diagnostics.mergeRelationships(hist);}}}
-return{HistogramSet,};});'use strict';tr.exportTo('tr.e.chrome',function(){function hasTitleAndCategory(event,title,category){return event.title===title&&event.category&&tr.b.getCategoryParts(event.category).includes(category);}
+return groupings;}}
+return{HistogramSet};});'use strict';tr.exportTo('tr.e.chrome',function(){function hasTitleAndCategory(event,title,category){return event.title===title&&event.category&&tr.b.getCategoryParts(event.category).includes(category);}
function getNavStartTimestamps(rendererHelper){const navStartTimestamps=[];for(const e of rendererHelper.mainThread.sliceGroup.childEvents()){if(hasTitleAndCategory(e,'navigationStart','blink.user_timing')){navStartTimestamps.push(e.start);}}
return navStartTimestamps;}
function getInteractiveTimestamps(model){const interactiveTimestampsMap=new Map();const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){const timestamps=[];interactiveTimestampsMap.set(rendererHelper.pid,timestamps);}
@@ -8494,38 +8737,33 @@ if(this.lastTaskIndex_+1<this.sortedTasks_.length&&this.sortedTasks_[this.lastTa
this.lastTaskIndex_++;}}}
function maxExpectedQueueingTimeInSlidingWindow(startTime,endTime,windowSize,tasks){if(windowSize<=0){throw Error('The window size must be positive number');}
if(startTime+windowSize>endTime){throw Error('The sliding window must fit in the specified time range');}
-const sortedTasks=tasks.slice().sort((a,b)=>a.start-b.start);for(let i=1;i<sortedTasks.length;i++){const PRECISION_MS=0.1;if(sortedTasks[i-1].end>sortedTasks[i].start+PRECISION_MS){throw Error('Tasks must not overlap');}
-if(sortedTasks[i-1].end>sortedTasks[i].start){const midpoint=(sortedTasks[i-1].end+sortedTasks[i].start)/2;sortedTasks[i-1].end=midpoint;sortedTasks[i].start=midpoint;}}
+const sortedTasks=tasks.slice().sort((a,b)=>a.start-b.start);for(let i=1;i<sortedTasks.length;i++){if(sortedTasks[i-1].end>sortedTasks[i].start){const midpoint=(sortedTasks[i-1].end+sortedTasks[i].start)/2;sortedTasks[i-1].end=midpoint;sortedTasks[i].start=midpoint;}}
let endpoints=[];endpoints.push(startTime);endpoints.push(endTime-windowSize);for(const task of tasks){endpoints.push(task.start-windowSize);endpoints.push(task.start);endpoints.push(task.end-windowSize);endpoints.push(task.end);}
endpoints=endpoints.filter(x=>(startTime<=x&&x+windowSize<=endTime));endpoints.sort((a,b)=>a-b);const slidingWindow=new SlidingWindow(endpoints[0],windowSize,sortedTasks);let maxEQT=0;for(const t of endpoints){slidingWindow.slide(t);maxEQT=Math.max(maxEQT,slidingWindow.getEQT);}
return maxEQT;}
return{getPostInteractiveTaskWindows,getNavStartTimestamps,getInteractiveTimestamps,expectedQueueingTime,maxExpectedQueueingTimeInSlidingWindow,weightedExpectedQueueingTime};});'use strict';tr.exportTo('tr.metrics.sh',function(){const WINDOW_SIZE_MS=500;const EQT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.01,WINDOW_SIZE_MS,50);function containsForcedGC_(slice){return slice.findTopmostSlicesRelativeToThisSlice(tr.metrics.v8.utils.isForcedGarbageCollectionEvent).length>0;}
-function createHistogramForEQT_(name,description){const histogram=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,EQT_BOUNDARIES);histogram.customizeSummaryOptions({avg:false,count:false,max:true,min:false,std:false,sum:false,});histogram.description=description;return histogram;}
-function expectedQueueingTimeMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=Object.values(chromeHelper.rendererHelpers);const rendererToInteractiveTimestamps=tr.e.chrome.getInteractiveTimestamps(model);addExpectedQueueingTimeMetric_('renderer_eqt',event=>{return{start:event.start,duration:event.duration};},false,rendererHelpers,rendererToInteractiveTimestamps,histograms,model);addExpectedQueueingTimeMetric_('renderer_eqt_cpu',event=>{return{start:event.cpuStart,duration:event.cpuDuration};},true,rendererHelpers,rendererToInteractiveTimestamps,histograms,model);}
-function addExpectedQueueingTimeMetric_(eqtName,getEventTimes,isCpuTime,rendererHelpers,rendererToInteractiveTimestamps,histograms,model){function getTasks(rendererHelper){const tasks=[];for(const slice of
+function getOrCreateHistogram_(histograms,name,description){return histograms.getHistogramNamed(name)||histograms.createHistogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:EQT_BOUNDARIES,description,summaryOptions:{avg:false,count:false,max:true,min:false,std:false,sum:false,},});}
+function expectedQueueingTimeMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=Object.values(chromeHelper.rendererHelpers);addExpectedQueueingTimeMetric_('renderer_eqt',event=>{return{start:event.start,duration:event.duration};},false,rendererHelpers,histograms,model);}
+function addExpectedQueueingTimeMetric_(eqtName,getEventTimes,isCpuTime,rendererHelpers,histograms,model){function getTasks(rendererHelper){const tasks=[];for(const slice of
tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread)){const times=getEventTimes(slice);if(times.duration>0&&!containsForcedGC_(slice)){tasks.push({start:times.start,end:times.start+times.duration});}}
return tasks;}
-const totalHistogram=createHistogramForEQT_(`total:${WINDOW_SIZE_MS}ms_window:${eqtName}`,`The maximum EQT in a ${WINDOW_SIZE_MS}ms sliding window`+' for a given renderer');const interactiveHistogram=createHistogramForEQT_(`interactive:${WINDOW_SIZE_MS}ms_window:${eqtName}`,`The maximum EQT in a ${WINDOW_SIZE_MS}ms sliding window`+' for a given renderer while the page is interactive');for(const rendererHelper of rendererHelpers){if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread.bounds.duration<WINDOW_SIZE_MS)continue;const tasks=getTasks(rendererHelper);totalHistogram.addSample(tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(rendererHelper.mainThread.bounds.min,rendererHelper.mainThread.bounds.max,WINDOW_SIZE_MS,tasks));const interactiveTimestamps=rendererToInteractiveTimestamps.get(rendererHelper.pid);if(interactiveTimestamps.length===0)continue;if(interactiveTimestamps.length>1){continue;}
-const interactiveWindow=tr.b.math.Range.fromExplicitRange(interactiveTimestamps[0],Infinity).findIntersection(rendererHelper.mainThread.bounds);interactiveHistogram.addSample(tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(interactiveWindow.min,interactiveWindow.max,WINDOW_SIZE_MS,tasks));}
-addV8ContributionToExpectedQueueingTime_(eqtName,getEventTimes,isCpuTime,totalHistogram,interactiveHistogram,rendererToInteractiveTimestamps,histograms,model);histograms.addHistogram(totalHistogram);histograms.addHistogram(interactiveHistogram);}
-function addV8ContributionToExpectedQueueingTime_(eqtName,getEventTimes,isCpuTime,totalEqtHistogram,interactiveEqtHistogram,rendererToInteractiveTimestamps,histograms,model){if(!model.categories.includes('v8'))return;const breakdownForTotal=new tr.v.d.RelatedHistogramMap();const breakdownForInteractive=new tr.v.d.RelatedHistogramMap();const eventNamesWithTaskExtractors=getV8EventNamesWithTaskExtractors_(getEventTimes);if(!isCpuTime){const taskExtractorsUsingRCS=getV8EventNamesWithTaskExtractorsUsingRCS_(getEventTimes);for(const[eventName,getTasks]of taskExtractorsUsingRCS){eventNamesWithTaskExtractors.set(eventName,getTasks);}}
-for(const[eventName,getTasks]of eventNamesWithTaskExtractors){const contribution=contributionToExpectedQueueingTime_(eqtName,eventName,getTasks,rendererToInteractiveTimestamps,histograms,model);breakdownForTotal.set(eventName,contribution.total);breakdownForInteractive.set(eventName,contribution.interactive);}
-totalEqtHistogram.diagnostics.set('v8',breakdownForTotal);interactiveEqtHistogram.diagnostics.set('v8',breakdownForInteractive);}
+const totalHistogram=getOrCreateHistogram_(histograms,`total:${WINDOW_SIZE_MS}ms_window:${eqtName}`,`The maximum EQT in a ${WINDOW_SIZE_MS}ms sliding window`+' for a given renderer');for(const rendererHelper of rendererHelpers){if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread.bounds.duration<WINDOW_SIZE_MS)continue;const tasks=getTasks(rendererHelper);const totalBreakdown=getV8Contribution_(eqtName,getEventTimes,isCpuTime,totalHistogram,histograms,rendererHelper,model);totalHistogram.addSample(tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(rendererHelper.mainThread.bounds.min,rendererHelper.mainThread.bounds.max,WINDOW_SIZE_MS,tasks),{v8:totalBreakdown});}}
+function getV8Contribution_(eqtName,getEventTimes,isCpuTime,totalEqtHistogram,histograms,rendererHelper,model){if(!model.categories.includes('v8'))return null;const totalBreakdown=new tr.v.d.Breakdown();const eventNamesWithTaskExtractors=getV8EventNamesWithTaskExtractors_(getEventTimes);if(!isCpuTime){const taskExtractorsUsingRCS=getV8EventNamesWithTaskExtractorsUsingRCS_(getEventTimes);for(const[eventName,getTasks]of taskExtractorsUsingRCS){eventNamesWithTaskExtractors.set(eventName,getTasks);}}
+let totalNames=totalEqtHistogram.diagnostics.get('v8');if(!totalNames){totalNames=new tr.v.d.RelatedNameMap();totalEqtHistogram.diagnostics.set('v8',totalNames);}
+for(const[eventName,getTasks]of eventNamesWithTaskExtractors){const totalHistogram=getOrCreateHistogram_(histograms,`total:${WINDOW_SIZE_MS}ms_window:${eqtName}:${eventName}`,`Contribution to the expected queueing time by ${eventName}`+' for a given renderer. It is computed as the maximum EQT in'+` a ${WINDOW_SIZE_MS}ms sliding window after shrinking top-level`+` tasks to contain only ${eventName} subevents`);const tasks=getTasks(rendererHelper);const totalSample=tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(rendererHelper.mainThread.bounds.min,rendererHelper.mainThread.bounds.max,WINDOW_SIZE_MS,tasks);totalHistogram.addSample(totalSample);totalBreakdown.set(eventName,totalSample);totalNames.set(eventName,totalHistogram.name);}
+return totalBreakdown;}
function getV8EventNamesWithTaskExtractors_(getEventTimes,cpuMetrics){function durationOfTopmostSubSlices(slice,predicate,excludePredicate){let duration=0;for(const sub of slice.findTopmostSlicesRelativeToThisSlice(predicate)){duration+=getEventTimes(sub).duration;if(excludePredicate!==null&&excludePredicate!==undefined){duration-=durationOfTopmostSubSlices(sub,excludePredicate);}}
return duration;}
function taskExtractor(predicate,excludePredicate){return function(rendererHelper){const slices=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const result=[];for(const slice of slices){const times=getEventTimes(slice);if(times.duration>0&&!containsForcedGC_(slice)){const duration=durationOfTopmostSubSlices(slice,predicate,excludePredicate);result.push({start:times.start,end:times.start+duration});}}
return result;};}
-return new Map([['v8',taskExtractor(tr.metrics.v8.utils.isV8Event)],['v8:execute',taskExtractor(tr.metrics.v8.utils.isV8ExecuteEvent)],['v8:gc',taskExtractor(tr.metrics.v8.utils.isGarbageCollectionEvent)],['v8:gc:full-mark-compactor',taskExtractor(tr.metrics.v8.utils.isFullMarkCompactorEvent)],['v8:gc:incremental-marking',taskExtractor(tr.metrics.v8.utils.isIncrementalMarkingEvent)],['v8:gc:latency-mark-compactor',taskExtractor(tr.metrics.v8.utils.isLatencyMarkCompactorEvent)],['v8:gc:memory-mark-compactor',taskExtractor(tr.metrics.v8.utils.isMemoryMarkCompactorEvent)],['v8:gc:scavenger',taskExtractor(tr.metrics.v8.utils.isScavengerEvent)]]);}
+return new Map([['v8',taskExtractor(tr.metrics.v8.utils.isV8Event)],['v8:execute',taskExtractor(tr.metrics.v8.utils.isV8ExecuteEvent)],['v8:gc',taskExtractor(tr.metrics.v8.utils.isGarbageCollectionEvent)]]);}
function extractTaskRCS(getEventTimes,predicate,rendererHelper){const result=[];for(const topSlice of
rendererHelper.mainThread.sliceGroup.topLevelSlices){const times=getEventTimes(topSlice);if(times.duration<=0||containsForcedGC_(topSlice)){continue;}
const v8ThreadSlices=[];for(const slice of topSlice.descendentSlices){if(tr.metrics.v8.utils.isV8RCSEvent(slice)){v8ThreadSlices.push(slice);}}
const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(v8ThreadSlices);let duration=0;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){if(predicate(runtimeGroup.name)){duration+=runtimeGroup.time;}}
duration=tr.b.convertUnit(duration,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);result.push({start:times.start,end:times.start+duration});}
return result;}
-function getV8EventNamesWithTaskExtractorsUsingRCS_(getEventTimes){const extractors=new Map();extractors.set('v8:compile_rcs',rendererHelper=>extractTaskRCS(getEventTimes,tr.metrics.v8.utils.isCompileRCSCategory,rendererHelper));extractors.set('v8:compile:optimize_rcs',rendererHelper=>extractTaskRCS(getEventTimes,tr.metrics.v8.utils.isCompileOptimizeRCSCategory,rendererHelper));extractors.set('v8:compile:parse_rcs',rendererHelper=>extractTaskRCS(getEventTimes,tr.metrics.v8.utils.isCompileParseRCSCategory,rendererHelper));extractors.set('v8:compile:compile-unoptimize_rcs',rendererHelper=>extractTaskRCS(getEventTimes,tr.metrics.v8.utils.isCompileUnoptimizeRCSCategory,rendererHelper));return extractors;}
-function contributionToExpectedQueueingTime_(eqtName,eventName,getTasks,rendererToInteractiveTimestamps,histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const totalHistogram=createHistogramForEQT_(`total:${WINDOW_SIZE_MS}ms_window:${eqtName}:${eventName}`,`Contribution to the expected queueing time by ${eventName}`+' for a given renderer. It is computed as the maximum EQT in'+` a ${WINDOW_SIZE_MS}ms sliding window after shrinking top-level`+` tasks to contain only ${eventName} subevents`);const interactiveHistogram=createHistogramForEQT_(`interactive:${WINDOW_SIZE_MS}ms_window:${eqtName}:${eventName}`,`Contribution to the expected queueing time by ${eventName}`+' for a given renderer while the page is interactive. It is computed'+` as the maximum EQT in a ${WINDOW_SIZE_MS}ms sliding window after`+` shrinking top-level tasks to contain only ${eventName} subevents`);const rendererHelpers=Object.values(chromeHelper.rendererHelpers);for(const rendererHelper of rendererHelpers){if(rendererHelper.isChromeTracingUI)continue;const tasks=getTasks(rendererHelper);totalHistogram.addSample(tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(rendererHelper.mainThread.bounds.min,rendererHelper.mainThread.bounds.max,WINDOW_SIZE_MS,tasks));const interactiveTimestamps=rendererToInteractiveTimestamps.get(rendererHelper.pid);if(interactiveTimestamps.length===0)continue;if(interactiveTimestamps.length>1){continue;}
-const interactiveWindow=tr.b.math.Range.fromExplicitRange(interactiveTimestamps[0],Infinity).findIntersection(rendererHelper.mainThread.bounds);interactiveHistogram.addSample(tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(interactiveWindow.min,interactiveWindow.max,WINDOW_SIZE_MS,tasks));}
-histograms.addHistogram(totalHistogram);histograms.addHistogram(interactiveHistogram);return{total:totalHistogram,interactive:interactiveHistogram};}
+function getV8EventNamesWithTaskExtractorsUsingRCS_(getEventTimes){const extractors=new Map();extractors.set('v8:compile_rcs',rendererHelper=>extractTaskRCS(getEventTimes,tr.metrics.v8.utils.isCompileRCSCategory,rendererHelper));extractors.set('v8:compile:optimize_rcs',rendererHelper=>extractTaskRCS(getEventTimes,tr.metrics.v8.utils.isCompileOptimizeRCSCategory,rendererHelper));return extractors;}
tr.metrics.MetricRegistry.register(expectedQueueingTimeMetric);return{expectedQueueingTimeMetric,};});'use strict';tr.exportTo('tr.b',function(){function MultiDimensionalViewNode(title,valueCount){this.title=title;const dimensions=title.length;this.children=new Array(dimensions);for(let i=0;i<dimensions;i++){this.children[i]=new Map();}
this.values=new Array(valueCount);for(let v=0;v<valueCount;v++){this.values[v]={self:0,total:0,totalState:NOT_PROVIDED};}}
MultiDimensionalViewNode.TotalState={NOT_PROVIDED:0,LOWER_BOUND:1,EXACT:2};const NOT_PROVIDED=MultiDimensionalViewNode.TotalState.NOT_PROVIDED;const LOWER_BOUND=MultiDimensionalViewNode.TotalState.LOWER_BOUND;const EXACT=MultiDimensionalViewNode.TotalState.EXACT;MultiDimensionalViewNode.prototype={get subRows(){return Array.from(this.children[0].values());}};function MultiDimensionalViewBuilder(dimensions,valueCount){if(typeof(dimensions)!=='number'||dimensions<0){throw new Error('Dimensions must be a non-negative number');}
@@ -8671,7 +8909,26 @@ const componentBreakdown=new tr.v.d.Breakdown();for(const[name,subNode]of node.c
if(componentBreakdown.size>0){diagnostics.set('components',componentBreakdown);}
if(diagnostics.size===0)return undefined;return diagnostics;}
function buildMemoryNumericFromNode(name,node,unit){const histogram=new tr.v.Histogram(name,unit,BOUNDARIES_FOR_UNIT_MAP.get(unit));node.values.forEach(v=>histogram.addSample(v.total,buildSampleDiagnostics(v,node)));return histogram;}
-tr.metrics.MetricRegistry.register(memoryMetric,{supportsRangeOfInterest:true});return{memoryMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const CHROME_POWER_GRACE_PERIOD_MS=1;function createEmptyHistogram_(interval,histograms){if(interval.perSecond){return{perSecond:true,energy:histograms.createHistogram(`${interval.name}:power`,tr.b.Unit.byName.powerInWatts_smallerIsBetter,[],{description:`Energy consumption rate for ${interval.description}`,summaryOptions:{avg:true,count:false,max:true,min:true,std:false,sum:false,},}),};}
+tr.metrics.MetricRegistry.register(memoryMetric,{supportsRangeOfInterest:true});return{memoryMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const BYTE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e9,1e2);function nativeCodeResidentMemoryMetric(histograms,model){const histogram=new tr.v.Histogram('NativeCodeResidentMemory',tr.b.Unit.byName.sizeInBytes_smallerIsBetter,BYTE_BOUNDARIES);for(const slice of model.getDescendantEvents()){if(slice.category==='disabled-by-default-memory-infra'&&slice.title==='ReportGlobalNativeCodeResidentMemoryKb'&&slice.args.NativeCodeResidentMemory){histogram.addSample(slice.args.NativeCodeResidentMemory);}}
+histograms.addHistogram(histogram);}
+tr.metrics.MetricRegistry.register(nativeCodeResidentMemoryMetric);return{nativeCodeResidentMemoryMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const EventFinderUtils=tr.e.chrome.EventFinderUtils;const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const SUMMARY_OPTIONS={avg:true,count:false,max:false,min:false,std:false,sum:false,};function addSamplesToHistogram(pairInfo,breakdownTree,histogram,histograms,diagnostics){histogram.addSample(pairInfo.end-pairInfo.start,diagnostics);if(!breakdownTree){return;}
+for(const[category,breakdown]of Object.entries(breakdownTree)){const relatedName=`${histogram.name}:${category}`;if(!histograms.getHistogramNamed(relatedName)){const relatedHist=histograms.createHistogram(relatedName,histogram.unit,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,summaryOptions:{count:false,max:false,min:false,sum:false,},});}
+const relatedHist=histograms.getHistogramNamed(relatedName);let relatedNames=histogram.diagnostics.get('breakdown');if(!relatedNames){relatedNames=new tr.v.d.RelatedNameMap();histogram.diagnostics.set('breakdown',relatedNames);}
+relatedNames.set(category,relatedName);relatedHist.addSample(breakdown.total,{breakdown:tr.v.d.Breakdown.fromEntries(Object.entries(breakdown.events)),});}}
+function splitOneRangeIntoPerSecondRanges(startTime,endTime){const results=[];for(let i=0;startTime+(i+1)*1000<=endTime;i+=1){const start=i*1000;const end=(i+1)*1000;results.push({start,end,});}
+return results;}
+function getNavigationInfos(model){const navigationInfos=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];navigationInfos.push({navigationStart:expectation.navigationStart,rendererHelper,url:expectation.url});}
+navigationInfos.forEach((navInfo,i)=>{if(i===navigationInfos.length-1){navInfo.navigationEndTime=model.bounds.max;}else{navInfo.navigationEndTime=navigationInfos[i+1].navigationStart.start;}});return navigationInfos;}
+function getRendererHelpers(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=[];for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;rendererHelpers.push(rendererHelper);}
+return rendererHelpers;}
+function getWallTimeBreakdownTree(rendererHelper,start,end){const startEndRange=tr.b.math.Range.fromExplicitRange(start,end);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,startEndRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,startEndRange);return breakdownTree;}
+function getCpuTimeBreakdownTree(rendererHelper,start,end){const startEndRange=tr.b.math.Range.fromExplicitRange(start,end);const breakdownTree=tr.metrics.sh.generateCpuTimeBreakdownTree(rendererHelper.mainThread,startEndRange);return breakdownTree;}
+function persecondMetric(histograms,model){const rendererHelpers=getRendererHelpers(model);const navigationInfos=getNavigationInfos(model);if(navigationInfos.length===0){return;}
+navigationInfos.forEach(navInfo=>{const navigationStart=navInfo.navigationStart.start;const navigationEnd=navInfo.navigationEndTime;const startEndPairs=splitOneRangeIntoPerSecondRanges(navigationStart,navigationEnd);const breakdownList=startEndPairs.map(p=>{const wallHistogramName=`wall_${p.start}_to_${p.end}`;const wallHistogramDescription=`Wall-clock time ${p.start} to ${p.end} breakdown`;const cpuHistogramName=`cpu_${p.start}_to_${p.end}`;const cpuHistogramDescription=`CPU time ${p.start} to ${p.end} breakdown`;const pid=navInfo.rendererHelper.pid;const breakdownTree=getWallTimeBreakdownTree(navInfo.rendererHelper,navigationStart+p.start,navigationStart+p.end);const cpuBreakdownTree=getCpuTimeBreakdownTree(navInfo.rendererHelper,navigationStart+p.start,navigationStart+p.end);const diagnostics={'Navigation infos':new tr.v.d.GenericSet([{url:navInfo.url,pid:navInfo.rendererHelper.pid,navStart:navigationStart,frameIdRef:navInfo.navigationStart.args.frame}]),'breakdown':tr.metrics.sh.createBreakdownDiagnostic(breakdownTree),};return Object.assign(p,{breakdownTree,cpuBreakdownTree,wallHistogramName,wallHistogramDescription,cpuHistogramName,cpuHistogramDescription,diagnostics,});});breakdownList.forEach(p=>{if(!histograms.getHistogramNamed(p.wallHistogramName)){histograms.createHistogram(p.wallHistogramName,timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:p.wallHistogramDescription,summaryOptions:SUMMARY_OPTIONS,});}
+const wallHistogram=histograms.getHistogramNamed(p.wallHistogramName);addSamplesToHistogram(p,p.breakdownTree,wallHistogram,histograms,p.diagnostics);if(!histograms.getHistogramNamed(p.cpuHistogramName)){histograms.createHistogram(p.cpuHistogramName,timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:p.cpuHistogramDescription,summaryOptions:SUMMARY_OPTIONS,});}
+const cpuHistogram=histograms.getHistogramNamed(p.cpuHistogramName);addSamplesToHistogram(p,p.cpuBreakdownTree,cpuHistogram,histograms,p.diagnostics);});});}
+tr.metrics.MetricRegistry.register(persecondMetric);return{persecondMetric,splitOneRangeIntoPerSecondRanges};});'use strict';tr.exportTo('tr.metrics.sh',function(){const CHROME_POWER_GRACE_PERIOD_MS=1;function createEmptyHistogram_(interval,histograms){if(interval.perSecond){return{perSecond:true,energy:histograms.createHistogram(`${interval.name}:power`,tr.b.Unit.byName.powerInWatts_smallerIsBetter,[],{description:`Energy consumption rate for ${interval.description}`,summaryOptions:{avg:true,count:false,max:true,min:true,std:false,sum:false,},}),};}
return{perSecond:false,energy:histograms.createHistogram(`${interval.name}:energy`,tr.b.Unit.byName.energyInJoules_smallerIsBetter,[],{description:`Energy consumed in ${interval.description}`,summaryOptions:{avg:false,count:false,max:true,min:true,std:false,sum:true,},}),};}
function createHistograms_(data,interval,histograms){if(data.histograms[interval.name]===undefined){data.histograms[interval.name]=createEmptyHistogram_(interval,histograms);}
if(data.histograms[interval.name].perSecond){for(const sample of data.model.device.powerSeries.getSamplesWithinRange(interval.bounds.min,interval.bounds.max)){data.histograms[interval.name].energy.addSample(sample.powerInW);}}else{const energyInJ=data.model.device.powerSeries.getEnergyConsumedInJ(interval.bounds.min,interval.bounds.max);data.histograms[interval.name].energy.addSample(energyInJ);}}
@@ -8688,7 +8945,46 @@ function computeChromeBounds_(model){const chromeBounds=new tr.b.math.Range();co
for(const pid in chromeHelper.rendererHelpers){if(chromeHelper.rendererHelpers[pid].mainThread){chromeBounds.addRange(chromeHelper.rendererHelpers[pid].mainThread.bounds);}}
return chromeBounds;}
function powerMetric(histograms,model){const data={model,histograms:{}};for(const interval of computeTimeIntervals_(model)){createHistograms_(data,interval,histograms);}}
-tr.metrics.MetricRegistry.register(powerMetric);return{powerMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function computeAnimationThroughput(animationExpectation){if(animationExpectation.frameEvents===undefined||animationExpectation.frameEvents.length===0){throw new Error('Animation missing frameEvents '+
+tr.metrics.MetricRegistry.register(powerMetric);return{powerMetric};});'use strict';tr.exportTo('tr.b.math',function(){function earthMoversDistance(firstHistogram,secondHistogram){const buckets=firstHistogram.length;if(secondHistogram.length!==buckets){throw new Error('Histograms have a different number of bins.');}
+const arrSum=arr=>arr.reduce((a,b)=>a+b,0);if(arrSum(firstHistogram)!==arrSum(secondHistogram)){throw new Error('The histograms\' sizes don\'t match.');}
+let total=0;let remainder=0;for(let bucket=0;bucket<buckets;bucket++){remainder+=secondHistogram[bucket]-
+firstHistogram[bucket];total+=Math.abs(remainder);}
+return total;}
+return{earthMoversDistance,};});'use strict';tr.exportTo('tr.e.chrome',function(){const earthMoversDistance=tr.b.math.earthMoversDistance;class SpeedIndex{static getSnapshotsProgress_(timestampedColorHistograms){const numberOfScreenshots=timestampedColorHistograms.length;const firstHistogram=timestampedColorHistograms[0].colorHistogram;const lastHistogram=timestampedColorHistograms[numberOfScreenshots-1].colorHistogram;const totalDistance=earthMoversDistance(firstHistogram[0],lastHistogram[0])+
+earthMoversDistance(firstHistogram[1],lastHistogram[1])+
+earthMoversDistance(firstHistogram[2],lastHistogram[2]);if(totalDistance===0){return[{value:1,ts:timestampedColorHistograms[0].ts}];}
+const snapshotsProgress=new Array(numberOfScreenshots);for(let i=0;i<numberOfScreenshots;i++){const histogram=timestampedColorHistograms[i].colorHistogram;const distance=earthMoversDistance(histogram[0],lastHistogram[0])+
+earthMoversDistance(histogram[1],lastHistogram[1])+
+earthMoversDistance(histogram[2],lastHistogram[2]);const moved=Math.max(totalDistance-distance,0);snapshotsProgress[i]={value:(moved/totalDistance),ts:timestampedColorHistograms[i].ts};}
+return snapshotsProgress;}
+static speedIndexFromSnapshotsProgress_(snapshotsProgress){if(snapshotsProgress.length===0){throw new Error('No snapshots were provided.');}
+let prevSnapshotTimeTaken=0;let prevSnapshotProgress=0;let speedIndex=0;const numberOfScreenshots=snapshotsProgress.length;for(let i=0;i<numberOfScreenshots;i++){const elapsed=snapshotsProgress[i].ts-prevSnapshotTimeTaken;speedIndex+=elapsed*(1.0-prevSnapshotProgress);prevSnapshotTimeTaken=snapshotsProgress[i].ts;prevSnapshotProgress=snapshotsProgress[i].value;}
+return Math.round(speedIndex);}
+static createColorHistogram(imagePixelValues){const n=imagePixelValues.length;const histogram=new Array(3);for(let j=0;j<3;j++){histogram[j]=new Array(256).fill(0);}
+for(let i=0;i<n;i+=4){const r=imagePixelValues[i];const g=imagePixelValues[i+1];const b=imagePixelValues[i+2];histogram[0][r]++;histogram[1][g]++;histogram[2][b]++;}
+return histogram;}
+static calculateSpeedIndex(timestampedColorHistograms){const snapshotsProgress=SpeedIndex.getSnapshotsProgress_(timestampedColorHistograms);return SpeedIndex.speedIndexFromSnapshotsProgress_(snapshotsProgress);}
+static lineSweep(lineSweepRects,viewport){const verticalSweepEdges=[];const horizontalSweepEdges=[];for(let i=0;i<lineSweepRects.length;i++){const rect=lineSweepRects[i];let left=rect.left;let right=rect.right;let top=rect.top;let bottom=rect.bottom;if(left>viewport.x+viewport.width)continue;if(right<viewport.x)continue;if(top>viewport.y+viewport.height)continue;if(bottom<viewport.y)continue;left=Math.max(left,viewport.y);right=Math.min(right,viewport.y+viewport.width);top=Math.max(top,viewport.y);bottom=Math.min(bottom,viewport.y+viewport.height);verticalSweepEdges.push({id:i,value:left,type:'left'},{id:i,value:right,type:'right'});horizontalSweepEdges.push({id:i,value:top,type:'top'},{id:i,value:bottom,type:'bottom'});}
+verticalSweepEdges.sort((a,b)=>a.value-b.value);horizontalSweepEdges.sort((a,b)=>a.value-b.value);const active=new Array(lineSweepRects.length).fill(false);let area=0;active[verticalSweepEdges[0].id]=true;for(let i=1;i<verticalSweepEdges.length;i++){const currentLine=verticalSweepEdges[i];const previousLine=verticalSweepEdges[i-1];const deltaX=currentLine.value-previousLine.value;if(deltaX===0)continue;let count=0;let firstRect;for(let j=0;j<horizontalSweepEdges.length;j++){if(active[horizontalSweepEdges[j].id]===true){if(horizontalSweepEdges[j].type==='top'){if(count===0){firstRect=j;}
+count++;}else{if(count===1){const deltaY=horizontalSweepEdges[j].value-
+horizontalSweepEdges[firstRect].value;area+=deltaX*deltaY;}
+count--;}}}
+active[currentLine.id]=(currentLine.type==='left');}
+return area;}
+static quadToRect(quad){const left=Math.min(quad[0],quad[2],quad[4]);const right=Math.max(quad[0],quad[2],quad[4]);const top=Math.min(quad[1],quad[3],quad[5]);const bottom=Math.max(quad[1],quad[3],quad[5]);return{left,right,top,bottom};}
+static calculateRectsBasedSpeedIndex(timestampedPaintRects,viewport){const numberOfRects=timestampedPaintRects.length;if(numberOfRects===0){throw new Error('Can\'t calculate speed index without any paint '+'rectangles.');}
+const areaAddedAtTimestamp=new Array(numberOfRects);const rects=[];let previousAreaOfUnion=0;let totalAreaOfUnion=0;for(let i=numberOfRects-1;i>=0;i--){rects.push(timestampedPaintRects[i].rect);const currentAreaOfUnion=SpeedIndex.lineSweep(rects,viewport);areaAddedAtTimestamp[numberOfRects-i-1]={value:currentAreaOfUnion-previousAreaOfUnion,ts:timestampedPaintRects[i].ts};totalAreaOfUnion+=areaAddedAtTimestamp[numberOfRects-i-1].value;previousAreaOfUnion=currentAreaOfUnion;}
+const paintProgressAtTimestamp=new Array(numberOfRects);let lastProgressRecorded=0;for(let i=0;i<numberOfRects;i++){paintProgressAtTimestamp[i]={value:areaAddedAtTimestamp[i].value/totalAreaOfUnion+
+lastProgressRecorded,ts:areaAddedAtTimestamp[i].ts};lastProgressRecorded=paintProgressAtTimestamp[i].value;}
+return SpeedIndex.speedIndexFromSnapshotsProgress_(paintProgressAtTimestamp);}}
+return{SpeedIndex,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const SpeedIndex=tr.e.chrome.SpeedIndex;const EventFinderUtils=tr.e.chrome.EventFinderUtils;const BIN_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function addRectsBasedSpeedIndexSample(samples,rendererHelper,navigationStart,loadDuration,frameID){let viewport;for(const event of EventFinderUtils.getMainThreadEvents(rendererHelper,'viewport','loading')){if(event.args.data.frameID===frameID&&event.start<(navigationStart+loadDuration)){viewport=event.args.data;break;}}
+if(!viewport)return;const timestampedPaintRects=[];for(const event of EventFinderUtils.getMainThreadEvents(rendererHelper,'PaintTracker::LayoutObjectPainted','loading')){if(event.start>=navigationStart&&event.start<navigationStart+loadDuration){const paintRect=event.args.data.visible_new_visual_rect;if(!paintRect)continue;timestampedPaintRects.push({rect:SpeedIndex.quadToRect(paintRect),ts:event.start});}}
+const numberOfRects=timestampedPaintRects.length;if(numberOfRects===0)return;samples.push({value:SpeedIndex.calculateRectsBasedSpeedIndex(timestampedPaintRects,viewport)-navigationStart});}
+function collectRectsBasedSpeedIndexSamplesFromLoadExpectations(model,chromeHelper){const rectsBasedSpeedIndexSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addRectsBasedSpeedIndexSample(rectsBasedSpeedIndexSamples,rendererHelper,expectation.navigationStart.start,expectation.duration,expectation.navigationStart.args.frame);}
+return rectsBasedSpeedIndexSamples;}
+function rectsBasedSpeedIndexMetric(histograms,model){const rectsBasedSpeedIndexHistogram=histograms.createHistogram('rectsBasedSpeedIndex',timeDurationInMs_smallerIsBetter,[],{binBoundaries:BIN_BOUNDARIES,description:' the average time at which visible parts of the'+' page are displayed (in ms).',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const samples=collectRectsBasedSpeedIndexSamplesFromLoadExpectations(model,chromeHelper);for(const sample of samples){rectsBasedSpeedIndexHistogram.addSample(sample.value);}}
+tr.metrics.MetricRegistry.register(rectsBasedSpeedIndexMetric);return{rectsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function computeAnimationThroughput(animationExpectation){if(animationExpectation.frameEvents===undefined||animationExpectation.frameEvents.length===0){throw new Error('Animation missing frameEvents '+
animationExpectation.stableId);}
const durationInS=tr.b.convertUnit(animationExpectation.duration,tr.b.UnitPrefixScale.METRIC.MILLI,tr.b.UnitPrefixScale.METRIC.NONE);return animationExpectation.frameEvents.length/durationInS;}
function computeAnimationframeTimeDiscrepancy(animationExpectation){if(animationExpectation.frameEvents===undefined||animationExpectation.frameEvents.length===0){throw new Error('Animation missing frameEvents '+
@@ -8702,15 +8998,134 @@ throughputNumeric.addSample(throughput,sampleDiagnosticMap);const frameTimeDiscr
ue.stableId);}
frameTimeDiscrepancyNumeric.addSample(frameTimeDiscrepancy,sampleDiagnosticMap);ue.associatedEvents.forEach(function(event){if(!(event instanceof tr.e.cc.InputLatencyAsyncSlice)){return;}
latencyNumeric.addSample(event.duration,sampleDiagnosticMap);});}else{throw new Error('Unrecognized stage for '+ue.stableId);}});[responseNumeric,throughputNumeric,frameTimeDiscrepancyNumeric,latencyNumeric].forEach(function(numeric){numeric.customizeSummaryOptions({avg:true,max:true,min:true,std:true});});histograms.addHistogram(responseNumeric);histograms.addHistogram(throughputNumeric);histograms.addHistogram(frameTimeDiscrepancyNumeric);histograms.addHistogram(latencyNumeric);}
-tr.metrics.MetricRegistry.register(responsivenessMetric,{supportsRangeOfInterest:true,requiredCategories:['rail'],});return{responsivenessMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function webviewStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('webview_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebView startup wall time';const startupCPUHist=new tr.v.Histogram('webview_startup_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupCPUHist.description='WebView startup CPU time';const loadWallHist=new tr.v.Histogram('webview_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebView blank URL load wall time';const loadCPUHist=new tr.v.Histogram('webview_url_load_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadCPUHist.description='WebView blank URL load CPU time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebViewStartupInterval'){startupWallHist.addSample(slice.duration);startupCPUHist.addSample(slice.cpuDuration);}
+tr.metrics.MetricRegistry.register(responsivenessMetric,{supportsRangeOfInterest:true,requiredCategories:['rail'],});return{responsivenessMetric,};});var JpegImage=(function jpegImage(){"use strict";var dctZigZag=new Int32Array([0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63]);var dctCos1=4017
+var dctSin1=799
+var dctCos3=3406
+var dctSin3=2276
+var dctCos6=1567
+var dctSin6=3784
+var dctSqrt2=5793
+var dctSqrt1d2=2896
+function constructor(){}
+function buildHuffmanTable(codeLengths,values){var k=0,code=[],i,j,length=16;while(length>0&&!codeLengths[length-1])
+length--;code.push({children:[],index:0});var p=code[0],q;for(i=0;i<length;i++){for(j=0;j<codeLengths[i];j++){p=code.pop();p.children[p.index]=values[k];while(p.index>0){p=code.pop();}
+p.index++;code.push(p);while(code.length<=i){code.push(q={children:[],index:0});p.children[p.index]=q.children;p=q;}
+k++;}
+if(i+1<length){code.push(q={children:[],index:0});p.children[p.index]=q.children;p=q;}}
+return code[0].children;}
+function decodeScan(data,offset,frame,components,resetInterval,spectralStart,spectralEnd,successivePrev,successive){var precision=frame.precision;var samplesPerLine=frame.samplesPerLine;var scanLines=frame.scanLines;var mcusPerLine=frame.mcusPerLine;var progressive=frame.progressive;var maxH=frame.maxH,maxV=frame.maxV;var startOffset=offset,bitsData=0,bitsCount=0;function readBit(){if(bitsCount>0){bitsCount--;return(bitsData>>bitsCount)&1;}
+bitsData=data[offset++];if(bitsData==0xFF){var nextByte=data[offset++];if(nextByte){throw new Error("unexpected marker: "+((bitsData<<8)|nextByte).toString(16));}}
+bitsCount=7;return bitsData>>>7;}
+function decodeHuffman(tree){var node=tree,bit;while((bit=readBit())!==null){node=node[bit];if(typeof node==='number')
+return node;if(typeof node!=='object')
+throw new Error("invalid huffman sequence");}
+return null;}
+function receive(length){var n=0;while(length>0){var bit=readBit();if(bit===null)return;n=(n<<1)|bit;length--;}
+return n;}
+function receiveAndExtend(length){var n=receive(length);if(n>=1<<(length-1))
+return n;return n+(-1<<length)+1;}
+function decodeBaseline(component,zz){var t=decodeHuffman(component.huffmanTableDC);var diff=t===0?0:receiveAndExtend(t);zz[0]=(component.pred+=diff);var k=1;while(k<64){var rs=decodeHuffman(component.huffmanTableAC);var s=rs&15,r=rs>>4;if(s===0){if(r<15)
+break;k+=16;continue;}
+k+=r;var z=dctZigZag[k];zz[z]=receiveAndExtend(s);k++;}}
+function decodeDCFirst(component,zz){var t=decodeHuffman(component.huffmanTableDC);var diff=t===0?0:(receiveAndExtend(t)<<successive);zz[0]=(component.pred+=diff);}
+function decodeDCSuccessive(component,zz){zz[0]|=readBit()<<successive;}
+var eobrun=0;function decodeACFirst(component,zz){if(eobrun>0){eobrun--;return;}
+var k=spectralStart,e=spectralEnd;while(k<=e){var rs=decodeHuffman(component.huffmanTableAC);var s=rs&15,r=rs>>4;if(s===0){if(r<15){eobrun=receive(r)+(1<<r)-1;break;}
+k+=16;continue;}
+k+=r;var z=dctZigZag[k];zz[z]=receiveAndExtend(s)*(1<<successive);k++;}}
+var successiveACState=0,successiveACNextValue;function decodeACSuccessive(component,zz){var k=spectralStart,e=spectralEnd,r=0;while(k<=e){var z=dctZigZag[k];var direction=zz[z]<0?-1:1;switch(successiveACState){case 0:var rs=decodeHuffman(component.huffmanTableAC);var s=rs&15,r=rs>>4;if(s===0){if(r<15){eobrun=receive(r)+(1<<r);successiveACState=4;}else{r=16;successiveACState=1;}}else{if(s!==1)
+throw new Error("invalid ACn encoding");successiveACNextValue=receiveAndExtend(s);successiveACState=r?2:3;}
+continue;case 1:case 2:if(zz[z])
+zz[z]+=(readBit()<<successive)*direction;else{r--;if(r===0)
+successiveACState=successiveACState==2?3:0;}
+break;case 3:if(zz[z])
+zz[z]+=(readBit()<<successive)*direction;else{zz[z]=successiveACNextValue<<successive;successiveACState=0;}
+break;case 4:if(zz[z])
+zz[z]+=(readBit()<<successive)*direction;break;}
+k++;}
+if(successiveACState===4){eobrun--;if(eobrun===0)
+successiveACState=0;}}
+function decodeMcu(component,decode,mcu,row,col){var mcuRow=(mcu/mcusPerLine)|0;var mcuCol=mcu%mcusPerLine;var blockRow=mcuRow*component.v+row;var blockCol=mcuCol*component.h+col;decode(component,component.blocks[blockRow][blockCol]);}
+function decodeBlock(component,decode,mcu){var blockRow=(mcu/component.blocksPerLine)|0;var blockCol=mcu%component.blocksPerLine;decode(component,component.blocks[blockRow][blockCol]);}
+var componentsLength=components.length;var component,i,j,k,n;var decodeFn;if(progressive){if(spectralStart===0)
+decodeFn=successivePrev===0?decodeDCFirst:decodeDCSuccessive;else
+decodeFn=successivePrev===0?decodeACFirst:decodeACSuccessive;}else{decodeFn=decodeBaseline;}
+var mcu=0,marker;var mcuExpected;if(componentsLength==1){mcuExpected=components[0].blocksPerLine*components[0].blocksPerColumn;}else{mcuExpected=mcusPerLine*frame.mcusPerColumn;}
+if(!resetInterval)resetInterval=mcuExpected;var h,v;while(mcu<mcuExpected){for(i=0;i<componentsLength;i++)
+components[i].pred=0;eobrun=0;if(componentsLength==1){component=components[0];for(n=0;n<resetInterval;n++){decodeBlock(component,decodeFn,mcu);mcu++;}}else{for(n=0;n<resetInterval;n++){for(i=0;i<componentsLength;i++){component=components[i];h=component.h;v=component.v;for(j=0;j<v;j++){for(k=0;k<h;k++){decodeMcu(component,decodeFn,mcu,j,k);}}}
+mcu++;if(mcu===mcuExpected)break;}}
+bitsCount=0;marker=(data[offset]<<8)|data[offset+1];if(marker<0xFF00){throw new Error("marker was not found");}
+if(marker>=0xFFD0&&marker<=0xFFD7){offset+=2;}
+else
+break;}
+return offset-startOffset;}
+function buildComponentData(frame,component){var lines=[];var blocksPerLine=component.blocksPerLine;var blocksPerColumn=component.blocksPerColumn;var samplesPerLine=blocksPerLine<<3;var R=new Int32Array(64),r=new Uint8Array(64);function quantizeAndInverse(zz,dataOut,dataIn){var qt=component.quantizationTable;var v0,v1,v2,v3,v4,v5,v6,v7,t;var p=dataIn;var i;for(i=0;i<64;i++)
+p[i]=zz[i]*qt[i];for(i=0;i<8;++i){var row=8*i;if(p[1+row]==0&&p[2+row]==0&&p[3+row]==0&&p[4+row]==0&&p[5+row]==0&&p[6+row]==0&&p[7+row]==0){t=(dctSqrt2*p[0+row]+512)>>10;p[0+row]=t;p[1+row]=t;p[2+row]=t;p[3+row]=t;p[4+row]=t;p[5+row]=t;p[6+row]=t;p[7+row]=t;continue;}
+v0=(dctSqrt2*p[0+row]+128)>>8;v1=(dctSqrt2*p[4+row]+128)>>8;v2=p[2+row];v3=p[6+row];v4=(dctSqrt1d2*(p[1+row]-p[7+row])+128)>>8;v7=(dctSqrt1d2*(p[1+row]+p[7+row])+128)>>8;v5=p[3+row]<<4;v6=p[5+row]<<4;t=(v0-v1+1)>>1;v0=(v0+v1+1)>>1;v1=t;t=(v2*dctSin6+v3*dctCos6+128)>>8;v2=(v2*dctCos6-v3*dctSin6+128)>>8;v3=t;t=(v4-v6+1)>>1;v4=(v4+v6+1)>>1;v6=t;t=(v7+v5+1)>>1;v5=(v7-v5+1)>>1;v7=t;t=(v0-v3+1)>>1;v0=(v0+v3+1)>>1;v3=t;t=(v1-v2+1)>>1;v1=(v1+v2+1)>>1;v2=t;t=(v4*dctSin3+v7*dctCos3+2048)>>12;v4=(v4*dctCos3-v7*dctSin3+2048)>>12;v7=t;t=(v5*dctSin1+v6*dctCos1+2048)>>12;v5=(v5*dctCos1-v6*dctSin1+2048)>>12;v6=t;p[0+row]=v0+v7;p[7+row]=v0-v7;p[1+row]=v1+v6;p[6+row]=v1-v6;p[2+row]=v2+v5;p[5+row]=v2-v5;p[3+row]=v3+v4;p[4+row]=v3-v4;}
+for(i=0;i<8;++i){var col=i;if(p[1*8+col]==0&&p[2*8+col]==0&&p[3*8+col]==0&&p[4*8+col]==0&&p[5*8+col]==0&&p[6*8+col]==0&&p[7*8+col]==0){t=(dctSqrt2*dataIn[i+0]+8192)>>14;p[0*8+col]=t;p[1*8+col]=t;p[2*8+col]=t;p[3*8+col]=t;p[4*8+col]=t;p[5*8+col]=t;p[6*8+col]=t;p[7*8+col]=t;continue;}
+v0=(dctSqrt2*p[0*8+col]+2048)>>12;v1=(dctSqrt2*p[4*8+col]+2048)>>12;v2=p[2*8+col];v3=p[6*8+col];v4=(dctSqrt1d2*(p[1*8+col]-p[7*8+col])+2048)>>12;v7=(dctSqrt1d2*(p[1*8+col]+p[7*8+col])+2048)>>12;v5=p[3*8+col];v6=p[5*8+col];t=(v0-v1+1)>>1;v0=(v0+v1+1)>>1;v1=t;t=(v2*dctSin6+v3*dctCos6+2048)>>12;v2=(v2*dctCos6-v3*dctSin6+2048)>>12;v3=t;t=(v4-v6+1)>>1;v4=(v4+v6+1)>>1;v6=t;t=(v7+v5+1)>>1;v5=(v7-v5+1)>>1;v7=t;t=(v0-v3+1)>>1;v0=(v0+v3+1)>>1;v3=t;t=(v1-v2+1)>>1;v1=(v1+v2+1)>>1;v2=t;t=(v4*dctSin3+v7*dctCos3+2048)>>12;v4=(v4*dctCos3-v7*dctSin3+2048)>>12;v7=t;t=(v5*dctSin1+v6*dctCos1+2048)>>12;v5=(v5*dctCos1-v6*dctSin1+2048)>>12;v6=t;p[0*8+col]=v0+v7;p[7*8+col]=v0-v7;p[1*8+col]=v1+v6;p[6*8+col]=v1-v6;p[2*8+col]=v2+v5;p[5*8+col]=v2-v5;p[3*8+col]=v3+v4;p[4*8+col]=v3-v4;}
+for(i=0;i<64;++i){var sample=128+((p[i]+8)>>4);dataOut[i]=sample<0?0:sample>0xFF?0xFF:sample;}}
+var i,j;for(var blockRow=0;blockRow<blocksPerColumn;blockRow++){var scanLine=blockRow<<3;for(i=0;i<8;i++)
+lines.push(new Uint8Array(samplesPerLine));for(var blockCol=0;blockCol<blocksPerLine;blockCol++){quantizeAndInverse(component.blocks[blockRow][blockCol],r,R);var offset=0,sample=blockCol<<3;for(j=0;j<8;j++){var line=lines[scanLine+j];for(i=0;i<8;i++)
+line[sample+i]=r[offset++];}}}
+return lines;}
+function clampTo8bit(a){return a<0?0:a>255?255:a;}
+constructor.prototype={load:function load(path){var xhr=new XMLHttpRequest();xhr.open("GET",path,true);xhr.responseType="arraybuffer";xhr.onload=(function(){var data=new Uint8Array(xhr.response||xhr.mozResponseArrayBuffer);this.parse(data);if(this.onload)
+this.onload();}).bind(this);xhr.send(null);},parse:function parse(data){var offset=0,length=data.length;function readUint16(){var value=(data[offset]<<8)|data[offset+1];offset+=2;return value;}
+function readDataBlock(){var length=readUint16();var array=data.subarray(offset,offset+length-2);offset+=array.length;return array;}
+function prepareComponents(frame){var maxH=0,maxV=0;var component,componentId;for(componentId in frame.components){if(frame.components.hasOwnProperty(componentId)){component=frame.components[componentId];if(maxH<component.h)maxH=component.h;if(maxV<component.v)maxV=component.v;}}
+var mcusPerLine=Math.ceil(frame.samplesPerLine/8/maxH);var mcusPerColumn=Math.ceil(frame.scanLines/8/maxV);for(componentId in frame.components){if(frame.components.hasOwnProperty(componentId)){component=frame.components[componentId];var blocksPerLine=Math.ceil(Math.ceil(frame.samplesPerLine/8)*component.h/maxH);var blocksPerColumn=Math.ceil(Math.ceil(frame.scanLines/8)*component.v/maxV);var blocksPerLineForMcu=mcusPerLine*component.h;var blocksPerColumnForMcu=mcusPerColumn*component.v;var blocks=[];for(var i=0;i<blocksPerColumnForMcu;i++){var row=[];for(var j=0;j<blocksPerLineForMcu;j++)
+row.push(new Int32Array(64));blocks.push(row);}
+component.blocksPerLine=blocksPerLine;component.blocksPerColumn=blocksPerColumn;component.blocks=blocks;}}
+frame.maxH=maxH;frame.maxV=maxV;frame.mcusPerLine=mcusPerLine;frame.mcusPerColumn=mcusPerColumn;}
+var jfif=null;var adobe=null;var pixels=null;var frame,resetInterval;var quantizationTables=[],frames=[];var huffmanTablesAC=[],huffmanTablesDC=[];var fileMarker=readUint16();if(fileMarker!=0xFFD8){throw new Error("SOI not found");}
+fileMarker=readUint16();while(fileMarker!=0xFFD9){var i,j,l;switch(fileMarker){case 0xFF00:break;case 0xFFE0:case 0xFFE1:case 0xFFE2:case 0xFFE3:case 0xFFE4:case 0xFFE5:case 0xFFE6:case 0xFFE7:case 0xFFE8:case 0xFFE9:case 0xFFEA:case 0xFFEB:case 0xFFEC:case 0xFFED:case 0xFFEE:case 0xFFEF:case 0xFFFE:var appData=readDataBlock();if(fileMarker===0xFFE0){if(appData[0]===0x4A&&appData[1]===0x46&&appData[2]===0x49&&appData[3]===0x46&&appData[4]===0){jfif={version:{major:appData[5],minor:appData[6]},densityUnits:appData[7],xDensity:(appData[8]<<8)|appData[9],yDensity:(appData[10]<<8)|appData[11],thumbWidth:appData[12],thumbHeight:appData[13],thumbData:appData.subarray(14,14+3*appData[12]*appData[13])};}}
+if(fileMarker===0xFFEE){if(appData[0]===0x41&&appData[1]===0x64&&appData[2]===0x6F&&appData[3]===0x62&&appData[4]===0x65&&appData[5]===0){adobe={version:appData[6],flags0:(appData[7]<<8)|appData[8],flags1:(appData[9]<<8)|appData[10],transformCode:appData[11]};}}
+break;case 0xFFDB:var quantizationTablesLength=readUint16();var quantizationTablesEnd=quantizationTablesLength+offset-2;while(offset<quantizationTablesEnd){var quantizationTableSpec=data[offset++];var tableData=new Int32Array(64);if((quantizationTableSpec>>4)===0){for(j=0;j<64;j++){var z=dctZigZag[j];tableData[z]=data[offset++];}}else if((quantizationTableSpec>>4)===1){for(j=0;j<64;j++){var z=dctZigZag[j];tableData[z]=readUint16();}}else
+throw new Error("DQT: invalid table spec");quantizationTables[quantizationTableSpec&15]=tableData;}
+break;case 0xFFC0:case 0xFFC1:case 0xFFC2:readUint16();frame={};frame.extended=(fileMarker===0xFFC1);frame.progressive=(fileMarker===0xFFC2);frame.precision=data[offset++];frame.scanLines=readUint16();frame.samplesPerLine=readUint16();frame.components={};frame.componentsOrder=[];var componentsCount=data[offset++],componentId;var maxH=0,maxV=0;for(i=0;i<componentsCount;i++){componentId=data[offset];var h=data[offset+1]>>4;var v=data[offset+1]&15;var qId=data[offset+2];frame.componentsOrder.push(componentId);frame.components[componentId]={h:h,v:v,quantizationIdx:qId};offset+=3;}
+prepareComponents(frame);frames.push(frame);break;case 0xFFC4:var huffmanLength=readUint16();for(i=2;i<huffmanLength;){var huffmanTableSpec=data[offset++];var codeLengths=new Uint8Array(16);var codeLengthSum=0;for(j=0;j<16;j++,offset++)
+codeLengthSum+=(codeLengths[j]=data[offset]);var huffmanValues=new Uint8Array(codeLengthSum);for(j=0;j<codeLengthSum;j++,offset++)
+huffmanValues[j]=data[offset];i+=17+codeLengthSum;((huffmanTableSpec>>4)===0?huffmanTablesDC:huffmanTablesAC)[huffmanTableSpec&15]=buildHuffmanTable(codeLengths,huffmanValues);}
+break;case 0xFFDD:readUint16();resetInterval=readUint16();break;case 0xFFDA:var scanLength=readUint16();var selectorsCount=data[offset++];var components=[],component;for(i=0;i<selectorsCount;i++){component=frame.components[data[offset++]];var tableSpec=data[offset++];component.huffmanTableDC=huffmanTablesDC[tableSpec>>4];component.huffmanTableAC=huffmanTablesAC[tableSpec&15];components.push(component);}
+var spectralStart=data[offset++];var spectralEnd=data[offset++];var successiveApproximation=data[offset++];var processed=decodeScan(data,offset,frame,components,resetInterval,spectralStart,spectralEnd,successiveApproximation>>4,successiveApproximation&15);offset+=processed;break;case 0xFFFF:if(data[offset]!==0xFF){offset--;}
+break;default:if(data[offset-3]==0xFF&&data[offset-2]>=0xC0&&data[offset-2]<=0xFE){offset-=3;break;}
+throw new Error("unknown JPEG marker "+fileMarker.toString(16));}
+fileMarker=readUint16();}
+if(frames.length!=1)
+throw new Error("only single frame JPEGs supported");for(var i=0;i<frames.length;i++){var cp=frames[i].components;for(var j in cp){cp[j].quantizationTable=quantizationTables[cp[j].quantizationIdx];delete cp[j].quantizationIdx;}}
+this.width=frame.samplesPerLine;this.height=frame.scanLines;this.jfif=jfif;this.adobe=adobe;this.components=[];for(var i=0;i<frame.componentsOrder.length;i++){var component=frame.components[frame.componentsOrder[i]];this.components.push({lines:buildComponentData(frame,component),scaleX:component.h/frame.maxH,scaleY:component.v/frame.maxV});}},getData:function getData(width,height){var scaleX=this.width/width,scaleY=this.height/height;var component1,component2,component3,component4;var component1Line,component2Line,component3Line,component4Line;var x,y;var offset=0;var Y,Cb,Cr,K,C,M,Ye,R,G,B;var colorTransform;var dataLength=width*height*this.components.length;var data=new Uint8Array(dataLength);switch(this.components.length){case 1:component1=this.components[0];for(y=0;y<height;y++){component1Line=component1.lines[0|(y*component1.scaleY*scaleY)];for(x=0;x<width;x++){Y=component1Line[0|(x*component1.scaleX*scaleX)];data[offset++]=Y;}}
+break;case 2:component1=this.components[0];component2=this.components[1];for(y=0;y<height;y++){component1Line=component1.lines[0|(y*component1.scaleY*scaleY)];component2Line=component2.lines[0|(y*component2.scaleY*scaleY)];for(x=0;x<width;x++){Y=component1Line[0|(x*component1.scaleX*scaleX)];data[offset++]=Y;Y=component2Line[0|(x*component2.scaleX*scaleX)];data[offset++]=Y;}}
+break;case 3:colorTransform=true;if(this.adobe&&this.adobe.transformCode)
+colorTransform=true;else if(typeof this.colorTransform!=='undefined')
+colorTransform=!!this.colorTransform;component1=this.components[0];component2=this.components[1];component3=this.components[2];for(y=0;y<height;y++){component1Line=component1.lines[0|(y*component1.scaleY*scaleY)];component2Line=component2.lines[0|(y*component2.scaleY*scaleY)];component3Line=component3.lines[0|(y*component3.scaleY*scaleY)];for(x=0;x<width;x++){if(!colorTransform){R=component1Line[0|(x*component1.scaleX*scaleX)];G=component2Line[0|(x*component2.scaleX*scaleX)];B=component3Line[0|(x*component3.scaleX*scaleX)];}else{Y=component1Line[0|(x*component1.scaleX*scaleX)];Cb=component2Line[0|(x*component2.scaleX*scaleX)];Cr=component3Line[0|(x*component3.scaleX*scaleX)];R=clampTo8bit(Y+1.402*(Cr-128));G=clampTo8bit(Y-0.3441363*(Cb-128)-0.71413636*(Cr-128));B=clampTo8bit(Y+1.772*(Cb-128));}
+data[offset++]=R;data[offset++]=G;data[offset++]=B;}}
+break;case 4:if(!this.adobe)
+throw new Error('Unsupported color mode (4 components)');colorTransform=false;if(this.adobe&&this.adobe.transformCode)
+colorTransform=true;else if(typeof this.colorTransform!=='undefined')
+colorTransform=!!this.colorTransform;component1=this.components[0];component2=this.components[1];component3=this.components[2];component4=this.components[3];for(y=0;y<height;y++){component1Line=component1.lines[0|(y*component1.scaleY*scaleY)];component2Line=component2.lines[0|(y*component2.scaleY*scaleY)];component3Line=component3.lines[0|(y*component3.scaleY*scaleY)];component4Line=component4.lines[0|(y*component4.scaleY*scaleY)];for(x=0;x<width;x++){if(!colorTransform){C=component1Line[0|(x*component1.scaleX*scaleX)];M=component2Line[0|(x*component2.scaleX*scaleX)];Ye=component3Line[0|(x*component3.scaleX*scaleX)];K=component4Line[0|(x*component4.scaleX*scaleX)];}else{Y=component1Line[0|(x*component1.scaleX*scaleX)];Cb=component2Line[0|(x*component2.scaleX*scaleX)];Cr=component3Line[0|(x*component3.scaleX*scaleX)];K=component4Line[0|(x*component4.scaleX*scaleX)];C=255-clampTo8bit(Y+1.402*(Cr-128));M=255-clampTo8bit(Y-0.3441363*(Cb-128)-0.71413636*(Cr-128));Ye=255-clampTo8bit(Y+1.772*(Cb-128));}
+data[offset++]=255-C;data[offset++]=255-M;data[offset++]=255-Ye;data[offset++]=255-K;}}
+break;default:throw new Error('Unsupported color mode');}
+return data;},copyToImageData:function copyToImageData(imageData){var width=imageData.width,height=imageData.height;var imageDataArray=imageData.data;var data=this.getData(width,height);var i=0,j=0,x,y;var Y,K,C,M,R,G,B;switch(this.components.length){case 1:for(y=0;y<height;y++){for(x=0;x<width;x++){Y=data[i++];imageDataArray[j++]=Y;imageDataArray[j++]=Y;imageDataArray[j++]=Y;imageDataArray[j++]=255;}}
+break;case 3:for(y=0;y<height;y++){for(x=0;x<width;x++){R=data[i++];G=data[i++];B=data[i++];imageDataArray[j++]=R;imageDataArray[j++]=G;imageDataArray[j++]=B;imageDataArray[j++]=255;}}
+break;case 4:for(y=0;y<height;y++){for(x=0;x<width;x++){C=data[i++];M=data[i++];Y=data[i++];K=data[i++];R=255-clampTo8bit(C*(1-K/255)+K);G=255-clampTo8bit(M*(1-K/255)+K);B=255-clampTo8bit(Y*(1-K/255)+K);imageDataArray[j++]=R;imageDataArray[j++]=G;imageDataArray[j++]=B;imageDataArray[j++]=255;}}
+break;default:throw new Error('Unsupported color mode');}}};return constructor;})();global.jpegDecode=decode;function decode(jpegData,opts){var defaultOpts={useTArray:false,colorTransform:true};if(opts){if(typeof opts==='object'){opts={useTArray:(typeof opts.useTArray==='undefined'?defaultOpts.useTArray:opts.useTArray),colorTransform:(typeof opts.colorTransform==='undefined'?defaultOpts.colorTransform:opts.colorTransform)};}else{opts=defaultOpts;opts.useTArray=true;}}else{opts=defaultOpts;}
+var arr=new Uint8Array(jpegData);var decoder=new JpegImage();decoder.parse(arr);decoder.colorTransform=opts.colorTransform;var image={width:decoder.width,height:decoder.height,data:opts.useTArray?new Uint8Array(decoder.width*decoder.height*4):new Buffer(decoder.width*decoder.height*4)};decoder.copyToImageData(image);return image;}'use strict';tr.exportTo('tr.metrics.sh',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const SpeedIndex=tr.e.chrome.SpeedIndex;const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function addSpeedIndexScreenshotsBasedSample(samples,navigationStart,browserHelper){const screenshotObjects=browserHelper.process.objects.getAllInstancesNamed('Screenshot');if(!screenshotObjects)return;for(let i=0;i<screenshotObjects.length;i++){const snapshots=screenshotObjects[i].snapshots;const timestampedColorHistograms=[];snapshots.map(snapshot=>{if(snapshot.ts>=navigationStart.start){timestampedColorHistograms.push({colorHistogram:SpeedIndex.createColorHistogram(getPixelData(snapshot.args)),ts:snapshot.ts});}});samples.push({value:SpeedIndex.calculateSpeedIndex(timestampedColorHistograms)-
+navigationStart.start});}}
+function getPixelData(base64JpegImage){const binaryString=atob(base64JpegImage);const bytes=new DataView(new ArrayBuffer(base64JpegImage.length));tr.b.Base64.DecodeToTypedArray(base64JpegImage,bytes);const rawImageData=jpegDecode(bytes.buffer,{useTArray:true});return rawImageData.data;}
+function collectSpeedIndexSamplesFromLoadExpectations(model,chromeHelper){const speedIndexScreenshotsBasedSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addSpeedIndexScreenshotsBasedSample(speedIndexScreenshotsBasedSamples,expectation.navigationStart,chromeHelper.browserHelper);}
+return speedIndexScreenshotsBasedSamples;}
+function screenshotsBasedSpeedIndexMetric(histograms,model){const speedIndexScreenshotsBasedHistogram=histograms.createHistogram('speedIndexScreenshotsBased',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'The average time at which visible parts of the'+' page are displayed.',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const samples=collectSpeedIndexSamplesFromLoadExpectations(model,chromeHelper);for(const sample of samples){speedIndexScreenshotsBasedHistogram.addSample(sample.value);}}
+tr.metrics.MetricRegistry.register(screenshotsBasedSpeedIndexMetric);return{screenshotsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function webviewStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('webview_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebView startup wall time';const startupCPUHist=new tr.v.Histogram('webview_startup_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupCPUHist.description='WebView startup CPU time';const loadWallHist=new tr.v.Histogram('webview_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebView blank URL load wall time';const loadCPUHist=new tr.v.Histogram('webview_url_load_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadCPUHist.description='WebView blank URL load CPU time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebViewStartupInterval'){startupWallHist.addSample(slice.duration);startupCPUHist.addSample(slice.cpuDuration);}
if(slice.title==='WebViewBlankUrlLoadInterval'){loadWallHist.addSample(slice.duration);loadCPUHist.addSample(slice.cpuDuration);}}
histograms.addHistogram(startupWallHist);histograms.addHistogram(startupCPUHist);histograms.addHistogram(loadWallHist);histograms.addHistogram(loadCPUHist);}
tr.metrics.MetricRegistry.register(webviewStartupMetric);return{webviewStartupMetric,};});'use strict';tr.exportTo('tr.metrics.tabs',function(){function tabsMetric(histograms,model,opt_options){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper){return;}
-const tabSwitchLatencies=[];const TAB_SWITCHING_SLICE_TITLE='TabSwitching::Latency';function extractLatencyFromHelpers(helpers,legacy){for(const helper of helpers){if(!helper.mainThread){continue;}
-const thread=helper.mainThread;for(const slice of thread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_SLICE_TITLE&&(legacy||slice.args.latency)){tabSwitchLatencies.push(legacy?slice.duration:slice.args.latency);}}}}
+const tabSwitchRequestDelays=[];const TAB_SWITCHING_REQUEST_TITLE='TabSwitchVisibilityRequest';let startTabSwitchVisibilityRequest=Number.MAX_SAFE_INTEGER;for(const helper of chromeHelper.browserHelpers){if(!helper.mainThread)continue;for(const slice of helper.mainThread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_REQUEST_TITLE&&!slice.error){tabSwitchRequestDelays.push(slice.duration);if(slice.start<startTabSwitchVisibilityRequest){startTabSwitchVisibilityRequest=slice.start;}}}}
+histograms.createHistogram('tab_switching_request_delay',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchRequestDelays,{description:'Delay before tab-request is made',summaryOptions:{sum:false}});const tabSwitchLatencies=[];const TAB_SWITCHING_SLICE_TITLE='TabSwitching::Latency';function extractLatencyFromHelpers(helpers,legacy){for(const helper of helpers){if(!helper.mainThread){continue;}
+const thread=helper.mainThread;for(const slice of thread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_SLICE_TITLE&&(legacy||slice.args.latency)&&slice.start>startTabSwitchVisibilityRequest){tabSwitchLatencies.push(legacy?slice.duration:slice.args.latency);}}}}
extractLatencyFromHelpers(chromeHelper.browserHelpers);extractLatencyFromHelpers(Object.values(chromeHelper.rendererHelpers));if(tabSwitchLatencies.length===0){extractLatencyFromHelpers(chromeHelper.browserHelpers,true);}
-histograms.createHistogram('tab_switching_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchLatencies,{description:'Tab switching time in ms',summaryOptions:{sum:false}});const tabSwitchRequestDelays=[];const TAB_SWITCHING_REQUEST_TITLE='TabSwitchVisibilityRequest';for(const helper of chromeHelper.browserHelpers){if(!helper.mainThread)continue;for(const slice of helper.mainThread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_REQUEST_TITLE&&!slice.error){tabSwitchRequestDelays.push(slice.duration);}}}
-histograms.createHistogram('tab_switching_request_delay',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchRequestDelays,{description:'Delay before tab-request is made',summaryOptions:{sum:false}});}
+histograms.createHistogram('tab_switching_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchLatencies,{description:'Tab switching time in ms',summaryOptions:{sum:false}});}
tr.metrics.MetricRegistry.register(tabsMetric,{supportsRangeOfInterest:false,});return{tabsMetric,};});'use strict';tr.exportTo('tr.metrics',function(){const MEMORY_INFRA_TRACING_CATEGORY='disabled-by-default-memory-infra';const TIME_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1e-3,1e5,30);const BYTE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e9,30);const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e5,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;function addMemoryInfraHistograms(histograms,model,categoryNamesToTotalEventSizes){const memoryDumpCount=model.globalMemoryDumps.length;if(memoryDumpCount===0)return;let totalOverhead=0;let nonMemoryInfraThreadOverhead=0;const overheadByProvider={};for(const process of Object.values(model.processes)){for(const thread of Object.values(process.threads)){for(const slice of Object.values(thread.sliceGroup.slices)){if(slice.category!==MEMORY_INFRA_TRACING_CATEGORY)continue;totalOverhead+=slice.duration;if(thread.name!=='MemoryInfra'){nonMemoryInfraThreadOverhead+=slice.duration;}
if(slice.args&&slice.args['dump_provider.name']){const providerName=slice.args['dump_provider.name'];let durationAndCount=overheadByProvider[providerName];if(durationAndCount===undefined){overheadByProvider[providerName]=durationAndCount={duration:0,count:0};}
durationAndCount.duration+=slice.duration;durationAndCount.count++;}}}}
@@ -8721,7 +9136,27 @@ eventStats[start].timeInterval)>=INTERVALS_PER_SEC){runningEventNumPerSec-=event
maxEventCountPerSec=Math.max(maxEventCountPerSec,runningEventNumPerSec);maxEventBytesPerSec=Math.max(maxEventBytesPerSec,runningEventBytesPerSec);}
const stats=model.stats.allTraceEventStats;const categoryNamesToTotalEventSizes=(stats.reduce((map,stat)=>(map.set(stat.category,((map.get(stat.category)||0)+
stat.totalEventSizeinBytes))),new Map()));const maxCatNameAndBytes=Array.from(categoryNamesToTotalEventSizes.entries()).reduce((a,b)=>((b[1]>=a[1])?b:a));const maxEventBytesPerCategory=maxCatNameAndBytes[1];const categoryWithMaxEventBytes=maxCatNameAndBytes[0];const maxEventCountPerSecValue=new tr.v.Histogram('peak_event_rate',tr.b.Unit.byName.count_smallerIsBetter,COUNT_BOUNDARIES);maxEventCountPerSecValue.description='Max number of events per second';maxEventCountPerSecValue.customizeSummaryOptions(SUMMARY_OPTIONS);maxEventCountPerSecValue.addSample(maxEventCountPerSec);const maxEventBytesPerSecValue=new tr.v.Histogram('peak_event_size_rate',tr.b.Unit.byName.sizeInBytes_smallerIsBetter,BYTE_BOUNDARIES);maxEventBytesPerSecValue.description='Max event size in bytes per second';maxEventBytesPerSecValue.customizeSummaryOptions(SUMMARY_OPTIONS);maxEventBytesPerSecValue.addSample(maxEventBytesPerSec);const totalTraceBytesValue=new tr.v.Histogram('trace_size',tr.b.Unit.byName.sizeInBytes_smallerIsBetter,BYTE_BOUNDARIES);totalTraceBytesValue.customizeSummaryOptions(SUMMARY_OPTIONS);totalTraceBytesValue.addSample(totalTraceBytes);const biggestCategory={name:categoryWithMaxEventBytes,size_in_bytes:maxEventBytesPerCategory};totalTraceBytesValue.diagnostics.set('category_with_max_event_size',new tr.v.d.GenericSet([biggestCategory]));histograms.addHistogram(totalTraceBytesValue);maxEventCountPerSecValue.diagnostics.set('category_with_max_event_size',new tr.v.d.GenericSet([biggestCategory]));histograms.addHistogram(maxEventCountPerSecValue);maxEventBytesPerSecValue.diagnostics.set('category_with_max_event_size',new tr.v.d.GenericSet([biggestCategory]));histograms.addHistogram(maxEventBytesPerSecValue);addMemoryInfraHistograms(histograms,model,categoryNamesToTotalEventSizes);}
-tr.metrics.MetricRegistry.register(tracingMetric);return{tracingMetric,MEMORY_INFRA_TRACING_CATEGORY,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(4,200,100);function computeExecuteMetrics(histograms,model){const cpuTotalExecution=new tr.v.Histogram('v8_execution_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalExecution.description='cpu total time spent in script execution';const wallTotalExecution=new tr.v.Histogram('v8_execution_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalExecution.description='wall total time spent in script execution';const cpuSelfExecution=new tr.v.Histogram('v8_execution_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfExecution.description='cpu self time spent in script execution';const wallSelfExecution=new tr.v.Histogram('v8_execution_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfExecution.description='wall self time spent in script execution';for(const e of model.findTopmostSlicesNamed('V8.Execute')){cpuTotalExecution.addSample(e.cpuDuration);wallTotalExecution.addSample(e.duration);cpuSelfExecution.addSample(e.cpuSelfTime);wallSelfExecution.addSample(e.selfTime);}
+tr.metrics.MetricRegistry.register(tracingMetric);return{tracingMetric,MEMORY_INFRA_TRACING_CATEGORY,};});'use strict';tr.exportTo('tr.metrics',function(){function parseBuckets_(event,processName){const len=tr.b.Base64.getDecodedBufferLength(event.args.buckets);const buffer=new ArrayBuffer(len);const dataView=new DataView(buffer);tr.b.Base64.DecodeToTypedArray(event.args.buckets,dataView);const decoded=new Uint32Array(buffer);const sum=decoded[1]+decoded[2]*0x100000000;const bins=[];let position=4;while(position<=decoded.length-4){const min=decoded[position++];const max=decoded[position++]+decoded[position++]*0x100000000;const count=decoded[position++];const processes=new tr.v.d.Breakdown();processes.set(processName,count);const events=new tr.v.d.RelatedEventSet([event]);bins.push({min,max,count,processes,events});}
+return{sum,bins};}
+function mergeBins_(x,y){x.sum+=y.sum;const allBins=[...x.bins,...y.bins];allBins.sort((a,b)=>a.min-b.min);x.bins=[];let last=undefined;for(const bin of allBins){if(last!==undefined&&bin.min===last.min){if(last.max!==bin.max)throw new Error('Incompatible bins');if(bin.count===0)continue;last.count+=bin.count;for(const event of bin.events){last.events.add(event);}
+last.processes.addDiagnostic(bin.processes);}else{if(last!==undefined&&bin.min<last.max){throw new Error('Incompatible bins');}
+x.bins.push(bin);last=bin;}}}
+function subtractBins_(x,y){x.sum-=y.sum;let p1=0;let p2=0;while(p2<y.bins.length){while(p1<x.bins.length&&x.bins[p1].min!==y.bins[p2].min){p1++;}
+if(p1===x.bins.length)throw new Error('Cannot subtract');if(x.bins[p1].max!==y.bins[p2].max){throw new Error('Incompatible bins');}
+if(x.bins[p1].count<y.bins[p2].count){throw new Error('Cannot subtract');}
+x.bins[p1].count-=y.bins[p2].count;for(const event of y.bins[p2].events){x.bins[p1].events.add(event);}
+const processName=tr.b.getOnlyElement(x.bins[p1].processes)[0];x.bins[p1].processes.set(processName,x.bins[p1].count);p2++;}}
+function getHistogramUnit_(name){return tr.b.Unit.byName.unitlessNumber_smallerIsBetter;}
+function getHistogramBoundaries_(name){if(name.startsWith('Event.Latency.Scroll')){return tr.v.HistogramBinBoundaries.createExponential(1e3,1e5,50);}
+if(name.startsWith('Graphics.Smoothness.Throughput')){return tr.v.HistogramBinBoundaries.createLinear(0,100,101);}
+return tr.v.HistogramBinBoundaries.createExponential(1e-3,1e3,50);}
+function umaMetric(histograms,model){const histogramValues=new Map();const nameCounts=new Map();for(const process of model.getAllProcesses()){const histogramEvents=new Map();for(const event of process.instantEvents){if(event.title!=='UMAHistogramSamples')continue;const name=event.args.name;const events=histogramEvents.get(name)||[];if(!histogramEvents.has(name))histogramEvents.set(name,events);events.push(event);}
+let processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(process.name);nameCounts.set(processName,(nameCounts.get(processName)||0)+1);processName=`${processName}_${nameCounts.get(processName)}`;for(const[name,events]of histogramEvents){const values=histogramValues.get(name)||{sum:0,bins:[]};if(!histogramValues.has(name))histogramValues.set(name,values);const endValues=parseBuckets_(events[events.length-1],processName);if(events.length===1){mergeBins_(values,endValues);}else if(events.length===2){subtractBins_(endValues,parseBuckets_(events[0],processName));mergeBins_(values,endValues);}else{throw new Error('There should be at most two snapshots of an UMA '+'histogram in each process');}}}
+for(const[name,values]of histogramValues){const histogram=new tr.v.Histogram(name,getHistogramUnit_(name),getHistogramBoundaries_(name));let sumOfMiddles=0;let sumOfBinLengths=0;for(const bin of values.bins){sumOfMiddles+=bin.count*(bin.min+bin.max)/2;sumOfBinLengths+=bin.count*(bin.max-bin.min);}
+const shift=(values.sum-sumOfMiddles)/sumOfBinLengths;if(Math.abs(shift)>0.5)throw new Error('Samples sum is wrong');for(const bin of values.bins){if(bin.count===0)continue;const shiftedValue=(bin.min+bin.max)/2+shift*(bin.max-bin.min);for(const[processName,count]of bin.processes){bin.processes.set(processName,shiftedValue*count/bin.count);}
+for(let i=0;i<bin.count;i++){histogram.addSample(shiftedValue,{processes:bin.processes,events:bin.events});}}
+histograms.addHistogram(histogram);}}
+tr.metrics.MetricRegistry.register(umaMetric,{requiredCategories:['benchmark'],});return{umaMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(4,200,100);function computeExecuteMetrics(histograms,model){const cpuTotalExecution=new tr.v.Histogram('v8_execution_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalExecution.description='cpu total time spent in script execution';const wallTotalExecution=new tr.v.Histogram('v8_execution_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalExecution.description='wall total time spent in script execution';const cpuSelfExecution=new tr.v.Histogram('v8_execution_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfExecution.description='cpu self time spent in script execution';const wallSelfExecution=new tr.v.Histogram('v8_execution_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfExecution.description='wall self time spent in script execution';for(const e of model.findTopmostSlicesNamed('V8.Execute')){cpuTotalExecution.addSample(e.cpuDuration);wallTotalExecution.addSample(e.duration);cpuSelfExecution.addSample(e.cpuSelfTime);wallSelfExecution.addSample(e.selfTime);}
histograms.addHistogram(cpuTotalExecution);histograms.addHistogram(wallTotalExecution);histograms.addHistogram(cpuSelfExecution);histograms.addHistogram(wallSelfExecution);}
function computeParseLazyMetrics(histograms,model){const cpuSelfParseLazy=new tr.v.Histogram('v8_parse_lazy_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfParseLazy.description='cpu self time spent performing lazy parsing';const wallSelfParseLazy=new tr.v.Histogram('v8_parse_lazy_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfParseLazy.description='wall self time spent performing lazy parsing';for(const e of model.findTopmostSlicesNamed('V8.ParseLazyMicroSeconds')){cpuSelfParseLazy.addSample(e.cpuSelfTime);wallSelfParseLazy.addSample(e.selfTime);}
for(const e of model.findTopmostSlicesNamed('V8.ParseLazy')){cpuSelfParseLazy.addSample(e.cpuSelfTime);wallSelfParseLazy.addSample(e.selfTime);}
@@ -8770,30 +9205,35 @@ addHistogramsForRuntimeGroup(runtimeGroup,{durationNames,durationBreakdown,count
for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addHistogramsForRuntimeGroup(runtimeGroup);}
const blinkGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;if(blinkGroupCollection.totalTime>0){blinkGroupCollection.runtimeGroups.forEach(addDetailedHistogramsForRuntimeGroup);}}
function runtimeStatsMetric(histograms,model){const interactiveTime=computeInteractiveTime_(model);const domContentLoadedTime=computeDomContentLoadedTime_(model);const endTime=Math.max(interactiveTime,domContentLoadedTime);const slices=[...model.getDescendantEvents()].filter(event=>event instanceof tr.e.v8.V8ThreadSlice&&event.start<=endTime);computeRuntimeStats(histograms,slices);}
-function addDurationHistogram(railStageName,runtimeGroupName,sampleValue,histograms,durationRelatedHistsByGroupName){const durationHistogram=histograms.createHistogram(`${railStageName}_${runtimeGroupName}:duration`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,convertMicroToMilli_(sampleValue),{binBoundaries:DURATION_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});if(durationRelatedHistsByGroupName.get(runtimeGroupName)===undefined){const durationHistogramMap=new tr.v.d.RelatedHistogramMap();durationHistogramMap.set(railStageName,durationHistogram);durationRelatedHistsByGroupName.set(runtimeGroupName,durationHistogramMap);}else{durationRelatedHistsByGroupName.get(runtimeGroupName).set(railStageName,durationHistogram);}}
-function addCountHistogram(railStageName,runtimeGroupName,sampleValue,histograms,countRelatedHistsByGroupName){const countHistogram=histograms.createHistogram(`${railStageName}_${runtimeGroupName}:count`,tr.b.Unit.byName.count_smallerIsBetter,sampleValue,{binBoundaries:COUNT_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});if(countRelatedHistsByGroupName.get(runtimeGroupName)===undefined){const countHistogramMap=new tr.v.d.RelatedHistogramMap();countHistogramMap.set(railStageName,countHistogram);countRelatedHistsByGroupName.set(runtimeGroupName,countHistogramMap);}else{countRelatedHistsByGroupName.get(runtimeGroupName).set(railStageName,countHistogram);}}
-function addTotalDurationHistogram(histogramName,time,histograms,durationRelatedHistsByGroupName){const durationHistogram=histograms.createHistogram(`${histogramName}:duration`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,convertMicroToMilli_(time),{binBoundaries:DURATION_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});const durationRelatedHistogram=durationRelatedHistsByGroupName.get(histogramName);if(durationRelatedHistogram!==undefined){durationHistogram.diagnostics.set('RAIL stages',durationRelatedHistogram);}}
-function addTotalCountHistogram(histogramName,count,histograms,countRelatedHistsByGroupName){const countHistogram=histograms.createHistogram(`${histogramName}:count`,tr.b.Unit.byName.count_smallerIsBetter,count,{binBoundaries:COUNT_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});const countRelatedHistogram=countRelatedHistsByGroupName.get(histogramName);if(countRelatedHistogram!==undefined){countHistogram.diagnostics.set('RAIL stages',countRelatedHistogram);}}
-function computeRuntimeStatsBucketOnUE(histograms,slices,v8SlicesBucketOnUEMap){const durationRelatedHistsByGroupName=new Map();const countRelatedHistsByGroupName=new Map();for(const[name,slicesUE]of v8SlicesBucketOnUEMap){const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(slicesUE);let overallV8Time=runtimeGroupCollection.totalTime;let overallV8Count=runtimeGroupCollection.totalCount;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addDurationHistogram(name,runtimeGroup.name,runtimeGroup.time,histograms,durationRelatedHistsByGroupName);if(runtimeGroup.name==='Blink C++'){overallV8Time-=runtimeGroup.time;}
-addCountHistogram(name,runtimeGroup.name,runtimeGroup.count,histograms,countRelatedHistsByGroupName);if(runtimeGroup.name==='Blink C++'){overallV8Count-=runtimeGroup.count;}}
-if(runtimeGroupCollection.blinkRCSGroupCollection.totalTime>0){const blinkRCSGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;for(const group of blinkRCSGroupCollection.runtimeGroups){addDurationHistogram(name,group.name,group.time,histograms,durationRelatedHistsByGroupName);addCountHistogram(name,group.name,group.count,histograms,countRelatedHistsByGroupName);}}
-addDurationHistogram(name,'V8-Only',overallV8Time,histograms,durationRelatedHistsByGroupName);addCountHistogram(name,'V8-Only',overallV8Count,histograms,countRelatedHistsByGroupName);}
-const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(slices);let overallV8Time=runtimeGroupCollection.totalTime;let overallV8Count=runtimeGroupCollection.totalCount;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addTotalDurationHistogram(runtimeGroup.name,runtimeGroup.time,histograms,durationRelatedHistsByGroupName);if(runtimeGroup.name==='Blink C++'){overallV8Time-=runtimeGroup.time;}
-addTotalCountHistogram(runtimeGroup.name,runtimeGroup.count,histograms,countRelatedHistsByGroupName);if(runtimeGroup.name==='Blink C++'){overallV8Count-=runtimeGroup.count;}}
-if(runtimeGroupCollection.blinkRCSGroupCollection.totalTime>0){const blinkRCSGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;for(const group of blinkRCSGroupCollection.runtimeGroups){addTotalDurationHistogram(group.name,group.time,histograms,durationRelatedHistsByGroupName);addTotalCountHistogram(group.name,group.count,histograms,countRelatedHistsByGroupName);}}
-addTotalDurationHistogram('V8-Only',overallV8Time,histograms,durationRelatedHistsByGroupName);addTotalCountHistogram('V8-Only',overallV8Count,histograms,countRelatedHistsByGroupName);}
+function addDurationHistogram(railStageName,runtimeGroupName,sampleValue,histograms,durationNamesByGroupName){const histName=`${railStageName}_${runtimeGroupName}:duration`;histograms.createHistogram(histName,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,convertMicroToMilli_(sampleValue),{binBoundaries:DURATION_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});let relatedNames=durationNamesByGroupName.get(runtimeGroupName);if(!relatedNames){relatedNames=new tr.v.d.RelatedNameMap();durationNamesByGroupName.set(runtimeGroupName,relatedNames);}
+relatedNames.set(railStageName,histName);}
+function addCountHistogram(railStageName,runtimeGroupName,sampleValue,histograms,countNamesByGroupName){const histName=`${railStageName}_${runtimeGroupName}:count`;histograms.createHistogram(histName,tr.b.Unit.byName.count_smallerIsBetter,sampleValue,{binBoundaries:COUNT_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});let relatedNames=countNamesByGroupName.get(runtimeGroupName);if(!relatedNames){relatedNames=new tr.v.d.RelatedNameMap();countNamesByGroupName.set(runtimeGroupName,relatedNames);}
+relatedNames.set(railStageName,histName);}
+function addTotalDurationHistogram(histogramName,time,histograms,relatedNames){const value=convertMicroToMilli_(time);const breakdown=new tr.v.d.Breakdown();if(relatedNames){for(const[cat,histName]of relatedNames){breakdown.set(cat,histograms.getHistogramNamed(histName).average);}}
+histograms.createHistogram(`${histogramName}:duration`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,{value,diagnostics:{'RAIL stages':breakdown}},{binBoundaries:DURATION_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,diagnostics:{'RAIL stages':relatedNames},});}
+function addTotalCountHistogram(histogramName,value,histograms,relatedNames){const breakdown=new tr.v.d.Breakdown();if(relatedNames){for(const[cat,histName]of relatedNames){breakdown.set(cat,histograms.getHistogramNamed(histName).average);}}
+histograms.createHistogram(`${histogramName}:count`,tr.b.Unit.byName.count_smallerIsBetter,{value,diagnostics:{'RAIL stages':breakdown}},{binBoundaries:COUNT_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,diagnostics:{'RAIL stages':relatedNames},});}
+function computeRuntimeStatsBucketOnUE(histograms,slices,v8SlicesBucketOnUEMap){const durationNamesByGroupName=new Map();const countNamesByGroupName=new Map();for(const[name,slicesUE]of v8SlicesBucketOnUEMap){const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(slicesUE);let overallV8Time=runtimeGroupCollection.totalTime;let overallV8Count=runtimeGroupCollection.totalCount;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addDurationHistogram(name,runtimeGroup.name,runtimeGroup.time,histograms,durationNamesByGroupName);if(runtimeGroup.name==='Blink C++'){overallV8Time-=runtimeGroup.time;}
+addCountHistogram(name,runtimeGroup.name,runtimeGroup.count,histograms,countNamesByGroupName);if(runtimeGroup.name==='Blink C++'){overallV8Count-=runtimeGroup.count;}}
+if(runtimeGroupCollection.blinkRCSGroupCollection.totalTime>0){const blinkRCSGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;for(const group of blinkRCSGroupCollection.runtimeGroups){addDurationHistogram(name,group.name,group.time,histograms,durationNamesByGroupName);addCountHistogram(name,group.name,group.count,histograms,countNamesByGroupName);}}
+addDurationHistogram(name,'V8-Only',overallV8Time,histograms,durationNamesByGroupName);addCountHistogram(name,'V8-Only',overallV8Count,histograms,countNamesByGroupName);}
+const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(slices);let overallV8Time=runtimeGroupCollection.totalTime;let overallV8Count=runtimeGroupCollection.totalCount;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addTotalDurationHistogram(runtimeGroup.name,runtimeGroup.time,histograms,durationNamesByGroupName.get(runtimeGroup.name));if(runtimeGroup.name==='Blink C++'){overallV8Time-=runtimeGroup.time;}
+addTotalCountHistogram(runtimeGroup.name,runtimeGroup.count,histograms,countNamesByGroupName.get(runtimeGroup.name));if(runtimeGroup.name==='Blink C++'){overallV8Count-=runtimeGroup.count;}}
+if(runtimeGroupCollection.blinkRCSGroupCollection.totalTime>0){const blinkRCSGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;for(const group of blinkRCSGroupCollection.runtimeGroups){addTotalDurationHistogram(group.name,group.time,histograms,durationNamesByGroupName.get(group.name));addTotalCountHistogram(group.name,group.count,histograms,countNamesByGroupName.get(group.name));}}
+addTotalDurationHistogram('V8-Only',overallV8Time,histograms,durationNamesByGroupName.get('V8-Only'));addTotalCountHistogram('V8-Only',overallV8Count,histograms,countNamesByGroupName.get('V8-Only'));}
function runtimeStatsTotalMetric(histograms,model){const v8ThreadSlices=[...model.getDescendantEvents()].filter(event=>event instanceof tr.e.v8.V8ThreadSlice).sort((e1,e2)=>e1.start-e2.start);const v8SlicesBucketOnUEMap=new Map();for(const expectation of model.userModel.expectations){if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
const slices=expectation.range.filterArray(v8ThreadSlices,event=>event.start);if(slices.length===0)continue;const lastSlice=slices[slices.length-1];if(!expectation.range.intersectsRangeExclusive(lastSlice.range)){slices.pop();}
if(v8SlicesBucketOnUEMap.get(expectation.stageTitle)===undefined){v8SlicesBucketOnUEMap.set(expectation.stageTitle,slices);}else{const totalSlices=v8SlicesBucketOnUEMap.get(expectation.stageTitle).concat(slices);v8SlicesBucketOnUEMap.set(expectation.stageTitle,totalSlices);}}
computeRuntimeStatsBucketOnUE(histograms,v8ThreadSlices,v8SlicesBucketOnUEMap);}
tr.metrics.MetricRegistry.register(runtimeStatsTotalMetric);tr.metrics.MetricRegistry.register(runtimeStatsMetric);return{runtimeStatsMetric,runtimeStatsTotalMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){function v8AndMemoryMetrics(histograms,model){tr.metrics.v8.executionMetric(histograms,model);tr.metrics.v8.gcMetric(histograms,model);tr.metrics.sh.memoryMetric(histograms,model,{rangeOfInterest:tr.metrics.v8.utils.rangeForMemoryDumps(model)});}
-tr.metrics.MetricRegistry.register(v8AndMemoryMetrics);return{v8AndMemoryMetrics,};});'use strict';tr.exportTo('tr.metrics.vr',function(){function createHistograms(histograms,name,options,hasCpuTime){const createdHistograms={wall:histograms.createHistogram(name+'_wall',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options)};if(hasCpuTime){createdHistograms.cpu=histograms.createHistogram(name+'_cpu',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options);}
+tr.metrics.MetricRegistry.register(v8AndMemoryMetrics);return{v8AndMemoryMetrics,};});'use strict';tr.exportTo('tr.metrics.vr',function(){const VR_GL_THREAD_NAME='VrShellGL';function createHistograms(histograms,name,options,hasCpuTime){const createdHistograms={wall:histograms.createHistogram(name+'_wall',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options)};if(hasCpuTime){createdHistograms.cpu=histograms.createHistogram(name+'_cpu',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options);}
return createdHistograms;}
-function frameCycleDurationMetric(histograms,model,opt_options){const histogramsByEventTitle=new Map();histogramsByEventTitle.set('Vr.DrawFrame',createHistograms(histograms,'draw_frame',{description:'Duration to render one frame'},true));histogramsByEventTitle.set('Vr.AcquireGvrFrame',createHistograms(histograms,'acquire_frame',{description:'Duration acquire a frame from GVR'},true));histogramsByEventTitle.set('Vr.ProcessControllerInput',createHistograms(histograms,'update_controller',{description:'Duration to query input from the controller'},true));histogramsByEventTitle.set('Vr.ProcessControllerInputForWebXr',createHistograms(histograms,'update_controller_webxr',{description:'Duration to query input from the controller '+'for WebXR'},true));histogramsByEventTitle.set('Vr.SubmitFrameNow',createHistograms(histograms,'submit_frame',{description:'Duration to submit a frame to GVR'},true));histogramsByEventTitle.set('Vr.PostSubmitDrawOnGpu',createHistograms(histograms,'post_submit_draw_on_gpu',{description:'Duration to draw a frame on GPU post submit to '+'GVR. Note this duration may include time spent on '+'reprojection'},false));histogramsByEventTitle.set('VrShellGl::DrawFrame',histogramsByEventTitle.get('Vr.DrawFrame'));histogramsByEventTitle.set('VrShellGl::AcquireFrame',histogramsByEventTitle.get('Vr.AcquireGvrFrame'));histogramsByEventTitle.set('VrShellGl::UpdateController',histogramsByEventTitle.get('Vr.ProcessControllerInput'));histogramsByEventTitle.set('VrShellGl::DrawFrameSubmitNow',histogramsByEventTitle.get('Vr.SubmitFrameNow'));histogramsByEventTitle.set('VrShellGl::PostSubmitDrawOnGpu',histogramsByEventTitle.get('Vr.PostSubmitDrawOnGpu'));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateAnimationsAndOpacity',createHistograms(histograms,'update_animations_and_opacity',{description:'Duration to apply animation and opacity changes'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateBindings',createHistograms(histograms,'update_bindings',{description:'Duration to push binding values'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateLayout',createHistograms(histograms,'update_layout',{description:'Duration to compute element sizes, layout and textures'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateWorldSpaceTransform',createHistograms(histograms,'update_world_space_transforms',{description:'Duration to calculate element transforms in world space'},true));histogramsByEventTitle.set('UiRenderer::DrawUiView',createHistograms(histograms,'draw_ui',{description:'Duration to draw the UI'},true));histogramsByEventTitle.set('UiElementRenderer::DrawTexturedQuad',createHistograms(histograms,'draw_textured_quad',{description:'Duration to draw a textured element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientQuad',createHistograms(histograms,'draw_gradient_quad',{description:'Duration to draw a gradient element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientGridQuad',createHistograms(histograms,'draw_gradient_grid_quad',{description:'Duration to draw a gradient grid element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawController',createHistograms(histograms,'draw_controller',{description:'Duration to draw the controller'},true));histogramsByEventTitle.set('UiElementRenderer::DrawLaser',createHistograms(histograms,'draw_laser',{description:'Duration to draw the laser'},true));histogramsByEventTitle.set('UiElementRenderer::DrawReticle',createHistograms(histograms,'draw_reticle',{description:'Duration to draw the reticle'},true));histogramsByEventTitle.set('UiElementRenderer::DrawShadow',createHistograms(histograms,'draw_shadow',{description:'Duration to draw a shadow element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawStars',createHistograms(histograms,'draw_stars',{description:'Duration to draw the stars'},true));histogramsByEventTitle.set('UiElementRenderer::DrawBackground',createHistograms(histograms,'draw_background',{description:'Duration to draw the textured background'},true));histogramsByEventTitle.set('UiElementRenderer::DrawKeyboard',createHistograms(histograms,'draw_keyboard',{description:'Duration to draw the keyboard'},true));const drawUiSubSlicesMap=new Map();const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let rangeOfInterest=model.bounds;const userExpectationsOfInterest=[tr.model.um.AnimationExpectation];if(opt_options&&opt_options.rangeOfInterest){rangeOfInterest=opt_options.rangeOfInterest;userExpectationsOfInterest.push(tr.model.um.ResponseExpectation);}
+function frameCycleDurationMetric(histograms,model,opt_options){const histogramsByEventTitle=new Map();const expectationEvents=tr.importer.VR_EXPECTATION_EVENTS;for(const eventName in expectationEvents){const extraInfo=expectationEvents[eventName];histogramsByEventTitle.set(eventName,createHistograms(histograms,extraInfo.histogramName,{description:extraInfo.description},extraInfo.hasCpuTime));}
+histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateAnimationsAndOpacity',createHistograms(histograms,'update_animations_and_opacity',{description:'Duration to apply animation and opacity changes'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateBindings',createHistograms(histograms,'update_bindings',{description:'Duration to push binding values'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateLayout',createHistograms(histograms,'update_layout',{description:'Duration to compute element sizes, layout and textures'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateWorldSpaceTransform',createHistograms(histograms,'update_world_space_transforms',{description:'Duration to calculate element transforms in world space'},true));histogramsByEventTitle.set('UiRenderer::DrawUiView',createHistograms(histograms,'draw_ui',{description:'Duration to draw the UI'},true));histogramsByEventTitle.set('UiElementRenderer::DrawTexturedQuad',createHistograms(histograms,'draw_textured_quad',{description:'Duration to draw a textured element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientQuad',createHistograms(histograms,'draw_gradient_quad',{description:'Duration to draw a gradient element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientGridQuad',createHistograms(histograms,'draw_gradient_grid_quad',{description:'Duration to draw a gradient grid element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawController',createHistograms(histograms,'draw_controller',{description:'Duration to draw the controller'},true));histogramsByEventTitle.set('UiElementRenderer::DrawLaser',createHistograms(histograms,'draw_laser',{description:'Duration to draw the laser'},true));histogramsByEventTitle.set('UiElementRenderer::DrawReticle',createHistograms(histograms,'draw_reticle',{description:'Duration to draw the reticle'},true));histogramsByEventTitle.set('UiElementRenderer::DrawShadow',createHistograms(histograms,'draw_shadow',{description:'Duration to draw a shadow element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawStars',createHistograms(histograms,'draw_stars',{description:'Duration to draw the stars'},true));histogramsByEventTitle.set('UiElementRenderer::DrawBackground',createHistograms(histograms,'draw_background',{description:'Duration to draw the textured background'},true));histogramsByEventTitle.set('UiElementRenderer::DrawKeyboard',createHistograms(histograms,'draw_keyboard',{description:'Duration to draw the keyboard'},true));const drawUiSubSlicesMap=new Map();const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let rangeOfInterest=model.bounds;const userExpectationsOfInterest=[tr.model.um.AnimationExpectation];if(opt_options&&opt_options.rangeOfInterest){rangeOfInterest=opt_options.rangeOfInterest;userExpectationsOfInterest.push(tr.model.um.ResponseExpectation);}
for(const ue of model.userModel.expectations){if(ue.initiatorType!==tr.model.um.INITIATOR_TYPE.VR){continue;}
if(!userExpectationsOfInterest.some(function(ueOfInterest){return ue instanceof ueOfInterest;})){continue;}
if(!rangeOfInterest.intersectsExplicitRangeInclusive(ue.start,ue.end)){continue;}
-for(const helper of chromeHelper.browserHelpers){const glThreads=helper.process.findAllThreadsMatching(thread=>!thread.name);for(const glThread of glThreads){for(const event of glThread.getDescendantEvents()){if(!(histogramsByEventTitle.has(event.title))){continue;}
+for(const helper of chromeHelper.browserHelpers){const glThreads=helper.process.findAllThreadsNamed(VR_GL_THREAD_NAME);for(const glThread of glThreads){for(const event of glThread.getDescendantEvents()){if(!(histogramsByEventTitle.has(event.title))){continue;}
if(event.start<ue.start||event.end>ue.end){continue;}
if(event.start<rangeOfInterest.min||event.end>rangeOfInterest.max){continue;}
if(event.parentSlice&&event.parentSlice.title==='UiRenderer::DrawUiView'){const guid=event.parentSlice.guid;if(!drawUiSubSlicesMap.has(guid)){drawUiSubSlicesMap.set(guid,[]);}
@@ -8811,7 +9251,18 @@ WEBVR_COUNTERS.get(counter.id).samples[series.name].push(sample.value);}}}}
if(!('value'in WEBVR_COUNTERS.get('gpu.WebVR FPS').samples)){WEBVR_COUNTERS.get('gpu.WebVR FPS').samples.value=[0];}
for(const[key,value]of WEBVR_COUNTERS){for(const[seriesName,samples]of Object.entries(value.samples)){let histogramName=value.name;if(seriesName!=='value'){histogramName=`${histogramName}_${seriesName}`;}
histograms.createHistogram(histogramName,value.unit,samples,value.options);}}}
-tr.metrics.MetricRegistry.register(webvrMetric,{supportsRangeOfInterest:true,});return{webvrMetric,};});'use strict';tr.exportTo('tr.metrics.webrtc',function(){const DISPLAY_HERTZ=60.0;const VSYNC_DURATION_US=1e6/DISPLAY_HERTZ;const SEVERITY=3;const FROZEN_FRAME_VSYNC_COUNT_THRESHOLD=6;const WEB_MEDIA_PLAYER_UPDATE_TITLE='UpdateCurrentFrame';const IDEAL_RENDER_INSTANT_NAME='Ideal Render Instant';const ACTUAL_RENDER_BEGIN_NAME='Actual Render Begin';const ACTUAL_RENDER_END_NAME='Actual Render End';const STREAM_ID_NAME='Serial';const REQUIRED_EVENT_ARGS_NAMES=[IDEAL_RENDER_INSTANT_NAME,ACTUAL_RENDER_BEGIN_NAME,ACTUAL_RENDER_END_NAME,STREAM_ID_NAME];const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;const count_smallerIsBetter=tr.b.Unit.byName.count_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_biggerIsBetter=tr.b.Unit.byName.unitlessNumber_biggerIsBetter;function isValidEvent(event){if(event.title!==WEB_MEDIA_PLAYER_UPDATE_TITLE||!event.args){return false;}
+tr.metrics.MetricRegistry.register(webvrMetric,{supportsRangeOfInterest:true,});return{webvrMetric,};});'use strict';tr.exportTo('tr.metrics.vr',function(){function webxrMetric(histograms,model,opt_options){const DEFAULT_BIN_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(20,120,25);const counterHistogramsByTitle=new Map();counterHistogramsByTitle.set('gpu.WebXR FPS',histograms.createHistogram('webxr_fps',tr.b.Unit.byName.count_biggerIsBetter,[],{description:'WebXR frames per second',binBoundaries:DEFAULT_BIN_BOUNDARIES,}));const instantHistogramsByTitle=new Map();const expectationEvents=tr.importer.WEBXR_INSTANT_EVENTS;for(const[eventName,eventData]of Object.entries(expectationEvents)){const argsToHistograms={};for(const[argName,argData]of Object.entries(eventData)){argsToHistograms[argName]=histograms.createHistogram(argData.histogramName,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:argData.description,binBoundaries:DEFAULT_BIN_BOUNDARIES,});}
+instantHistogramsByTitle.set(eventName,argsToHistograms);}
+const rangeOfInterestEnabled=opt_options&&opt_options.rangeOfInterest;const rangeOfInterest=(rangeOfInterestEnabled?opt_options.rangeOfInterest:tr.b.math.Range.fromExplicitRange(-Infinity,Infinity));for(const ue of model.userModel.expectations){if(!rangeOfInterest.intersectsExplicitRangeInclusive(ue.start,ue.end)){continue;}
+if(ue.initiatorType!==tr.model.um.INITIATOR_TYPE.VR)continue;if(!rangeOfInterestEnabled){if(!(ue instanceof tr.model.um.AnimationExpectation))continue;}else{if(!(ue instanceof tr.model.um.AnimationExpectation||ue instanceof tr.model.um.ResponseExpectation))continue;}
+for(const counter of model.getAllCounters()){if(!(counterHistogramsByTitle.has(counter.id)))continue;for(const series of counter.series){for(const sample of series.samples){if(sample.timestamp<ue.start||sample.timestamp>=ue.end){continue;}
+if(!rangeOfInterest.intersectsExplicitRangeInclusive(sample.timestamp,sample.timestamp)){continue;}
+counterHistogramsByTitle.get(counter.id).addSample(sample.value);}}}
+for(const event of ue.associatedEvents.asSet()){if(!(instantHistogramsByTitle.has(event.title))){continue;}
+if(!rangeOfInterest.intersectsExplicitRangeInclusive(event.start,event.start)){continue;}
+const eventHistograms=instantHistogramsByTitle.get(event.title);for(const[key,value]of Object.entries(event.args)){if(key in eventHistograms){eventHistograms[key].addSample(value,{event:new tr.v.d.RelatedEventSet(event)});}}}}
+if(counterHistogramsByTitle.get('gpu.WebXR FPS').numValues===0){counterHistogramsByTitle.get('gpu.WebXR FPS').addSample(0);}}
+tr.metrics.MetricRegistry.register(webxrMetric,{supportsRangeOfInterest:true,});return{webxrMetric,};});'use strict';tr.exportTo('tr.metrics.webrtc',function(){const DISPLAY_HERTZ=60.0;const VSYNC_DURATION_US=1e6/DISPLAY_HERTZ;const SEVERITY=3;const FROZEN_FRAME_VSYNC_COUNT_THRESHOLD=6;const WEB_MEDIA_PLAYER_UPDATE_TITLE='UpdateCurrentFrame';const IDEAL_RENDER_INSTANT_NAME='Ideal Render Instant';const ACTUAL_RENDER_BEGIN_NAME='Actual Render Begin';const ACTUAL_RENDER_END_NAME='Actual Render End';const STREAM_ID_NAME='Serial';const REQUIRED_EVENT_ARGS_NAMES=[IDEAL_RENDER_INSTANT_NAME,ACTUAL_RENDER_BEGIN_NAME,ACTUAL_RENDER_END_NAME,STREAM_ID_NAME];const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;const count_smallerIsBetter=tr.b.Unit.byName.count_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_biggerIsBetter=tr.b.Unit.byName.unitlessNumber_biggerIsBetter;function isValidEvent(event){if(event.title!==WEB_MEDIA_PLAYER_UPDATE_TITLE||!event.args){return false;}
for(const parameter of REQUIRED_EVENT_ARGS_NAMES){if(!(parameter in event.args)){return false;}}
return true;}
function webrtcRenderingMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let webMediaPlayerMSEvents=[];for(const rendererPid in modelHelper.rendererHelpers){const rendererHelper=modelHelper.rendererHelpers[rendererPid];const compositorThread=rendererHelper.compositorThread;if(compositorThread!==undefined){webMediaPlayerMSEvents=webMediaPlayerMSEvents.concat(compositorThread.sliceGroup.slices.filter(isValidEvent));}}
@@ -9095,18 +9546,19 @@ this.textHeightPx_*(this.data_.length-index)+')').attr('x',(d,index)=>this.xScal
this.autoDataRange_.reset();for(const datum of this.data_){this.autoDataRange_.addValue(datum.percentile_0);this.autoDataRange_.addValue(datum.percentile_100);}},updateScales_(){super.updateScales_();this.xScale_.domain([0,this.data_.length]);},get xAxisTickOffset(){return 0.5;},updateDataRange_(){if(this.overrideDataRange_!==undefined)return;this.autoDataRange_.reset();for(const datum of this.data_){this.autoDataRange_.addValue(datum.percentile_0);this.autoDataRange_.addValue(datum.percentile_100);}},updateXAxis_(xAxis){xAxis.selectAll('*').remove();if(this.hideXAxis)return;tr.ui.b.NameColumnChart.prototype.updateXAxis_.call(this,xAxis);const baseline=xAxis.selectAll('path').data([this]);baseline.enter().append('line').attr('stroke','black').attr('x1',this.xScale_(0)).attr('x2',this.xScale_(this.data_.length)).attr('y1',this.graphHeight).attr('y2',this.graphHeight);baseline.exit().remove();},updateDataContents_(dataSel){dataSel.selectAll('*').remove();const boxesSel=dataSel.selectAll('path');for(let index=0;index<this.data_.length;++index){const datum=this.data_[index];const color=datum.color||'black';let sel=boxesSel.data([datum]);sel.enter().append('rect').attr('fill',color).attr('x',this.xScale_(index+0.2)).attr('width',this.xScale_(index+0.8)-this.xScale_(index+0.2)).attr('y',this.yScale_(datum.percentile_75)).attr('height',this.yScale_(datum.percentile_25)-
this.yScale_(datum.percentile_75));sel.exit().remove();sel=boxesSel.data([datum]);sel.enter().append('line').attr('stroke',color).attr('x1',this.xScale_(index)).attr('x2',this.xScale_(index+1)).attr('y1',this.yScale_(datum.percentile_50)).attr('y2',this.yScale_(datum.percentile_50));sel.exit().remove();sel=boxesSel.data([datum]);sel.enter().append('line').attr('stroke',color).attr('x1',this.xScale_(index+0.4)).attr('x2',this.xScale_(index+0.6)).attr('y1',this.yScale_(datum.percentile_0)).attr('y2',this.yScale_(datum.percentile_0));sel.exit().remove();sel=boxesSel.data([datum]);sel.enter().append('line').attr('stroke',color).attr('x1',this.xScale_(index+0.4)).attr('x2',this.xScale_(index+0.6)).attr('y1',this.yScale_(datum.percentile_100)).attr('y2',this.yScale_(datum.percentile_100));sel.exit().remove();sel=boxesSel.data([datum]);sel.enter().append('line').attr('stroke',color).attr('x1',this.xScale_(index+0.5)).attr('x2',this.xScale_(index+0.5)).attr('y1',this.yScale_(datum.percentile_100)).attr('y2',this.yScale_(datum.percentile_0));sel.exit().remove();}}};return{BoxChart,};});'use strict';tr.exportTo('tr.ui.b',function(){const BarChart=tr.ui.b.define('bar-chart',tr.ui.b.ColumnChart);BarChart.prototype={__proto__:tr.ui.b.ColumnChart.prototype,decorate(){super.decorate();this.verticalScale_=undefined;this.horizontalScale_=undefined;this.isWaterfall_=false;},updateScales_(){super.updateScales_();this.yScale_.range([this.graphWidth,0]);this.xScale_.range([0,this.graphHeight]);this.verticalScale_=this.isYLogScale_?d3.scale.log(10):d3.scale.linear();this.verticalScale_.domain(this.xScale_.domain());this.verticalScale_.range([this.graphHeight,0]);this.horizontalScale_=d3.scale.linear();this.horizontalScale_.domain(this.yScale_.domain());this.horizontalScale_.range([0,this.graphWidth]);},set isWaterfall(waterfall){this.isWaterfall_=waterfall;if(waterfall){this.getDataSeries('hide').color='transparent';}
this.updateContents_();},get isWaterfall(){return this.isWaterfall_;},get defaultGraphHeight(){return Math.max(20,10*this.data_.length);},get defaultGraphWidth(){return 100;},get barHeight(){return this.graphHeight/this.data.length;},drawBrush_(brushRectsSel){brushRectsSel.attr('x',0).attr('width',this.graphWidth).attr('y',d=>this.verticalScale_(d.max)).attr('height',d=>this.verticalScale_(d.min)-this.verticalScale_(d.max)).attr('fill','rgb(213, 236, 229)');},getDataPointAtChartPoint_(chartPoint){const flippedPoint={x:this.graphHeight-chartPoint.y,y:this.graphWidth-chartPoint.x};return super.getDataPointAtChartPoint_(flippedPoint);},drawXAxis_(xAxis){xAxis.attr('transform','translate(0,'+this.graphHeight+')').call(d3.svg.axis().scale(this.horizontalScale_).orient('bottom'));},get yAxisWidth(){return this.computeScaleTickWidth_(this.verticalScale_);},drawYAxis_(yAxis){const axisModifier=d3.svg.axis().scale(this.verticalScale_).orient('left');yAxis.call(axisModifier);},drawHoverValueBox_(rect){const rectHoverEvent=new tr.b.Event('rect-mouseenter');rectHoverEvent.rect=rect;this.dispatchEvent(rectHoverEvent);if(!this.enableHoverBox||(this.isWaterfall_&&rect.key==='hide')){return;}
-const seriesKeys=[...this.seriesByKey_.keys()];const chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.selectAll('.hover').remove();let keyWidthPx=0;let keyHeightPx=0;let xWidthPx=0;let xHeightPx=0;let groupWidthPx=0;let groupHeightPx=0;if(seriesKeys.length>1&&!this.isWaterfall_){keyWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.key).width;keyHeightPx=this.textHeightPx_;}
+const seriesKeys=[...this.seriesByKey_.keys()];const chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.selectAll('.hover').remove();let keyWidthPx=0;let keyHeightPx=0;let xWidthPx=0;let xHeightPx=0;let groupWidthPx=0;let groupHeightPx=0;if(seriesKeys.length>1&&!this.isGrouped&&!this.isWaterfall_){keyWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.key).width;keyHeightPx=this.textHeightPx_;}
if(this.data.length>1&&!this.isWaterfall_){xWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,''+rect.datum.x).width;xHeightPx=this.textHeightPx_;}
if(this.isGrouped&&rect.datum.group!==undefined){groupWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.datum.group).width;groupHeightPx=this.textHeightPx_;}
-const valueWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.value).width;const valueHeightPx=this.textHeightPx_;const maxWidthPx=Math.max(keyWidthPx,xWidthPx,groupWidthPx,valueWidthPx)+5;const hoverWidthPx=this.isGrouped?maxWidthPx:Math.min(maxWidthPx,Math.max(50,rect.widthPx));const hoverTopPx=rect.topPx+(rect.heightPx/2);const hoverLeftPx=rect.leftPx+rect.widthPx-hoverWidthPx;chartAreaSel.append('rect').attr('class','hover').attr('fill','white').attr('x',hoverLeftPx).attr('y',hoverTopPx).attr('width',hoverWidthPx).attr('height',keyHeightPx+xHeightPx+
-valueHeightPx+groupHeightPx);if(seriesKeys.length>1&&!this.isWaterfall_){chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx-3).text(rect.key);}
-if(this.data.length>1&&!this.isWaterfall_){chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx+valueHeightPx-3).text(''+rect.datum.x);}
-if(this.isGrouped&&rect.datum.group!==undefined){chartAreaSel.append('text').on('mouseleave',()=>this.clearHoverValueBox_(rect)).attr('class','hover').attr('fill',rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx+xHeightPx+groupHeightPx-3).text(rect.datum.group);}
-chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+xHeightPx+keyHeightPx+
+const valueWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.value).width;const valueHeightPx=this.textHeightPx_;const maxWidthPx=Math.max(keyWidthPx,xWidthPx,groupWidthPx,valueWidthPx)+5;const hoverWidthPx=this.isGrouped?maxWidthPx:Math.min(maxWidthPx,Math.max(50,rect.widthPx));let hoverTopPx=rect.topPx;hoverTopPx=Math.min(hoverTopPx,this.getBoundingClientRect().height-
+valueHeightPx);let hoverLeftPx=rect.leftPx+(rect.widthPx/2);hoverLeftPx=Math.max(hoverLeftPx-hoverWidthPx,-this.margin.left);chartAreaSel.append('rect').attr('class','hover').attr('fill','white').attr('x',hoverLeftPx).attr('y',hoverTopPx).attr('width',hoverWidthPx).attr('height',keyHeightPx+xHeightPx+
+valueHeightPx+groupHeightPx);if(seriesKeys.length>1&&!this.isGrouped&&!this.isWaterfall_){chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color==='transparent'?'#000000':rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx-3).text(rect.key);}
+if(this.data.length>1&&!this.isWaterfall_){chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color==='transparent'?'#000000':rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx+valueHeightPx-3).text(''+rect.datum.x);}
+if(this.isGrouped&&rect.datum.group!==undefined){chartAreaSel.append('text').on('mouseleave',()=>this.clearHoverValueBox_(rect)).attr('class','hover').attr('fill',rect.color==='transparent'?'#000000':rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx+xHeightPx+groupHeightPx-3).text(rect.datum.group);}
+chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color==='transparent'?'#000000':rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+xHeightPx+keyHeightPx+
groupHeightPx+valueHeightPx-3).text(rect.value);},flipRect_(rect){return{datum:rect.datum,index:rect.index,key:rect.key,value:rect.value,color:rect.color,topPx:this.graphHeight-rect.leftPx-rect.widthPx,leftPx:this.graphWidth-rect.topPx-rect.heightPx,widthPx:rect.heightPx,heightPx:rect.widthPx,underflow:rect.underflow,overflow:rect.overflow,};},drawRect_(rect,sel){super.drawRect_(this.flipRect_(rect),sel);},drawUnderflow_(rect,rectsSel){let sel=rectsSel.data([rect]);sel.enter().append('text').text('*').attr('fill',rect.color).attr('x',0).attr('y',this.graphHeight-rect.leftPx+
3+(rect.widthPx/2));sel.exit().remove();sel=rectsSel.data([rect]);sel.enter().append('rect').attr('fill','rgba(0, 0, 0, 0)').attr('x',0).attr('y',this.graphHeight-rect.leftPx-rect.widthPx).attr('width',10).attr('height',rect.widthPx).on('mouseenter',()=>this.drawHoverValueBox_(this.flipRect_(rect))).on('mouseleave',()=>this.clearHoverValueBox_(rect));sel.exit().remove();},drawOverflow_(rect,sel){sel=sel.data([rect]);sel.enter().append('text').text('*').attr('fill',rect.color).attr('x',this.graphWidth).attr('y',this.graphHeight-rect.leftPx+
3+(rect.widthPx/2));sel.exit().remove();}};return{BarChart,};});'use strict';tr.exportTo('tr.ui.b',function(){const NameBarChart=tr.ui.b.define('name-bar-chart',tr.ui.b.BarChart);const Y_AXIS_PADDING=2;NameBarChart.prototype={__proto__:tr.ui.b.BarChart.prototype,getDataPointAtChartPoint_(chartPoint){return{x:tr.ui.b.BarChart.prototype.getDataPointAtChartPoint_.call(this,chartPoint).x,y:parseInt(Math.floor((this.graphHeight-chartPoint.y)/this.barHeight))};},getXForDatum_(datum,index){return index;},get yAxisWidth(){if(this.data.length===0)return 0;return Y_AXIS_PADDING+tr.b.math.Statistics.max(this.data_,d=>tr.ui.b.getSVGTextSize(this,d.x).width);},get defaultGraphHeight(){return(3+this.textHeightPx_)*this.data.length;},updateYAxis_(yAxis){if(tr.ui.b.getSVGTextSize(this,'test').width===0){tr.b.requestAnimationFrame(()=>this.updateYAxis_(yAxis));return;}
-yAxis.selectAll('*').remove();const nameTexts=yAxis.selectAll('text').data(this.data_);nameTexts.enter().append('text').attr('x',d=>-(tr.ui.b.getSVGTextSize(this,d.x).width+Y_AXIS_PADDING)).attr('y',(d,index)=>this.verticalScale_(index)).text(d=>d.x);nameTexts.exit().remove();let previousTop=undefined;for(const text of nameTexts[0]){const bbox=text.getBBox();if((previousTop===undefined)||(previousTop>(bbox.y+bbox.height))){previousTop=bbox.y;}else{text.style.opacity=0;}}}};return{NameBarChart,};});'use strict';tr.exportTo('tr.v.ui',function(){const DIAGNOSTIC_SPAN_BEHAVIOR={created(){this.diagnostic_=undefined;this.name_=undefined;this.histogram_=undefined;},attached(){if(this.diagnostic_)this.updateContents_();},get diagnostic(){return this.diagnostic_;},build(diagnostic,name,histogram){this.diagnostic_=diagnostic;this.name_=name;this.histogram_=histogram;if(this.isAttached)this.updateContents_();},updateContents_(){throw new Error('dom-modules must override updateContents_()');}};return{DIAGNOSTIC_SPAN_BEHAVIOR,};});'use strict';tr.exportTo('tr.v.ui',function(){const DEFAULT_COLOR_SCHEME=new tr.b.SinebowColorGenerator();function getHistogramName(histogram,diagnosticName,key){if(histogram===undefined)return undefined;const nameMap=histogram.diagnostics.get(diagnosticName);if(nameMap===undefined)return undefined;return nameMap.get(key);}
+yAxis.selectAll('*').remove();if(this.hideYAxis)return;const nameTexts=yAxis.selectAll('text').data(this.data_);nameTexts.enter().append('text').attr('x',d=>-(tr.ui.b.getSVGTextSize(this,d.x).width+Y_AXIS_PADDING)).attr('y',(d,index)=>this.verticalScale_(index)).text(d=>d.x);nameTexts.exit().remove();let previousTop=undefined;for(const text of nameTexts[0]){const bbox=text.getBBox();if((previousTop===undefined)||(previousTop>(bbox.y+bbox.height))){previousTop=bbox.y;}else{text.style.opacity=0;}}}};return{NameBarChart,};});'use strict';tr.exportTo('tr.v.ui',function(){const DIAGNOSTIC_SPAN_BEHAVIOR={created(){this.diagnostic_=undefined;this.name_=undefined;this.histogram_=undefined;},attached(){if(this.diagnostic_)this.updateContents_();},get diagnostic(){return this.diagnostic_;},build(diagnostic,name,histogram){this.diagnostic_=diagnostic;this.name_=name;this.histogram_=histogram;if(this.isAttached)this.updateContents_();},updateContents_(){throw new Error('dom-modules must override updateContents_()');}};return{DIAGNOSTIC_SPAN_BEHAVIOR,};});'use strict';tr.exportTo('tr.v.ui',function(){const DEFAULT_COLOR_SCHEME=new tr.b.SinebowColorGenerator();function getHistogramName(histogram,diagnosticName,key){if(histogram===undefined)return undefined;const nameMap=histogram.diagnostics.get(diagnosticName);if(nameMap===undefined)return undefined;return nameMap.get(key);}
class BreakdownTableSummaryRow{constructor(displayElement,histogramNames){this.displayElement_=displayElement;this.histogramNames_=histogramNames;this.keySpan_=undefined;}
get numberValue(){return undefined;}
get keySpan(){if(this.keySpan_===undefined){if(this.histogramNames_.length){this.keySpan_=document.createElement('tr-ui-a-analysis-link');this.keySpan_.setSelectionAndContent(this.histogramNames_,'Select All');}else{this.keySpan_='Sum';}}
@@ -9133,9 +9585,8 @@ if(other.numberValue===undefined){return-1;}
if(this.numberValue===other.numberValue){return this.name.localeCompare(other.name);}
return other.numberValue-this.numberValue;}}
Polymer({is:'tr-v-ui-breakdown-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],created(){this.chart_=new tr.ui.b.ColumnChart();this.chart_.graphHeight=130;this.chart_.isStacked=true;this.chart_.hideXAxis=true;this.chart_.hideLegend=true;this.chart_.enableHoverBox=false;this.chart_.addEventListener('rect-mouseenter',event=>this.onRectMouseEnter_(event));this.chart_.addEventListener('rect-mouseleave',event=>this.onRectMouseLeave_(event));},onRectMouseEnter_(event){for(const row of this.$.table.tableRows){if(row.name===event.rect.key){row.displayElement.style.background=event.rect.color;row.keySpan.scrollIntoViewIfNeeded();}else{row.displayElement.style.background='';}}},onRectMouseLeave_(event){for(const row of this.$.table.tableRows){row.displayElement.style.background='';}},ready(){Polymer.dom(this.$.container).appendChild(this.chart_);this.$.table.zebra=true;this.$.table.showHeader=false;this.$.table.tableColumns=[{value:row=>row.keySpan,},{value:row=>row.displayElement,align:tr.ui.b.TableFormat.ColumnAlignment.RIGHT,},{value:row=>row.stringPercent,align:tr.ui.b.TableFormat.ColumnAlignment.RIGHT,},];},updateContents_(){this.$.container.style.display='none';this.$.table.style.display='none';this.$.empty.style.display='block';if(!this.diagnostic_){this.chart_.data=[];return;}
-if(this.histogram_)this.chart_.unit=this.histogram_.unit;let colorScheme=undefined;if(this.diagnostic.colorScheme===tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER){colorScheme=(name)=>{let cat=name.split(' ');cat=cat[cat.length-1];return tr.e.chrome.ChromeUserFriendlyCategoryDriver.getColor(cat);};}else if(this.diagnostic.colorScheme!==undefined){colorScheme=(name)=>tr.b.FixedColorSchemeRegistry.lookUp(this.diagnostic.colorScheme).getColor(name);}else{colorScheme=(name)=>DEFAULT_COLOR_SCHEME.colorForKey(name);}
-const tableRows=[];let tableSum=0;const histogramNames=[];for(const[key,value]of this.diagnostic){let histogramName;let row;if(value instanceof tr.v.Histogram){histogramName=value.name;row=new BreakdownTableRow(key,value.sum,histogramName,value.unit,colorScheme(key));}else{histogramName=getHistogramName(this.histogram_,this.name_,key);row=new BreakdownTableRow(key,value,histogramName,this.chart_.unit,colorScheme(key));}
-tableRows.push(row);if(row.numberValue!==undefined)tableSum+=row.numberValue;if(histogramName){histogramNames.push(histogramName);}}
+if(this.histogram_)this.chart_.unit=this.histogram_.unit;let colorScheme=undefined;if(this.diagnostic.colorScheme===tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER){colorScheme=(name)=>{let cat=name.split(' ');cat=cat[cat.length-1];return tr.e.chrome.ChromeUserFriendlyCategoryDriver.getColor(cat);};}else if(this.diagnostic.colorScheme){colorScheme=(name)=>tr.b.FixedColorSchemeRegistry.lookUp(this.diagnostic.colorScheme).getColor(name);}else{colorScheme=(name)=>DEFAULT_COLOR_SCHEME.colorForKey(name);}
+const tableRows=[];let tableSum=0;const histogramNames=[];for(const[key,value]of this.diagnostic){const histogramName=getHistogramName(this.histogram_,this.name_,key);const row=new BreakdownTableRow(key,value,histogramName,this.chart_.unit,colorScheme(key));tableRows.push(row);if(row.numberValue!==undefined)tableSum+=row.numberValue;if(histogramName){histogramNames.push(histogramName);}}
tableRows.sort((x,y)=>x.compare(y));if(tableSum>0){let summaryDisplayElement=tableSum;if(this.chart_.unit!==undefined){summaryDisplayElement=this.chart_.unit.format(tableSum);}
summaryDisplayElement=tr.ui.b.createSpan({textContent:summaryDisplayElement,});tableRows.unshift(new BreakdownTableSummaryRow(summaryDisplayElement,histogramNames));}
const chartData={x:0};for(const row of tableRows){if(row.numberValue===undefined)continue;row.tableSum=tableSum;chartData[row.name]=row.numberValue;const dataSeries=this.chart_.getDataSeries(row.name);dataSeries.color=row.color;dataSeries.highlightedColor=row.highlightedColor;}
@@ -9143,18 +9594,15 @@ if(tableRows.length>0){this.$.table.style.display='block';this.$.empty.style.dis
if(Object.keys(chartData).length>1){this.$.container.style.display='block';this.$.empty.style.display='none';this.chart_.data=[chartData];}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-collected-related-event-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){Polymer.dom(this).textContent='';for(const[canonicalUrl,events]of this.diagnostic){const link=document.createElement('a');if(events.length===1){const event=tr.b.getOnlyElement(events);link.textContent=event.title+' '+
tr.b.Unit.byName.timeDurationInMs.format(event.duration);}else{link.textContent=events.length+' events';}
link.href=canonicalUrl;Polymer.dom(this).appendChild(link);Polymer.dom(this).appendChild(document.createElement('br'));}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-date-range-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){if(this.diagnostic===undefined){Polymer.dom(this).textContent='';return;}
-Polymer.dom(this).textContent=this.diagnostic.toString();}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-generic-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){this.$.generic.style.display='none';this.$.links.textContent='';if(this.diagnostic===undefined)return;const values=Array.from(this.diagnostic);let areAllStrings=true;let areAllNumbers=true;for(const value of values){if(typeof value!=='number'){areAllNumbers=false;if(typeof value!=='string'){areAllStrings=false;break;}}}
+Polymer.dom(this).textContent=this.diagnostic.toString();}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){function isLinkTuple(value){return((value instanceof Array)&&(value.length===2)&&(typeof value[0]==='string')&&tr.b.isUrl(value[1]));}
+Polymer({is:'tr-v-ui-generic-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){this.$.generic.style.display='none';this.$.links.textContent='';if(this.diagnostic===undefined)return;const values=Array.from(this.diagnostic);let areAllStrings=true;let areAllNumbers=true;for(const value of values){if(typeof value!=='number'){areAllNumbers=false;if(typeof value!=='string'&&!isLinkTuple(value)){areAllStrings=false;break;}}}
if(!areAllStrings){this.$.generic.style.display='';this.$.generic.object=values;return;}
if(areAllNumbers){values.sort((x,y)=>x-y);}else{values.sort();}
-for(const value of values){const link={textContent:''+value};if(tr.b.isUrl(value))link.href=value;if(this.name_===tr.v.d.RESERVED_NAMES.TRACE_URLS){link.textContent=value.substr(1+value.lastIndexOf('/'));}
+for(const value of values){const link={textContent:''+value};if(isLinkTuple(value)){link.textContent=value[0];link.href=value[1];}else if(tr.b.isUrl(value)){link.href=value;}
+if(this.name_===tr.v.d.RESERVED_NAMES.TRACE_URLS){link.textContent=value.substr(1+value.lastIndexOf('/'));}
const linkEl=tr.ui.b.createLink(link);if(link.href){linkEl.target='_blank';linkEl.addEventListener('click',e=>e.stopPropagation());}
this.$.links.appendChild(linkEl);}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-related-event-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){Polymer.dom(this).textContent='';const events=new tr.model.EventSet([...this.diagnostic]);const link=document.createElement('tr-ui-a-analysis-link');let label=events.length+' events';if(events.length===1){const event=tr.b.getOnlyElement(events);label=event.title+' ';label+=tr.b.Unit.byName.timeDurationInMs.format(event.duration);}
-link.setSelectionAndContent(events,label);Polymer.dom(this).appendChild(link);}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-related-histogram-map-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],ready(){this.$.table.showHeader=false;this.$.table.tableColumns=[{value:row=>row[0]},{value:row=>row[1]},];},updateContents_(){Polymer.dom(this).textContent='';const rows=[];const histogramNames=new Set();for(const[name,hist]of this.diagnostic){histogramNames.add(hist.name);}
-if(histogramNames.size>1){const link=document.createElement('tr-ui-a-analysis-link');link.setSelectionAndContent(Array.from(histogramNames),'Select All');rows.push([link,'']);}
-for(const[name,hist]of this.diagnostic){const link=document.createElement('tr-ui-a-analysis-link');link.setSelectionAndContent([hist.name],name);const scalarSpan=tr.v.ui.createScalarSpan(hist);rows.push([link,scalarSpan]);}
-this.$.table.tableRows=rows;this.$.table.rebuild();}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-scalar-diagnostic-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){this.$.scalar.setValueAndUnit(this.diagnostic.value.value,this.diagnostic.value.unit);}});return{};});'use strict';Polymer({is:'tr-v-ui-tag-map-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){if(this.diagnostic===undefined){this.$.generic.object=undefined;return;}
-const obj={};for(const[tag,stories]of this.diagnostic.tagsToStoryNames){obj[tag]=Array.from(stories);}
-this.$.generic.object=obj;},onShow_(){this.$.show.style.display='none';this.$.hide.style.display='block';this.$.generic.style.display='block';},onHide_(){this.$.show.style.display='block';this.$.hide.style.display='none';this.$.generic.style.display='none';},});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-unmergeable-diagnostic-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){Polymer.dom(this).textContent='';for(const diagnostic of this.diagnostic){const div=document.createElement('div');div.appendChild(tr.v.ui.createDiagnosticSpan(diagnostic,this.name_,this.histogram_));Polymer.dom(this).appendChild(div);}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){function findElementNameForDiagnostic(diagnostic){let typeInfo=undefined;let curProto=diagnostic.constructor.prototype;while(curProto){typeInfo=tr.v.d.Diagnostic.findTypeInfo(curProto.constructor);if(typeInfo&&typeInfo.metadata.elementName)break;typeInfo=undefined;curProto=curProto.__proto__;}
+link.setSelectionAndContent(events,label);Polymer.dom(this).appendChild(link);}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-scalar-diagnostic-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){this.$.scalar.setValueAndUnit(this.diagnostic.value.value,this.diagnostic.value.unit);}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-unmergeable-diagnostic-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){Polymer.dom(this).textContent='';for(const diagnostic of this.diagnostic){if(diagnostic instanceof tr.v.d.RelatedNameMap)continue;const div=document.createElement('div');div.appendChild(tr.v.ui.createDiagnosticSpan(diagnostic,this.name_,this.histogram_));Polymer.dom(this).appendChild(div);}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){function findElementNameForDiagnostic(diagnostic){let typeInfo=undefined;let curProto=diagnostic.constructor.prototype;while(curProto){typeInfo=tr.v.d.Diagnostic.findTypeInfo(curProto.constructor);if(typeInfo&&typeInfo.metadata.elementName)break;typeInfo=undefined;curProto=curProto.__proto__;}
if(typeInfo===undefined){throw new Error(diagnostic.constructor.name+' or a base class must have a registered elementName');}
const tagName=typeInfo.metadata.elementName;if(tr.ui.b.isUnknownElementName(tagName)){throw new Error('Element not registered: '+tagName);}
return tagName;}
@@ -9162,7 +9610,7 @@ function createDiagnosticSpan(diagnostic,name,histogram){const tagName=findEleme
return{createDiagnosticSpan,};});'use strict';tr.exportTo('tr.v.ui',function(){function makeColumn(title,histogram){return{title,value(map){const diagnostic=map.get(title);if(!diagnostic)return'';return tr.v.ui.createDiagnosticSpan(diagnostic,title,histogram);}};}
Polymer({is:'tr-v-ui-diagnostic-map-table',created(){this.diagnosticMaps_=undefined;this.histogram_=undefined;this.isMetadata_=false;},set histogram(h){this.histogram_=h;},set isMetadata(m){this.isMetadata_=m;this.$.table.showHeader=!this.isMetadata_;},set diagnosticMaps(maps){this.diagnosticMaps_=maps;this.updateContents_();},get diagnosticMaps(){return this.diagnosticMaps_;},updateContents_(){if(this.isMetadata_&&this.diagnosticMaps_.length!==1){throw new Error('Metadata diagnostic-map-tables require exactly 1 DiagnosticMap');}
if(this.diagnosticMaps_===undefined||this.diagnosticMaps_.length===0){this.$.table.tableRows=[];this.$.table.tableColumns=[];return;}
-let names=new Set();for(const map of this.diagnosticMaps_){for(const[name,diagnostic]of map){if(diagnostic instanceof tr.v.d.UnmergeableDiagnosticSet)continue;if(diagnostic instanceof tr.v.d.CollectedRelatedEventSet)continue;if(diagnostic instanceof tr.v.d.GroupingPath)continue;names.add(name);}}
+let names=new Set();for(const map of this.diagnosticMaps_){for(const[name,diagnostic]of map){if(diagnostic instanceof tr.v.d.UnmergeableDiagnosticSet)continue;if(diagnostic instanceof tr.v.d.CollectedRelatedEventSet)continue;names.add(name);}}
names=Array.from(names).sort();const histogram=this.histogram_;if(this.isMetadata_){const diagnosticMap=this.diagnosticMaps_[0];this.$.table.tableColumns=[{value(name){return name.name;}},{value(name){const diagnostic=diagnosticMap.get(name.name);if(!diagnostic)return'';return tr.v.ui.createDiagnosticSpan(diagnostic,name.name,histogram);}},];this.$.table.tableRows=names.map(name=>{return{name};});}else{this.$.table.tableColumns=names.map(name=>makeColumn(name,histogram));this.$.table.tableRows=this.diagnosticMaps_;}
this.$.table.rebuild();}});return{};});'use strict';tr.exportTo('tr.b',function(){class Serializable{constructor(){Object.defineProperty(this,'properties_',{configurable:false,enumerable:false,value:new Map(),});}
define(name,initialValue){if(this[name]!==undefined){throw new Error(`"${name}" is already defined.`);}
@@ -9222,7 +9670,7 @@ if(this.viewState.mergeSampleDiagnostics){const merged=new tr.v.d.DiagnosticMap(
maps=[merged];}
const mark=tr.b.Timing.mark('histogram-span',(this.viewState.mergeSampleDiagnostics?'merge':'split')+'SampleDiagnostics');this.$.sample_diagnostics.diagnosticMaps=maps;mark.end();if(this.anySampleDiagnostics_){this.$.diagnostics.selectedSubView=this.$.sample_diagnostics_container;}},get histogram(){return this.histogram_;},get referenceHistogram(){return this.referenceHistogram_;},getDeltaScalars_(statNames,scalarMap){if(!this.histogram.canCompare(this.referenceHistogram))return;for(const deltaStatName of tr.v.Histogram.getDeltaStatisticsNames(statNames)){if(IGNORE_DELTA_STATISTICS_NAMES.includes(deltaStatName))continue;const scalar=this.histogram.getStatisticScalar(deltaStatName,this.referenceHistogram,this.mwuResult_);if(scalar===undefined)continue;scalarMap.set(deltaStatName,scalar);}},set isYLogScale(logScale){this.chart_.isYLogScale=logScale;},async updateContents_(){this.$.chart.style.display='none';this.$.drag_handle.style.display='none';this.$.container.style.justifyContent='';while(Polymer.dom(this.$.chart).lastChild){Polymer.dom(this.$.chart).removeChild(Polymer.dom(this.$.chart).lastChild);}
if(!this.histogram)return;this.$.container.style.display='';const scalarMap=new Map();this.getDeltaScalars_(this.histogram.statisticsNames,scalarMap);for(const[name,scalar]of this.histogram.statisticsScalars){scalarMap.set(name,scalar);}
-this.$.stats.scalarMap=scalarMap;this.updateSignificance_();const metricDiagnosticMap=new tr.v.d.DiagnosticMap();const metadataDiagnosticMap=new tr.v.d.DiagnosticMap();for(const[key,diagnostic]of this.histogram.diagnostics){if(key===tr.v.d.RESERVED_NAMES.MERGED_FROM)continue;if(key===tr.v.d.RESERVED_NAMES.MERGED_TO)continue;if(diagnostic instanceof tr.v.d.GroupingPath)continue;if(diagnostic instanceof tr.v.d.RelatedNameMap)continue;if(tr.v.d.RESERVED_NAMES_SET.has(key)){metadataDiagnosticMap.set(key,diagnostic);}else{metricDiagnosticMap.set(key,diagnostic);}}
+this.$.stats.scalarMap=scalarMap;this.updateSignificance_();const metricDiagnosticMap=new tr.v.d.DiagnosticMap();const metadataDiagnosticMap=new tr.v.d.DiagnosticMap();for(const[key,diagnostic]of this.histogram.diagnostics){if(diagnostic instanceof tr.v.d.RelatedNameMap)continue;if(tr.v.d.RESERVED_NAMES_SET.has(key)){metadataDiagnosticMap.set(key,diagnostic);}else{metricDiagnosticMap.set(key,diagnostic);}}
const diagnosticTabs=[];if(metricDiagnosticMap.size){this.$.metric_diagnostics.diagnosticMaps=[metricDiagnosticMap];diagnosticTabs.push(this.$.metric_diagnostics);}
if(this.anySampleDiagnostics_){diagnosticTabs.push(this.$.sample_diagnostics_container);}
if(metadataDiagnosticMap.size){this.$.metadata_diagnostics.diagnosticMaps=[metadataDiagnosticMap];diagnosticTabs.push(this.$.metadata_diagnostics);}
@@ -9237,7 +9685,7 @@ if(binCounts[2]>0&&binCounts[1]>(binCounts[2]*2)){dataRange.max=binCounts[2]*(1+
this.chart_.overrideDataRange=dataRange;this.chart_.data=chartData;this.$.stats_container.style.maxHeight=this.chart_.getBoundingClientRect().height+'px';}});});'use strict';tr.exportTo('tr.ui.analysis',function(){const EVENT_FIELD=[{key:'start',label:'Start'},{key:'cpuDuration',label:'CPU Duration'},{key:'duration',label:'Duration'},{key:'cpuSelfTime',label:'CPU Self Time'},{key:'selfTime',label:'Self Time'}];function buildDiagnostics_(slice){const diagnostics={};for(const item of EVENT_FIELD){const fieldName=item.key;if(slice[fieldName]===undefined)continue;diagnostics[fieldName]=new tr.v.d.Scalar(new tr.b.Scalar(tr.b.Unit.byName.timeDurationInMs,slice[fieldName]));}
diagnostics.args=new tr.v.d.GenericSet([slice.args]);diagnostics.event=new tr.v.d.RelatedEventSet(slice);return diagnostics;}
Polymer({is:'tr-ui-a-multi-event-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;},ready(){this.$.radioPicker.style.display='none';this.$.radioPicker.items=EVENT_FIELD;this.$.radioPicker.select('cpuSelfTime');this.$.radioPicker.addEventListener('change',()=>{if(this.isAttached)this.updateContents_();});this.$.histogramSpan.graphWidth=400;this.$.histogramSpan.canMergeSampleDiagnostics=false;this.$.histogramContainer.style.display='none';},attached(){if(this.currentSelection_!==undefined)this.updateContents_();},set selection(selection){if(selection.length<=1){throw new Error('Only supports multiple items');}
-this.setSelectionWithoutErrorChecks(selection);},get selection(){return this.currentSelection_;},setSelectionWithoutErrorChecks(selection){this.currentSelection_=selection;if(this.isAttached)this.updateContents_();},get eventsHaveDuration(){return this.eventsHaveDuration_;},set eventsHaveDuration(eventsHaveDuration){this.eventsHaveDuration_=eventsHaveDuration;if(this.isAttached)this.updateContents_();},get eventsHaveSubRows(){return this.eventsHaveSubRows_;},set eventsHaveSubRows(eventsHaveSubRows){this.eventsHaveSubRows_=eventsHaveSubRows;if(this.isAttached)this.updateContents_();},buildHistogram_(selectedKey){let leftBoundary=Number.MAX_VALUE;let rightBoundary=tr.b.math.Statistics.percentile(this.currentSelection_,0.95,function(value){leftBoundary=Math.min(leftBoundary,value[selectedKey]);return value[selectedKey];});if(leftBoundary===rightBoundary)rightBoundary+=1;const histogram=new tr.v.Histogram('',tr.b.Unit.byName.timeDurationInMs,tr.v.HistogramBinBoundaries.createLinear(leftBoundary,rightBoundary,Math.ceil(Math.sqrt(this.currentSelection_.length))));histogram.customizeSummaryOptions({sum:false});for(const slice of this.currentSelection_){histogram.addSample(slice[selectedKey],buildDiagnostics_(slice));}
+this.setSelectionWithoutErrorChecks(selection);},get selection(){return this.currentSelection_;},setSelectionWithoutErrorChecks(selection){this.currentSelection_=selection;if(this.isAttached)this.updateContents_();},get eventsHaveDuration(){return this.eventsHaveDuration_;},set eventsHaveDuration(eventsHaveDuration){this.eventsHaveDuration_=eventsHaveDuration;if(this.isAttached)this.updateContents_();},get eventsHaveSubRows(){return this.eventsHaveSubRows_;},set eventsHaveSubRows(eventsHaveSubRows){this.eventsHaveSubRows_=eventsHaveSubRows;if(this.isAttached)this.updateContents_();},buildHistogram_(selectedKey){let leftBoundary=Number.MAX_VALUE;let rightBoundary=tr.b.math.Statistics.percentile(this.currentSelection_,0.95,function(value){leftBoundary=Math.min(leftBoundary,value[selectedKey]);return value[selectedKey];});if(leftBoundary===rightBoundary)rightBoundary+=1;const histogram=new tr.v.Histogram('',tr.b.Unit.byName.timeDurationInMs,tr.v.HistogramBinBoundaries.createLinear(leftBoundary,rightBoundary,Math.ceil(Math.sqrt(this.currentSelection_.length))));histogram.customizeSummaryOptions({sum:false,percentile:[0.5,0.9],});for(const slice of this.currentSelection_){histogram.addSample(slice[selectedKey],buildDiagnostics_(slice));}
return histogram;},updateContents_(){const selection=this.currentSelection_;if(!selection)return;const eventsByTitle=selection.getEventsOrganizedByTitle();const numTitles=Object.keys(eventsByTitle).length;this.$.eventSummaryTable.configure({showTotals:numTitles>1,eventsByTitle,eventsHaveDuration:this.eventsHaveDuration_,eventsHaveSubRows:this.eventsHaveSubRows_});this.$.selectionSummaryTable.selection=this.currentSelection_;if(numTitles===1){this.$.radioPicker.style.display='block';this.$.histogramContainer.style.display='flex';this.$.histogramSpan.build(this.buildHistogram_(this.$.radioPicker.selectedKey));if(this.$.histogramSpan.histogram.numValues===0){this.$.histogramContainer.style.display='none';}}else{this.$.radioPicker.style.display='none';this.$.histogramContainer.style.display='none';}}});return{};});'use strict';tr.exportTo('tr.ui.analysis',function(){const FLOW_IN=0x1;const FLOW_OUT=0x2;const FLOW_IN_OUT=FLOW_IN|FLOW_OUT;function FlowClassifier(){this.numEvents_=0;this.eventsByGUID_={};}
FlowClassifier.prototype={getFS_(event){let fs=this.eventsByGUID_[event.guid];if(fs===undefined){this.numEvents_++;fs={state:0,event};this.eventsByGUID_[event.guid]=fs;}
return fs;},addInFlow(event){const fs=this.getFS_(event);fs.state|=FLOW_IN;return event;},addOutFlow(event){const fs=this.getFS_(event);fs.state|=FLOW_OUT;return event;},hasEvents(){return this.numEvents_>0;},get inFlowEvents(){const selection=new tr.model.EventSet();for(const guid in this.eventsByGUID_){const fs=this.eventsByGUID_[guid];if(fs.state===FLOW_IN){selection.push(fs.event);}}
@@ -9544,7 +9992,7 @@ ctx.restore();tr.ui.tracks.ContainerTrack.prototype.drawTrack.call(this,type);},
this.drawFlowArrow_(ctx,events[i],canvasBounds);}},drawFlowArrow_(ctx,flowEvent,canvasBounds){const dt=this.viewport.currentDisplayTransform;const pixelRatio=window.devicePixelRatio||1;const startTrack=this.viewport.trackForEvent(flowEvent.startSlice);const endTrack=this.viewport.trackForEvent(flowEvent.endSlice);if(startTrack===undefined||endTrack===undefined)return;const startBounds=startTrack.getBoundingClientRect();const endBounds=endTrack.getBoundingClientRect();if(flowEvent.selectionState===SelectionState.SELECTED){ctx.shadowBlur=1;ctx.shadowColor='red';ctx.shadowOffsety=2;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[tr.b.ColorScheme.getVariantColorId(flowEvent.colorId,tr.b.ColorScheme.properties.brightenedOffsets[0])];}else if(flowEvent.selectionState===SelectionState.HIGHLIGHTED){ctx.shadowBlur=1;ctx.shadowColor='red';ctx.shadowOffsety=2;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[tr.b.ColorScheme.getVariantColorId(flowEvent.colorId,tr.b.ColorScheme.properties.brightenedOffsets[0])];}else if(flowEvent.selectionState===SelectionState.DIMMED){ctx.shadowBlur=0;ctx.shadowOffsetX=0;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[flowEvent.colorId];}else{let hasBoost=false;const startSlice=flowEvent.startSlice;hasBoost|=startSlice.selectionState===SelectionState.SELECTED;hasBoost|=startSlice.selectionState===SelectionState.HIGHLIGHTED;const endSlice=flowEvent.endSlice;hasBoost|=endSlice.selectionState===SelectionState.SELECTED;hasBoost|=endSlice.selectionState===SelectionState.HIGHLIGHTED;if(hasBoost){ctx.shadowBlur=1;ctx.shadowColor='rgba(255, 0, 0, 0.4)';ctx.shadowOffsety=2;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[tr.b.ColorScheme.getVariantColorId(flowEvent.colorId,tr.b.ColorScheme.properties.brightenedOffsets[0])];}else{ctx.shadowBlur=0;ctx.shadowOffsetX=0;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[flowEvent.colorId];}}
const startSize=startBounds.left+startBounds.top+
startBounds.bottom+startBounds.right;const endSize=endBounds.left+endBounds.top+
-endBounds.bottom+endBounds.right;if(startSize===0&&endSize===0)return;const startY=this.calculateTrackY_(startTrack,canvasBounds);const endY=this.calculateTrackY_(endTrack,canvasBounds);const pixelStartY=pixelRatio*startY;const pixelEndY=pixelRatio*endY;const startXView=dt.xWorldToView(flowEvent.start);const endXView=dt.xWorldToView(flowEvent.end);const midXView=(startXView+endXView)/2;ctx.beginPath();ctx.moveTo(startXView,pixelStartY);ctx.bezierCurveTo(midXView,pixelStartY,midXView,pixelEndY,endXView,pixelEndY);ctx.stroke();const arrowWidth=5*pixelRatio;const distance=endXView-startXView;if(distance<=(2*arrowWidth))return;const tipX=endXView;const tipY=pixelEndY;const arrowHeight=(endBounds.height/4)*pixelRatio;tr.ui.b.drawTriangle(ctx,tipX,tipY,tipX-arrowWidth,tipY-arrowHeight,tipX-arrowWidth,tipY+arrowHeight);ctx.fill();},drawVSyncHighlight(ctx,dt,viewLWorld,viewRWorld,viewHeight){if(!this.viewport_.highlightVSync){return;}
+endBounds.bottom+endBounds.right;if(startSize===0&&endSize===0)return;const startY=this.calculateTrackY_(startTrack,canvasBounds);const endY=this.calculateTrackY_(endTrack,canvasBounds);const worldOffset=this.getBoundingClientRect().top-canvasBounds.top;const pixelStartY=pixelRatio*(startY-worldOffset);const pixelEndY=pixelRatio*(endY-worldOffset);const startXView=dt.xWorldToView(flowEvent.start);const endXView=dt.xWorldToView(flowEvent.end);const midXView=(startXView+endXView)/2;ctx.beginPath();ctx.moveTo(startXView,pixelStartY);ctx.bezierCurveTo(midXView,pixelStartY,midXView,pixelEndY,endXView,pixelEndY);ctx.stroke();const arrowWidth=5*pixelRatio;const distance=endXView-startXView;if(distance<=(2*arrowWidth))return;const tipX=endXView;const tipY=pixelEndY;const arrowHeight=(endBounds.height/4)*pixelRatio;tr.ui.b.drawTriangle(ctx,tipX,tipY,tipX-arrowWidth,tipY-arrowHeight,tipX-arrowWidth,tipY+arrowHeight);ctx.fill();},drawVSyncHighlight(ctx,dt,viewLWorld,viewRWorld,viewHeight){if(!this.viewport_.highlightVSync){return;}
const stripes=ModelTrack.generateStripes_(this.vSyncTimes_,viewLWorld,viewRWorld);if(stripes.length===0){return;}
const vSyncHighlightColor=new tr.b.Color(ColorScheme.getColorForReservedNameAsString('vsync_highlight_color'));const stripeRange=stripes[stripes.length-1].max-stripes[0].min;const stripeDensity=stripeRange?stripes.length/(dt.scaleX*stripeRange):0;const clampedStripeDensity=tr.b.math.clamp(stripeDensity,ModelTrack.VSYNC_DENSITY_OPAQUE,ModelTrack.VSYNC_DENSITY_TRANSPARENT);const opacity=(ModelTrack.VSYNC_DENSITY_TRANSPARENT-clampedStripeDensity)/ModelTrack.VSYNC_DENSITY_RANGE;if(opacity===0){return;}
ctx.fillStyle=vSyncHighlightColor.toStringWithAlphaOverride(ModelTrack.VSYNC_HIGHLIGHT_ALPHA*opacity);for(let i=0;i<stripes.length;i++){const xLeftView=dt.xWorldToView(stripes[i].min);const xRightView=dt.xWorldToView(stripes[i].max);ctx.fillRect(xLeftView,0,xRightView-xLeftView,viewHeight);}},calculateTrackY_(track,canvasBounds){const bounds=track.getBoundingClientRect();const size=bounds.left+bounds.top+bounds.bottom+bounds.right;if(size===0){return this.calculateTrackY_(Polymer.dom(track).parentNode,canvasBounds);}
@@ -9707,10 +10155,10 @@ if(config){return{excluded:config.excluded_categories||[],included:config.includ
function validateTraceCategories(requiredCategories,categories){if(!requiredCategories)return;if(!categories)throw new Error('Missing trace config metadata');for(const cat of requiredCategories){const isDisabledByDefault=(cat.indexOf('disabled-by-default')===0);let missing=false;if(isDisabledByDefault){if(!categories.included.includes(cat)){missing=true;}}else if(categories.excluded.includes(cat)){missing=true;}
if(missing){throw new Error(`Trace is missing required category "${cat}"`);}}}
function validateDiagnosticNames(histograms){for(const hist of histograms){for(const name of hist.diagnostics.keys()){if(tr.v.d.RESERVED_NAMES_SET.has(name)){throw new Error(`Illegal diagnostic name "${name}" on Histogram "${hist.name}"`);}}}}
-function addTelemetryInfo(histograms,model){for(const metadata of model.metadata){if(!metadata.value||!metadata.value.telemetry)continue;const traceUrls=metadata.value.telemetry[tr.v.d.RESERVED_NAMES.TRACE_URLS];if(traceUrls&&model.canonicalUrl!==traceUrls[0]){throw new Error(`canonicalUrl "${model.canonicalUrl}" != `+`traceUrl "${traceUrls[0]}"`);}
-for(const[name,value]of Object.entries(metadata.value.telemetry)){const type=tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);if(type===undefined){throw new Error(`Unexpected telemetry.${name}`);}
+function addTelemetryInfo(histograms,model){for(const metadata of model.metadata){if(!metadata.value||!metadata.value.telemetry)continue;for(const[name,value]of Object.entries(metadata.value.telemetry)){const type=tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);if(type===undefined){throw new Error(`Unexpected telemetry.${name}`);}
histograms.addSharedDiagnosticToAllHistograms(name,new type(value));}}}
-function metricMapFunction(result,model,options){const histograms=runMetrics(model,options,result.addFailure.bind(result));addTelemetryInfo(histograms,model);result.addPair('histograms',histograms.asDicts());const scalarDicts=[];for(const value of histograms){for(const[statName,scalar]of value.statisticsScalars){scalarDicts.push({name:value.name+'_'+statName,numeric:scalar.asDict(),description:value.description,});}}
+function metricMapFunction(result,model,options){const histograms=runMetrics(model,options,result.addFailure.bind(result));addTelemetryInfo(histograms,model);if(model.canonicalUrl!==undefined){const info=tr.v.d.RESERVED_INFOS.TRACE_URLS;histograms.addSharedDiagnosticToAllHistograms(info.name,new info.type([model.canonicalUrl]));}
+result.addPair('histograms',histograms.asDicts());const scalarDicts=[];for(const value of histograms){for(const[statName,scalar]of value.statisticsScalars){scalarDicts.push({name:value.name+'_'+statName,numeric:scalar.asDict(),description:value.description,});}}
result.addPair('scalars',scalarDicts);}
tr.mre.FunctionRegistry.register(metricMapFunction);return{metricMapFunction,runMetrics,};});'use strict';tr.exportTo('tr.mre',function(){class MreResult{constructor(failures,pairs){if(failures===undefined){failures=[];}
if(pairs===undefined){pairs={};}
@@ -9766,7 +10214,7 @@ let cell=''+row[i];cell=cell.replace(/\n/g,' ');if(cell.indexOf(',')>=0||cell.in
str+=cell;}
str+='\n';}
return str;}}
-return{CSVBuilder,};});'use strict';tr.exportTo('tr.v',function(){const getDisplayLabel=tr.v.HistogramGrouping.DISPLAY_LABEL.callback;const DEFAULT_POSSIBLE_GROUPS=[];DEFAULT_POSSIBLE_GROUPS.push(new tr.v.HistogramGrouping(tr.v.HistogramGrouping.HISTOGRAM_NAME.key,h=>h.shortName||h.name));const EXCLUDED_GROUPING_KEYS=[tr.v.HistogramGrouping.HISTOGRAM_NAME.key,tr.v.HistogramGrouping.DISPLAY_LABEL.key,];for(const group of tr.v.HistogramGrouping.BY_KEY.values()){if(EXCLUDED_GROUPING_KEYS.includes(group.key))continue;DEFAULT_POSSIBLE_GROUPS.push(group);}
+return{CSVBuilder,};});'use strict';tr.exportTo('tr.v',function(){const getDisplayLabel=tr.v.HistogramGrouping.DISPLAY_LABEL.callback;const DEFAULT_POSSIBLE_GROUPS=[];const EXCLUDED_GROUPING_KEYS=[tr.v.HistogramGrouping.DISPLAY_LABEL.key,];for(const group of tr.v.HistogramGrouping.BY_KEY.values()){if(EXCLUDED_GROUPING_KEYS.includes(group.key))continue;DEFAULT_POSSIBLE_GROUPS.push(group);}
class HistogramParameterCollector{constructor(){this.statisticNames_=new Set(['avg']);this.labelsToStartTimes_=new Map();this.keysToGroupings_=new Map(DEFAULT_POSSIBLE_GROUPS.map(g=>[g.key,g]));this.keysToValues_=new Map(DEFAULT_POSSIBLE_GROUPS.map(g=>[g.key,new Set()]));this.keysToValues_.delete(tr.v.HistogramGrouping.HISTOGRAM_NAME.key);}
process(histograms){const allStoryTags=new Set();let maxSampleCount=0;for(const hist of histograms){maxSampleCount=Math.max(maxSampleCount,hist.numValues);for(const statName of hist.statisticsNames){this.statisticNames_.add(statName);}
let startTime=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START);if(startTime!==undefined)startTime=startTime.minDate.getTime();const displayLabel=getDisplayLabel(hist);if(this.labelsToStartTimes_.has(displayLabel)){startTime=Math.min(startTime,this.labelsToStartTimes_.get(displayLabel));}
@@ -9805,35 +10253,20 @@ for(const name of names){const option=document.createElement('option');option.te
if(names.includes(this.viewState.displayStatisticName)){this.displayStatisticName=this.viewState.displayStatisticName;this.$.statistic.value=this.displayStatisticName;}else{this.viewState.displayStatisticName=names[0]||'';}},get anyOverviewCharts_(){for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){if(row.isOverviewed)return true;}
return false;},async toggleOverviewLineCharts_(){const showOverviews=!this.anyOverviewCharts_;const mark=tr.b.Timing.mark('histogram-set-controls',(showOverviews?'show':'hide')+'OverviewCharts');for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){await row.update({isOverviewed:showOverviews});}
this.$.hide_overview.style.display=showOverviews?'inline':'none';this.$.show_overview.style.display=showOverviews?'none':'inline';await tr.b.animationFrame();mark.end();},set helpHref(href){this.$.help.href=href;this.$.help.style.display='inline';},set feedbackHref(href){this.$.feedback.href=href;this.$.feedback.style.display='inline';},clearSearch_(){this.set('searchQuery','');this.$.search.focus();},getAlphaString_(alphaIndex){return(''+ALPHA_OPTIONS[alphaIndex]).substr(0,5);},openAlphaSlider_(){const alphaButtonRect=this.$.alpha.getBoundingClientRect();this.$.alpha_slider_container.style.display='flex';this.$.alpha_slider_container.style.top=alphaButtonRect.bottom+'px';this.$.alpha_slider_container.style.left=alphaButtonRect.left+'px';this.$.alpha_slider.focus();},closeAlphaSlider_(){this.$.alpha_slider_container.style.display='';},updateAlpha_(){this.alphaIndex=this.$.alpha_slider.value;},getAlphaIndexFromViewState_(){for(let i=0;i<ALPHA_OPTIONS.length;++i){if(ALPHA_OPTIONS[i]>=this.viewState.alpha)return i;}
-return ALPHA_OPTIONS.length-1;},set enableVisualization(enable){this.$.show_visualization.style.display=enable?'inline':'none';},loadVisualization_(){tr.b.dispatchSimpleEvent(this,'loadVisualization',true,true,{});},});return{};});'use strict';tr.exportTo('tr.v',function(){function deleteMergedToDiagnostics(histogramArrayMap){for(const[name,histograms]of histogramArrayMap){if(histograms instanceof Array){for(const histogram of histograms){histogram.diagnostics.delete(tr.v.d.RESERVED_NAMES.MERGED_TO);}}else if(histograms instanceof Map){deleteMergedToDiagnostics(histograms);}}}
-class HistogramSetHierarchy{constructor(name){this.name=name;this.description='';this.depth=0;this.subRows=[];this.columns=new Map();this.mergeRelationshipsForColumn_=new Map();}*walk(){yield this;for(const row of this.subRows)yield*row.walk();}
+return ALPHA_OPTIONS.length-1;},set enableVisualization(enable){this.$.show_visualization.style.display=enable?'inline':'none';},loadVisualization_(){tr.b.dispatchSimpleEvent(this,'loadVisualization',true,true,{});},});return{};});'use strict';tr.exportTo('tr.v',function(){class HistogramSetHierarchy{constructor(name){this.name=name;this.description='';this.depth=0;this.subRows=[];this.columns=new Map();}*walk(){yield this;for(const row of this.subRows)yield*row.walk();}
static*walkAll(rootRows){for(const rootRow of rootRows)yield*rootRow.walk();}
static build(histogramArrayMap){const rootRows=[];HistogramSetHierarchy.buildInternal_(histogramArrayMap,[],rootRows);const histograms=new tr.v.HistogramSet();for(const row of HistogramSetHierarchy.walkAll(rootRows)){for(const hist of row.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;histograms.addHistogram(hist);}}
-histograms.deduplicateDiagnostics();for(const row of HistogramSetHierarchy.walkAll(rootRows)){for(const[name,hist]of row.columns){if(!(hist instanceof tr.v.Histogram))continue;if(!row.mergeRelationshipsForColumn_.get(name))continue;hist.diagnostics.mergeRelationships(hist);}}
-deleteMergedToDiagnostics(histogramArrayMap);for(const row of HistogramSetHierarchy.walkAll(rootRows)){row.maybeRebin_();}
+histograms.deduplicateDiagnostics();for(const row of HistogramSetHierarchy.walkAll(rootRows)){row.maybeRebin_();}
return rootRows;}
maybeRebin_(){const dataRange=new tr.b.math.Range();for(const hist of this.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;if(hist.allBins.length>1)return;if(hist.numValues===0)continue;dataRange.addValue(hist.min);dataRange.addValue(hist.max);}
dataRange.addValue(tr.b.math.lesserWholeNumber(dataRange.min));dataRange.addValue(tr.b.math.greaterWholeNumber(dataRange.max));if(dataRange.min===dataRange.max)return;const boundaries=tr.v.HistogramBinBoundaries.createLinear(dataRange.min,dataRange.max,tr.v.DEFAULT_REBINNED_COUNT);for(const[name,hist]of this.columns){if(!(hist instanceof tr.v.Histogram))continue;this.columns.set(name,hist.rebin(boundaries));}}
-static mergeHistogramDownHierarchy_(histogram,hierarchy,columnName){let groupingPath=undefined;for(const row of hierarchy){if(groupingPath!==undefined){groupingPath.push(row.name);}else if(row.name===histogram.name){groupingPath=[];}
-if(!row.description){row.description=histogram.description;}
-const existing=row.columns.get(columnName);if(existing===undefined){const clone=histogram.clone();if(groupingPath!==undefined){new tr.v.d.GroupingPath(groupingPath).addToHistogram(clone);}
-row.columns.set(columnName,clone);row.mergeRelationshipsForColumn_.set(columnName,true);continue;}
+static mergeHistogramDownHierarchy_(histogram,hierarchy,columnName){for(const row of hierarchy){if(!row.description){row.description=histogram.description;}
+const existing=row.columns.get(columnName);if(existing===undefined){row.columns.set(columnName,histogram.clone());continue;}
if(existing instanceof tr.v.HistogramSet){existing.addHistogram(histogram);continue;}
-if(!existing.canAddHistogram(histogram)){const unmergeableHistograms=new tr.v.HistogramSet([histogram]);const mergedFrom=existing.diagnostics.get(tr.v.d.RESERVED_NAMES.MERGED_FROM);if(mergedFrom!==undefined){for(const[unusedName,origHist]of mergedFrom){unmergeableHistograms.addHistogram(origHist);}}
-row.columns.set(columnName,unmergeableHistograms);continue;}
-if(existing.name!==histogram.name){row.mergeRelationshipsForColumn_.set(name,false);}
+if(!existing.canAddHistogram(histogram)){const unmergeableHistograms=new tr.v.HistogramSet([histogram]);row.columns.set(columnName,unmergeableHistograms);continue;}
existing.addHistogram(histogram);}}
-static buildInternal_(histogramArrayMap,hierarchy,rootRows){for(const[name,histograms]of histogramArrayMap){if(histograms instanceof Array){for(const histogram of histograms){HistogramSetHierarchy.mergeHistogramDownHierarchy_(histogram,hierarchy,name);}}else if(histograms instanceof Map){const row=new HistogramSetHierarchy(name);row.depth=hierarchy.length;hierarchy.push(row);HistogramSetHierarchy.buildInternal_(histograms,hierarchy,rootRows);hierarchy.pop();if(hierarchy.length===0){rootRows.push(row);}else{const parentRow=hierarchy[hierarchy.length-1];parentRow.subRows.push(row);}}}}
-static filter(rows,histograms){const results=[];for(const row of rows){let filteredSubRows=[];if(row.subRows.length>0){filteredSubRows=HistogramSetHierarchy.filter(row.subRows,histograms);if(filteredSubRows.length===0)continue;}else{let found=false;for(const testHist of row.columns.values()){if(testHist instanceof tr.v.HistogramSet){for(const origHist of testHist){if(histograms.lookupHistogram(origHist.guid)!==undefined){found=true;break;}}
-if(found)break;continue;}
-if(!(testHist instanceof tr.v.Histogram)){throw new Error('Cells can only contain Histogram or HistogramSet');}
-if(histograms.lookupHistogram(testHist.guid)!==undefined){found=true;break;}
-const mergedFrom=testHist.diagnostics.get(tr.v.d.RESERVED_NAMES.MERGED_FROM);if(mergedFrom!==undefined){for(const[unusedName,origHist]of mergedFrom){if(histograms.lookupHistogram(origHist.guid)!==undefined){found=true;break;}}}
-if(found)break;}
-if(!found)continue;}
-const clone=new HistogramSetHierarchy(row.name);clone.description=row.description;clone.depth=row.depth;clone.subRows=filteredSubRows;clone.columns=row.columns;results.push(clone);}
-return results;}}
-return{HistogramSetHierarchy,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-table-cell',created(){this.viewState_=undefined;this.rootListener_=this.onRootStateUpdate_.bind(this);this.row_=undefined;this.displayLabel_='';this.histogram_=undefined;this.histogramSpan_=undefined;this.overviewChart_=undefined;this.mwuResult_=undefined;},ready(){this.addEventListener('click',this.onClick_.bind(this));},attached(){if(this.row){this.row.rootViewState.addUpdateListener(this.rootListener_);}},detached(){this.row.rootViewState.removeUpdateListener(this.rootListener_);},updateMwu_(){const referenceHistogram=this.referenceHistogram;this.mwuResult_=undefined;if(!(this.histogram instanceof tr.v.Histogram))return;if(!this.histogram.canCompare(referenceHistogram))return;this.mwuResult_=tr.b.math.Statistics.mwu(this.histogram.sampleValues,referenceHistogram.sampleValues,this.row.rootViewState.alpha);},build(row,displayLabel,viewState){this.row_=row;this.displayLabel_=displayLabel;this.viewState_=viewState;this.histogram_=this.row.columns.get(displayLabel);if(this.viewState){this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));}
+static buildInternal_(histogramArrayMap,hierarchy,rootRows){for(const[name,histograms]of histogramArrayMap){if(histograms instanceof Array){for(const histogram of histograms){HistogramSetHierarchy.mergeHistogramDownHierarchy_(histogram,hierarchy,name);}}else if(histograms instanceof Map){const row=new HistogramSetHierarchy(name);row.depth=hierarchy.length;hierarchy.push(row);HistogramSetHierarchy.buildInternal_(histograms,hierarchy,rootRows);hierarchy.pop();if(hierarchy.length===0){rootRows.push(row);}else{const parentRow=hierarchy[hierarchy.length-1];parentRow.subRows.push(row);}}}}}
+return{HistogramSetHierarchy};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-table-cell',created(){this.viewState_=undefined;this.rootListener_=this.onRootStateUpdate_.bind(this);this.row_=undefined;this.displayLabel_='';this.histogram_=undefined;this.histogramSpan_=undefined;this.overviewChart_=undefined;this.mwuResult_=undefined;},ready(){this.addEventListener('click',this.onClick_.bind(this));},attached(){if(this.row){this.row.rootViewState.addUpdateListener(this.rootListener_);}},detached(){this.row.rootViewState.removeUpdateListener(this.rootListener_);},updateMwu_(){const referenceHistogram=this.referenceHistogram;this.mwuResult_=undefined;if(!(this.histogram instanceof tr.v.Histogram))return;if(!this.histogram.canCompare(referenceHistogram))return;this.mwuResult_=tr.b.math.Statistics.mwu(this.histogram.sampleValues,referenceHistogram.sampleValues,this.row.rootViewState.alpha);},build(row,displayLabel,viewState){this.row_=row;this.displayLabel_=displayLabel;this.viewState_=viewState;this.histogram_=this.row.columns.get(displayLabel);if(this.viewState){this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));}
this.row.viewState.addUpdateListener(this.onRowStateUpdate_.bind(this));if(this.isAttached){this.row.rootViewState.addUpdateListener(this.rootListener_);}
this.updateMwu_();this.updateContents_();},updateSignificance_(){if(!this.mwuResult_)return;this.$.scalar.significance=this.mwuResult_.significance;},get viewState(){return this.viewState_;},get row(){return this.row_;},get histogram(){return this.histogram_;},get referenceHistogram(){const referenceDisplayLabel=this.row.rootViewState.referenceDisplayLabel;if(!referenceDisplayLabel)return undefined;if(referenceDisplayLabel===this.displayLabel_)return undefined;return this.row.columns.get(referenceDisplayLabel);},get isHistogramOpen(){return(this.histogramSpan_!==undefined)&&(this.$.histogram.style.display==='block');},set isHistogramOpen(open){if(!(this.histogram instanceof tr.v.Histogram)||(this.histogram.numValues===0)){return;}
this.$.scalar.style.display=open?'none':'flex';this.$.open_histogram.style.display=open?'none':'block';this.$.close_histogram.style.display=open?'block':'none';this.$.histogram.style.display=open?'block':'none';if(open&&this.histogramSpan_===undefined){this.histogramSpan_=document.createElement('tr-v-ui-histogram-span');this.histogramSpan_.viewState=this.viewState;this.histogramSpan_.rowState=this.row.viewState;this.histogramSpan_.rootState=this.row.rootViewState;this.histogramSpan_.build(this.histogram,this.referenceHistogram);this.$.histogram.appendChild(this.histogramSpan_);}
@@ -9893,53 +10326,71 @@ async restoreState(vs){await this.viewState.update({isExpanded:vs.isExpanded,isO
for(const row of this.subRows){const previousState=vs.subRows.get(row.name);if(!previousState)continue;await row.restoreState(previousState);}}
sortSubRows(){const sortColumn=this.baseTable_.tableColumns[this.rootViewState_.sortColumnIndex];if(sortColumn===undefined)return;this.subRows_.sort(sortColumn.cmp);if(this.rootViewState_.sortDescending){this.subRows_.reverse();}}}
return{HistogramSetTableRow,};});'use strict';tr.exportTo('tr.v.ui',function(){const MIDLINE_HORIZONTAL_ELLIPSIS=String.fromCharCode(0x22ef);function escapeRegExp(str){return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,'\\$&');}
-Polymer({is:'tr-v-ui-histogram-set-table',created(){this.viewState_=undefined;this.progress_=()=>Promise.resolve();this.nameColumnTitle_=undefined;this.displayLabels_=[];this.histograms_=undefined;this.sourceHistograms_=undefined;this.groupedHistograms_=undefined;this.hierarchies_=undefined;this.tableRows_=undefined;this.sortColumnChangedListener_=e=>this.onSortColumnChanged_(e);},ready(){this.$.table.zebra=true;this.addEventListener('sort-column-changed',this.sortColumnChangedListener_);this.addEventListener('requestSelectionChange',this.onRequestSelectionChange_.bind(this));this.addEventListener('row-expanded-changed',this.onRowExpandedChanged_.bind(this));},get viewState(){return this.viewState_;},set viewState(vs){if(this.viewState_){throw new Error('viewState must be set exactly once.');}
-this.viewState_=vs;this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));},get histograms(){return this.histograms_;},async build(histograms,sourceHistograms,displayLabels,opt_progress){this.histograms_=histograms;this.sourceHistograms_=sourceHistograms;this.groupedHistograms_=undefined;this.displayLabels_=displayLabels;if(opt_progress!==undefined)this.progress_=opt_progress;if(histograms.length===0){throw new Error('histogram-set-table requires non-empty HistogramSet.');}
+Polymer({is:'tr-v-ui-histogram-set-table',created(){this.viewState_=undefined;this.progress_=()=>Promise.resolve();this.nameColumnTitle_=undefined;this.displayLabels_=[];this.histograms_=undefined;this.sourceHistograms_=undefined;this.filteredHistograms_=undefined;this.groupedHistograms_=undefined;this.hierarchies_=undefined;this.tableRows_=undefined;this.sortColumnChangedListener_=e=>this.onSortColumnChanged_(e);},ready(){this.$.table.zebra=true;this.addEventListener('sort-column-changed',this.sortColumnChangedListener_);this.addEventListener('requestSelectionChange',this.onRequestSelectionChange_.bind(this));this.addEventListener('row-expanded-changed',this.onRowExpandedChanged_.bind(this));},get viewState(){return this.viewState_;},set viewState(vs){if(this.viewState_){throw new Error('viewState must be set exactly once.');}
+this.viewState_=vs;this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));},get histograms(){return this.histograms_;},async build(histograms,sourceHistograms,displayLabels,opt_progress){this.histograms_=histograms;this.sourceHistograms_=sourceHistograms;this.filteredHistograms_=undefined;this.groupedHistograms_=undefined;this.displayLabels_=displayLabels;if(opt_progress!==undefined)this.progress_=opt_progress;if(histograms.length===0){throw new Error('histogram-set-table requires non-empty HistogramSet.');}
await this.progress_('Building columns...');this.$.table.tableColumns=[{title:this.buildNameColumnTitle_(),value:row=>row.nameCell,cmp:(a,b)=>a.compareNames(b),}].concat(displayLabels.map(l=>this.buildColumn_(l)));tr.b.Timing.instant('histogram-set-table','columnCount',this.$.table.tableColumns.length);await this.updateContents_();this.fire('display-ready');this.progress_=()=>Promise.resolve();this.checkNameColumnOverflow_(tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows));},buildNameColumnTitle_(){this.nameColumnTitle_=document.createElement('span');this.nameColumnTitle_.style.display='inline-flex';const nameEl=document.createElement('span');nameEl.textContent='Name';this.nameColumnTitle_.appendChild(nameEl);const toggleWidthEl=document.createElement('span');toggleWidthEl.style.fontWeight='bold';toggleWidthEl.style.background='#bbb';toggleWidthEl.style.color='#333';toggleWidthEl.style.padding='0px 3px';toggleWidthEl.style.marginRight='8px';toggleWidthEl.style.display='none';toggleWidthEl.textContent=MIDLINE_HORIZONTAL_ELLIPSIS;toggleWidthEl.addEventListener('click',this.toggleNameColumnWidth_.bind(this));this.nameColumnTitle_.appendChild(toggleWidthEl);return this.nameColumnTitle_;},toggleNameColumnWidth_(opt_event){this.viewState.update({constrainNameColumn:!this.viewState.constrainNameColumn,});if(opt_event!==undefined){opt_event.stopPropagation();opt_event.preventDefault();tr.b.Timing.instant('histogram-set-table','nameColumn'+
-(this.viewState.constrainNameColumn?'Constrained':'Unconstrained'));}},buildColumn_(displayLabel){const title=document.createElement('span');title.textContent=displayLabel;title.style.whiteSpace='pre';return{displayLabel,title,value:row=>row.getCell(displayLabel),cmp:(rowA,rowB)=>rowA.compareCells(rowB,displayLabel),};},async updateContents_(){if(this.groupedHistograms_===undefined){await this.progress_('Grouping Histograms...');this.groupHistograms_();}
-if(this.hierarchies_===undefined){await this.progress_('Merging Histograms...');this.hierarchies_=tr.v.HistogramSetHierarchy.build(this.groupedHistograms_);this.tableRows_=undefined;}
-const tableRowsDirty=this.tableRows_===undefined;const previousRowStates=this.viewState.tableRowStates;if(tableRowsDirty){await this.progress_('Filtering rows...');let filteredHistograms=this.viewState.showAll?this.histograms:this.sourceHistograms_;if(this.viewState.searchQuery){let query=undefined;try{query=new RegExp(this.viewState.searchQuery);}catch(e){}
-if(query!==undefined){filteredHistograms=new tr.v.HistogramSet([...filteredHistograms].filter(hist=>hist.name.match(query)));if(filteredHistograms.length===0&&!this.viewState.showAll){await this.viewState.update({showAll:true});return;}}}
-const filteredHierarchies=tr.v.HistogramSetHierarchy.filter(this.hierarchies_,filteredHistograms);this.tableRows_=filteredHierarchies.map(hierarchy=>new tr.v.ui.HistogramSetTableRow(hierarchy,this.$.table,this.viewState));tr.b.Timing.instant('histogram-set-table','rootRowCount',this.tableRows_.length);const namesToRowStates=new Map();for(const row of this.tableRows_){namesToRowStates.set(row.name,row.viewState);}
+(this.viewState.constrainNameColumn?'Constrained':'Unconstrained'));}},buildColumn_(displayLabel){const title=document.createElement('span');title.textContent=displayLabel;title.style.whiteSpace='pre';return{displayLabel,title,value:row=>row.getCell(displayLabel),cmp:(rowA,rowB)=>rowA.compareCells(rowB,displayLabel),};},async updateContents_(){const previousRowStates=this.viewState.tableRowStates;if(!this.filteredHistograms_){await this.progress_('Filtering rows...');this.filteredHistograms_=this.viewState.showAll?this.histograms:this.sourceHistograms_;if(this.viewState.searchQuery){let query;try{query=new RegExp(this.viewState.searchQuery);}catch(e){}
+if(query!==undefined){this.filteredHistograms_=new tr.v.HistogramSet([...this.filteredHistograms_].filter(hist=>hist.name.match(query)));if(this.filteredHistograms_.length===0&&!this.viewState.showAll){await this.viewState.update({showAll:true});return;}}}
+this.groupedHistograms_=undefined;}
+if(!this.groupedHistograms_){await this.progress_('Grouping Histograms...');this.groupHistograms_();}
+if(!this.hierarchies_){await this.progress_('Merging Histograms...');this.hierarchies_=tr.v.HistogramSetHierarchy.build(this.groupedHistograms_);this.tableRows_=undefined;}
+const tableRowsDirty=this.tableRows_===undefined;if(tableRowsDirty){this.tableRows_=this.hierarchies_.map(hierarchy=>new tr.v.ui.HistogramSetTableRow(hierarchy,this.$.table,this.viewState));tr.b.Timing.instant('histogram-set-table','rootRowCount',this.tableRows_.length);const namesToRowStates=new Map();for(const row of this.tableRows_){namesToRowStates.set(row.name,row.viewState);}
await this.viewState.update({tableRowStates:namesToRowStates});}
await this.progress_('Configuring table...');this.nameColumnTitle_.children[1].style.filter=this.viewState.constrainNameColumn?'invert(100%)':'';const referenceDisplayLabelIndex=this.displayLabels_.indexOf(this.viewState.referenceDisplayLabel);this.$.table.selectedTableColumnIndex=(referenceDisplayLabelIndex<0)?undefined:(1+referenceDisplayLabelIndex);this.removeEventListener('sort-column-changed',this.sortColumnChangedListener_);this.$.table.sortColumnIndex=this.viewState.sortColumnIndex;this.$.table.sortDescending=this.viewState.sortDescending;this.addEventListener('sort-column-changed',this.sortColumnChangedListener_);if(tableRowsDirty){await this.progress_('Building DOM...');this.$.table.tableRows=this.tableRows_;for(const row of this.tableRows_){const previousState=previousRowStates.get(row.name);if(!previousState)continue;await row.restoreState(previousState);}}
this.$.table.rebuild();},async onRowExpandedChanged_(event){event.row.viewState.isExpanded=this.$.table.getExpandedForTableRow(event.row);tr.b.Timing.instant('histogram-set-table','row'+(event.row.viewState.isExpanded?'Expanded':'Collapsed'));if(this.nameColumnTitle_.children[1].style.display==='block')return;await tr.b.animationFrame();this.checkNameColumnOverflow_(event.row.subRows);},checkNameColumnOverflow_(rows){for(const row of rows){if(!row.nameCell.isOverflowing)continue;const[nameSpan,dots]=this.nameColumnTitle_.children;dots.style.display='block';const labelWidthPx=tr.v.ui.NAME_COLUMN_WIDTH_PX-
dots.getBoundingClientRect().width;nameSpan.style.width=labelWidthPx+'px';return;}},groupHistograms_(){const groupings=this.viewState.groupings.slice();groupings.push(tr.v.HistogramGrouping.DISPLAY_LABEL);function canSkipGrouping(grouping,groupedHistograms){if(groupedHistograms.size>1)return false;if(grouping.key===groupings[0].key)return false;if(grouping.key===tr.v.HistogramGrouping.DISPLAY_LABEL.key){return false;}
return true;}
-this.groupedHistograms_=this.histograms.groupHistogramsRecursively(groupings,canSkipGrouping);this.hierarchies_=undefined;},async onViewStateUpdate_(event){if(this.histograms_===undefined)return;if(event.delta.groupings!==undefined){this.groupedHistograms_=undefined;}
-if(event.delta.searchQuery!==undefined||event.delta.showAll!==undefined){this.tableRows_=undefined;}
+this.groupedHistograms_=this.filteredHistograms_.groupHistogramsRecursively(groupings,canSkipGrouping);this.hierarchies_=undefined;},async onViewStateUpdate_(event){if(this.histograms_===undefined)return;if(event.delta.searchQuery!==undefined||event.delta.showAll!==undefined){this.filteredHistograms_=undefined;}
+if(event.delta.groupings!==undefined){this.groupedHistograms_=undefined;}
if(event.delta.displayStatistic!==undefined&&this.$.table.sortColumnIndex>0){this.$.table.sortColumnIndex=undefined;}
if(event.delta.referenceDisplayLabel!==undefined||event.delta.displayStatisticName!==undefined){this.$.table.tableRows=this.$.table.tableRows;}
if(event.delta.tableRowStates){if(this.tableRows_.length!==this.viewState.tableRowStates.size){throw new Error('Only histogram-set-table may update tableRowStates');}
-for(const row of this.tableRows_){if(this.viewState.tableRowStates.get(row.name)!==row.viewState){throw new Error('Only histogram-set-table may update tableRowStates');}}}
+for(const row of this.tableRows_){if(this.viewState.tableRowStates.get(row.name)!==row.viewState){throw new Error('Only histogram-set-table may update tableRowStates');}}
+return;}
await this.updateContents_();},onSortColumnChanged_(event){tr.b.Timing.instant('histogram-set-table','sortColumn');this.viewState.update({sortColumnIndex:event.sortColumnIndex,sortDescending:event.sortDescending,});},onRequestSelectionChange_(event){if(event.selection instanceof tr.model.EventSet)return;event.stopPropagation();tr.b.Timing.instant('histogram-set-table','selectHistogramNames');let histogramNames=event.selection;histogramNames.sort();histogramNames=histogramNames.map(escapeRegExp).join('|');this.viewState.update({showAll:true,searchQuery:`^(${histogramNames})$`,});},get leafHistograms(){const histograms=new tr.v.HistogramSet();for(const row of
tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows)){if(row.subRows.length)continue;for(const hist of row.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;histograms.addHistogram(hist);}}
-return histograms;}});return{MIDLINE_HORIZONTAL_ELLIPSIS,};});'use strict';const COLORS=[['#FFD740','#FFC400','#FFAB00','#E29800'],['#FF6E40','#FF3D00','#DD2C00','#A32000'],['#40C4FF','#00B0FF','#0091EA','#006DAF'],['#89C641','#54B503','#4AA510','#377A0D'],['#B388FF','#7C4DFF','#651FFF','#6200EA'],['#FF80AB','#FF4081','#F50057','#C51162'],['#FFAB40','#FF9100','#FF6D00','#D65C02'],['#8C9EFF','#536DFE','#3D5AFE','#304FFE']];const METRICS=new Map([['Pipeline',['pipeline:begin_frame_transport','pipeline:begin_frame_to_frame_submission','pipeline:frame_submission_to_display','pipeline:draw']],['Thread',['thread_browser_cpu_time_per_frame','thread_display_compositor_cpu_time_per_frame','thread_GPU_cpu_time_per_frame','thread_IO_cpu_time_per_frame','thread_other_cpu_time_per_frame','thread_raster_cpu_time_per_frame','thread_renderer_compositor_cpu_time_per_frame','thread_renderer_main_cpu_time_per_frame']]]);const STATISTIC_KEY='statistic';Polymer({is:'tr-v-ui-metrics-visualization',created(){this.sortedPages_=new Map();this.displayLabels_=new Map();this.groups_=new Map();this.charts_=new Map();this.subMetricNames_=new Map();},build(leafHistograms,histograms){if(!leafHistograms||leafHistograms.length<1||!histograms||histograms.length<1){this.$.data_error.style.display='block';return;}
-this.histograms=histograms;for(const key of METRICS.keys()){const newAggregateChart=this.initializeColumnChart(key);Polymer.dom(this.$.container).appendChild(newAggregateChart);this.populateChart_(leafHistograms,key,newAggregateChart,true);newAggregateChart.toolTipCallBack=()=>this.openMetricsChart_(key);}
-if(this.groups_.size<1){this.$.data_error.style.display='block';return;}},populateChart_(histograms,metricName,chart,aggregate){const storiesGrouping=tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES);const benchmarkStartGrouping=tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START);const labels=new Map();const groups=new Map();for(const metric of METRICS.get(metricName)){const metricHistograms=histograms.getHistogramsNamed(metric);for(const histogram of metricHistograms){const benchmarkStart=benchmarkStartGrouping.callback(histogram);const page=storiesGrouping.callback(histogram);const displayLabel=tr.v.HistogramGrouping.DISPLAY_LABEL.callback(histogram);const average=histogram.average===undefined?0:histogram.average;labels.set(displayLabel,Date.parse(benchmarkStart));let pageMap=new Map();let labelMap=new Map();if(groups.get(page)===undefined){groups.set(page,pageMap);pageMap.set(displayLabel,labelMap);}else{pageMap=groups.get(page);if(pageMap.get(displayLabel)===undefined){pageMap.set(displayLabel,labelMap);}else{labelMap=pageMap.get(displayLabel);}}
-let metricMap=new Map();let statistic=new tr.b.math.RunningStatistics();if(labelMap.has(metric)){metricMap=labelMap.get(metric);statistic=metricMap.get(STATISTIC_KEY);}
-statistic.add(average);metricMap.set(STATISTIC_KEY,statistic);labelMap.set(metric,metricMap);const merged=new tr.v.d.DiagnosticMap();for(const bin of histogram.allBins){for(const map of bin.diagnosticMaps){merged.addDiagnostics(map);}}
-const subMetrics=[];if(merged.get('breakdown')===undefined){metricMap.set(metric,statistic);subMetrics.push(metric);}else{for(const[subMetric,total]of merged.get('breakdown')){let subStatistic=new tr.b.math.RunningStatistics();if(metricMap.has(subMetric)){subStatistic=metricMap.get(subMetric);}
-subStatistic.add(total);metricMap.set(subMetric,subStatistic);subMetrics.push(subMetric);}}
-const prevSubMetrics=this.subMetricNames_.get(metric);if(!prevSubMetrics||subMetrics.length>prevSubMetrics.length){this.subMetricNames_.set(metric,subMetrics);}}}
-const displayLabels=this.getSortedDisplayLabels_(labels);const sortedPages=[...groups.keys()].sort((a,b)=>this.sortGroups_(a,b,groups,displayLabels,METRICS.get(metricName)));this.setChartColors_(METRICS.get(metricName),displayLabels,chart);this.setChartSize_(groups.size,displayLabels.length,chart);this.setChartData_(groups,sortedPages,displayLabels,chart);let mapName=metricName;if(aggregate){mapName='Aggregate '+mapName;}
-this.groups_.set(mapName,groups);this.displayLabels_.set(mapName,displayLabels);this.sortedPages_.set(mapName,sortedPages);},getSortedDisplayLabels_(labels){return Array.from(labels.keys()).sort((a,b)=>labels.get(a)-labels.get(b));},sortGroups_(a,b,groups,displayLabels,mainMetricNames){let aValue=0;const aMap=groups.get(a);if(aMap.get(displayLabels[0])!==undefined){for(const metricName of mainMetricNames){const aMetricMap=aMap.get(displayLabels[0]).get(metricName);aValue+=aMetricMap.get(STATISTIC_KEY).mean;}}
-let bValue=0;const bMap=groups.get(b);if(bMap.get(displayLabels[0])!==undefined){for(const metricName of mainMetricNames){const bMetricMap=bMap.get(displayLabels[0]).get(metricName);bValue+=bMetricMap.get(STATISTIC_KEY).mean;}}
-if(aValue===bValue)return 0;return(aValue<bValue)?-1:1;},setChartData_(groups,sortedPages,displayLabels,chart){const chartData=[];for(const page of sortedPages){const pageMap=groups.get(page);for(const label of displayLabels){const data={x:label,group:page};if(!pageMap.has(label))continue;const labelMap=pageMap.get(label);for(const[metric,metricMap]of labelMap){const key=this.getSeriesKey_(metric,label);const mean=metricMap.get(STATISTIC_KEY).mean;data[key]=Math.round(mean*100)/100;if(label===displayLabels[0]){chart.getDataSeries(key).title=metric;}else{chart.getDataSeries(key).title='';}}
-chartData.push(data);}
+return histograms;}});return{MIDLINE_HORIZONTAL_ELLIPSIS,};});'use strict';tr.exportTo('tr.v.ui',function(){const PAGE_BREAKDOWN_KEY='pageBreakdown';Polymer({is:'tr-v-ui-metrics-visualization',created(){this.charts_=new Map();},ready(){this.$.start.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_();});this.$.end.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_();});this.$.search_page.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_();});},build(chartData){this.title_=chartData.title;this.aggregateData_=chartData.aggregate;this.data_=chartData.page;this.submetricsData_=chartData.submetrics;this.benchmarkCount_=chartData.aggregate.length;const aggregateChart=this.initializeColumnChart(this.title_);Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);this.charts_.set(tr.v.ui.AGGREGATE_KEY,aggregateChart);this.setChartColors_(tr.v.ui.AGGREGATE_KEY);aggregateChart.data=chartData.aggregate;this.setChartSize_(tr.v.ui.AGGREGATE_KEY);const newChart=this.initializeColumnChart(this.title_+' Breakdown');newChart.enableToolTip=true;newChart.toolTipCallBack=(rect)=>this.openChildChart_(rect);Polymer.dom(this.$.pageByPageContainer).appendChild(newChart);this.charts_.set(PAGE_BREAKDOWN_KEY,newChart);this.setChartColors_(PAGE_BREAKDOWN_KEY);newChart.data=this.data_;this.setChartSize_(PAGE_BREAKDOWN_KEY);},setChartSize_(page){const chart=this.charts_.get(page);const pageCount=chart.data.length;chart.graphHeight=tr.b.math.clamp(pageCount*20,400,600);chart.graphWidth=tr.b.math.clamp(pageCount*30,200,1000);},setChartColors_(page){const chart=this.charts_.get(page);const metrics=tr.v.ui.METRICS.get(this.title_);for(let i=0;i<this.benchmarkCount_;++i){for(let j=0;j<metrics.length;++j){const mainColorIndex=j%tr.v.ui.COLORS.length;const subColorIndex=i%tr.v.ui.COLORS[mainColorIndex].length;const color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];const series=metrics[j]+'-'+this.aggregateData_[i].x;chart.getDataSeries(series).color=color;if(i===0){chart.getDataSeries(series).title=metrics[j];}else{chart.getDataSeries(series).title='';}}}},initializeColumnChart(title){const newChart=new tr.ui.b.NameColumnChart();newChart.hideLegend=false;newChart.isStacked=true;newChart.yAxisLabel='ms';newChart.hideXAxis=true;newChart.displayXInHover=true;newChart.isGrouped=true;newChart.showTitleInLegend=true;newChart.chartTitle=title;newChart.titleHeight='14pt';return newChart;},initializeChildChart_(title,height,width){const div=document.createElement('div');div.classList.add('container');Polymer.dom(this.$.submetricsContainer).insertBefore(div,this.$.submetricsContainer.firstChild);const childChart=new tr.ui.b.NameBarChart();childChart.xAxisLabel='ms';childChart.chartTitle=title;childChart.graphHeight=height;childChart.graphWidth=width;childChart.titleHeight='14pt';childChart.isStacked=true;childChart.hideLegend=true;childChart.isGrouped=true;childChart.isWaterfall=true;div.appendChild(childChart);const button=this.initializeCloseButton_(div,this.$.submetricsContainer);div.appendChild(button);return childChart;},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},openChildChart_(rect){const metrics=tr.v.ui.METRICS.get(this.title_);let metric;let metricIndex;for(let i=0;i<metrics.length;++i){if(rect.key.startsWith(metrics[i])){metric=metrics[i];metricIndex=i;break;}}
+const page=rect.datum.group;const title=this.title_+' '+metric+': '+page;const submetrics=this.submetricsData_.get(page).get(metric);const width=tr.b.math.clamp(submetrics.size*150,300,700);const height=tr.b.math.clamp(submetrics.size*this.benchmarkCount_*50,300,700);const childChart=this.initializeChildChart_(title,height,width);childChart.data=this.processSubmetrics_(childChart,submetrics,0,metricIndex).data;},processSubmetrics_(chart,submetrics,hideValue,metricIndex){const finalData=[];let submetricIndex=0;for(const submetric of submetrics.values()){let benchmarkIndex=0;for(const benchmark of submetric.values()){benchmark.hide=!hideValue?0:hideValue;const series=benchmark.x+'-'+benchmark.group;const mainColorIndex=metricIndex%tr.v.ui.COLORS.length;const subColorIndex=benchmarkIndex%tr.v.ui.COLORS[mainColorIndex].length;chart.getDataSeries(series).color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];if(benchmarkIndex===(this.benchmarkCount_-1)){hideValue+=benchmark[series];}
+finalData.push(benchmark);benchmarkIndex++;}
+submetricIndex++;}
+return{data:finalData,hide:hideValue};},filterByPercentile_(){const startPercentile=this.$.start.value;const endPercentile=this.$.end.value;if(startPercentile===''||endPercentile==='')return;const length=this.data_.length/(this.benchmarkCount_+1);const startIndex=this.getPercentileIndex_(startPercentile,length);const endIndex=this.getPercentileIndex_(endPercentile,length);this.charts_.get(PAGE_BREAKDOWN_KEY).data=this.data_.slice(startIndex,endIndex);},getPercentileIndex_(percentile,arrayLength){const index=Math.ceil(arrayLength*(percentile/100.0));if(index===-1)return 0;if(index>=arrayLength)return arrayLength;return index*this.benchmarkCount_;},searchByPage_(){const criteria=this.$.search_page.value;if(criteria==='')return;const query=new RegExp(criteria);const filteredData=[...this.data_].filter(group=>{if(group.group)return group.group.match(query);return false;});if(filteredData.length<1){this.$.search_error.style.display='block';return;}
+const page=filteredData[0].group;const title=this.title_+' Breakdown: '+page;const metricToSubmetricMap=this.submetricsData_.get(page);let totalSubmetrics=0;for(const submetrics of metricToSubmetricMap.values()){for(const benchmark of submetrics.values()){totalSubmetrics+=benchmark.length;}}
+const width=tr.b.math.clamp(totalSubmetrics*150,300,700);const height=tr.b.math.clamp(totalSubmetrics*this.benchmarkCount_*30,300,700);const childChart=this.initializeChildChart_(title,height,width);const childData=[];let hide=0;let metricIndex=0;for(const submetrics of metricToSubmetricMap.values()){const submetricsData=this.processSubmetrics_(childChart,submetrics,hide,metricIndex);childData.push(...submetricsData.data);hide=submetricsData.hide;metricIndex++;}
+childChart.data=childData;},});});'use strict';Polymer({is:'tr-v-ui-raster-visualization',ready(){this.$.pageSelector.addEventListener('click',()=>{this.selectPage_();});this.$.search_page.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_();});this.$.search_button.addEventListener('click',()=>{this.searchByPage_();});},build(chartData){this.data_=chartData;const aggregateChart=this.createChart_('Aggregate Data by Run');Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);aggregateChart.enableToolTip=true;aggregateChart.toolTipCallBack=(rect)=>this.openBenchmarkChart_(rect);this.setChartColors_(aggregateChart,this.data_.get(tr.v.ui.AGGREGATE_KEY));aggregateChart.data=this.data_.get(tr.v.ui.AGGREGATE_KEY);this.setChartSize_(aggregateChart,this.data_.get(tr.v.ui.AGGREGATE_KEY).length);for(const page of this.data_.keys()){if(page===tr.v.ui.AGGREGATE_KEY)continue;const option=document.createElement('option');option.textContent=page;option.value=page;this.$.pageSelector.appendChild(option);}},setChartSize_(chart,pageCount,dataLength){chart.graphHeight=tr.b.math.clamp(pageCount*25,175,1000);chart.graphWidth=tr.b.math.clamp(pageCount*25,500,1000);},setChartColors_(chart,data){const metrics=new Map();let count=0;for(const thread of tr.v.ui.FRAME.values()){for(const metric of thread.keys()){metrics.set(metric,count);count++;}}
+for(let i=0;i<Math.floor(data.length/tr.v.ui.FRAME.length);++i){let j=0;for(const[threadName,thread]of tr.v.ui.FRAME.entries()){for(const metric of thread.keys()){let color='transparent';if(thread.get(metric)){const mainColorIndex=metrics.get(metric)%tr.v.ui.COLORS.length;const subColorIndex=i%tr.v.ui.COLORS[mainColorIndex].length;color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];}
+const series=metric+'-'+data[i*2+j].x+'-'+threadName;chart.getDataSeries(series).color=color;chart.getDataSeries(series).title=!i?metric:'';}
+j++;}}},createChart_(title){const newChart=new tr.ui.b.NameBarChart();newChart.chartTitle=title;newChart.xAxisLabel='ms';newChart.hideLegend=false;newChart.showTitleInLegend=true;newChart.hideYAxis=true;newChart.isStacked=true;newChart.displayXInHover=true;newChart.isGrouped=true;return newChart;},openBenchmarkChart_(rect){const benchmarkIndex=Math.floor(rect.index/tr.v.ui.FRAME.length);const title=rect.datum.x;const div=document.createElement('div');Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const chart=this.createChart_(title);div.appendChild(chart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const newDataSet=[];for(const page of this.data_.keys()){if(page===tr.v.ui.AGGREGATE_KEY)continue;for(let i=0;i<tr.v.ui.FRAME.length;i++){newDataSet.push(this.data_.get(page)[benchmarkIndex*tr.v.ui.FRAME.length+i]);}}
+this.setChartColors_(chart,newDataSet);chart.data=newDataSet;this.setChartSize_(chart,newDataSet.length);},selectPage_(){const div=document.createElement('div');const page=this.$.pageSelector.value;if(page==='')return;Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const pageChart=this.createChart_(page);div.appendChild(pageChart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const pageData=this.data_.get(page);this.setChartColors_(pageChart,pageData);pageChart.data=pageData;this.setChartSize_(pageChart,pageData.length);},searchByPage_(){const criteria=this.$.search_page.value;if(criteria==='')return;const query=new RegExp(criteria);const filteredData=[...this.data_.keys()].filter(page=>page.match(query));if(filteredData.length<1){this.$.search_error.style.display='block';return;}
+const page=filteredData[0];const div=document.createElement('div');Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const pageChart=this.createChart_(page);div.appendChild(pageChart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const pageData=this.data_.get(page);this.setChartColors_(pageChart,pageData);pageChart.data=pageData;this.setChartSize_(pageChart,pageData.length);},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},});'use strict';tr.exportTo('tr.v.ui',function(){const STATISTICS_KEY='statistics';const SUBMETRICS_KEY='submetrics';const AGGREGATE_KEY='aggregate';const RASTER_START_METRIC_KEY='pipeline:begin_frame_to_raster_start';const COLORS=[['#FFD740','#FFC400','#FFAB00','#E29800'],['#FF6E40','#FF3D00','#DD2C00','#A32000'],['#40C4FF','#00B0FF','#0091EA','#006DAF'],['#89C641','#54B503','#4AA510','#377A0D'],['#B388FF','#7C4DFF','#651FFF','#6200EA'],['#FF80AB','#FF4081','#F50057','#C51162'],['#FFAB40','#FF9100','#FF6D00','#D65C02'],['#8C9EFF','#536DFE','#3D5AFE','#304FFE']];const FRAME=[new Map([['pipeline:begin_frame_to_raster_start',false],['pipeline:begin_frame_to_raster_end',true]]),new Map([['pipeline:begin_frame_transport',true],['pipeline:begin_frame_to_frame_submission',true],['pipeline:frame_submission_to_display',true],['pipeline:draw',true]])];const METRICS=new Map([['Pipeline',['pipeline:begin_frame_transport','pipeline:begin_frame_to_frame_submission','pipeline:frame_submission_to_display','pipeline:draw']],['Thread',['thread_browser_cpu_time_per_frame','thread_display_compositor_cpu_time_per_frame','thread_GPU_cpu_time_per_frame','thread_IO_cpu_time_per_frame','thread_other_cpu_time_per_frame','thread_raster_cpu_time_per_frame','thread_renderer_compositor_cpu_time_per_frame','thread_renderer_main_cpu_time_per_frame']]]);function getValueFromMap(key,map){let retrievedValue=map.get(key);if(!retrievedValue){retrievedValue=new Map();map.set(key,retrievedValue);}
+return retrievedValue;}
+Polymer({is:'tr-v-ui-visualizations-data-container',created(){this.orderedBenchmarks_=[];this.groupedData_=new Map();},build(leafHistograms,histograms){if(!leafHistograms||leafHistograms.length<1||!histograms||histograms.length<1){this.$.data_error.style.display='block';return;}
+this.processHistograms_(this.groupHistograms_(histograms),this.groupHistograms_(leafHistograms));this.buildCharts_();},processHistograms_(histograms,leafHistograms){const benchmarkStartGrouping=tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START);const benchmarkToStartTime=new Map();for(const[metric,benchmarks]of histograms.entries()){for(const[benchmark,pages]of leafHistograms.get(metric).entries()){for(const[page,histograms]of pages.entries()){for(const histogram of histograms){const aggregateToBenchmarkMap=getValueFromMap(AGGREGATE_KEY,this.groupedData_);const benchmarkToMetricMap=getValueFromMap(benchmark,aggregateToBenchmarkMap);benchmarkToMetricMap.set(metric,new Map([[STATISTICS_KEY,histogram.running]]));}}}
+for(const[benchmark,pages]of benchmarks.entries()){for(const[page,histograms]of pages.entries()){for(const histogram of histograms){if(!benchmarkToStartTime.get(benchmark)){benchmarkToStartTime.set(benchmark,benchmarkStartGrouping.callback(histogram));}
+const pageToBenchmarkMap=getValueFromMap(page,this.groupedData_);const benchmarkToMetricMap=getValueFromMap(benchmark,pageToBenchmarkMap);const mergedSubmetrics=new tr.v.d.DiagnosticMap();for(const bin of histogram.allBins){for(const map of bin.diagnosticMaps){mergedSubmetrics.addDiagnostics(map);}}
+if(benchmarkToMetricMap.get(metric))continue;benchmarkToMetricMap.set(metric,new Map([[STATISTICS_KEY,histogram.running],[SUBMETRICS_KEY,mergedSubmetrics.get('breakdown')]]));}}}}
+this.orderedBenchmarks_=this.sortBenchmarks_(benchmarkToStartTime);},groupHistograms_(histograms){const groupings=[tr.v.HistogramGrouping.HISTOGRAM_NAME,tr.v.HistogramGrouping.DISPLAY_LABEL,tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES)];return histograms.groupHistogramsRecursively(groupings);},sortBenchmarks_(benchmarks){return Array.from(benchmarks.keys()).sort((a,b)=>{Date.parse(benchmarks.get(a))-Date.parse(benchmarks.get(b));});},getSeriesKey_(metric,benchmark){return metric+'-'+benchmark;},buildCharts_(){const rasterDataToBePassed=this.buildRasterChart_();this.$.rasterVisualization.build(rasterDataToBePassed);for(const chartName of METRICS.keys()){const metricsDataToBePassed=this.buildMetricsData_(chartName);const newChart=this.$.metricsVisualization.cloneNode(true);newChart.style.display='block';Polymer.dom(this.$.metrics_container).appendChild(newChart);newChart.build(metricsDataToBePassed);}},buildRasterChart_(){const orderedPages=[...this.groupedData_.keys()].filter((page)=>this.filterPagesWithoutRasterMetric_(page)).sort((a,b)=>this.sortByRasterStart_(a,b));const allChartData=new Map();for(const page of orderedPages){const pageMap=this.groupedData_.get(page);let chartData=[];for(const benchmark of this.orderedBenchmarks_){if(!pageMap.has(benchmark))continue;const benchmarkMap=pageMap.get(benchmark);const benchmarkData=[];if(benchmarkMap.get(RASTER_START_METRIC_KEY)===undefined){continue;}
+for(const[threadName,thread]of FRAME.entries()){const data={x:benchmark,hide:0};if(page!==AGGREGATE_KEY)data.group=page;let rasterBegin=0;for(const metric of thread.keys()){const metricMap=benchmarkMap.get(metric);const key=this.getSeriesKey_(metric,data.x+'-'+threadName);const stats=metricMap.get(STATISTICS_KEY);const mean=stats?stats.mean:0;let roundedMean=Math.round(mean*100)/100;if(metric===RASTER_START_METRIC_KEY){rasterBegin=roundedMean;}else if(metric==='pipeline:begin_frame_to_raster_end'){roundedMean-=rasterBegin;}
+data[key]=roundedMean;}
+benchmarkData.push(data);}
+chartData=chartData.concat(benchmarkData);}
+allChartData.set(page,chartData);}
+return allChartData;},buildMetricsData_(chartName){const orderedPages=[...this.groupedData_.keys()].sort((a,b)=>this.sortByTotal_(a,b,chartName));const chartData=[];const aggregateChart=[];for(const page of orderedPages){const pageMap=this.groupedData_.get(page);for(const benchmark of this.orderedBenchmarks_){if(!pageMap.has(benchmark))continue;const data={x:benchmark,group:page};const benchmarkMap=pageMap.get(benchmark);for(const metric of METRICS.get(chartName)){const metricMap=benchmarkMap.get(metric);const key=this.getSeriesKey_(metric,benchmark);const stats=metricMap.get(STATISTICS_KEY);const mean=stats?stats.mean:0;data[key]=Math.round(mean*100)/100;}
+if(page===AGGREGATE_KEY){aggregateChart.push(data);}else{chartData.push(data);}}
chartData.push({});}
-chart.data=chartData;},setChartSize_(pageCount,displayLabelCount,chart){chart.graphHeight=tr.b.math.clamp(pageCount*displayLabelCount*20,300,600);chart.graphWidth=tr.b.math.clamp(pageCount*displayLabelCount*25,500,1000);},setChartColors_(mainMetricNames,displayLabels,chart){for(let i=0;i<mainMetricNames.length;++i){const mainMetric=mainMetricNames[i];for(let j=0;j<displayLabels.length;++j){const mainColorIndex=i%COLORS.length;const subColorIndex=j%COLORS[mainColorIndex].length;const color=COLORS[mainColorIndex][subColorIndex];const displayLabel=displayLabels[j];const series=this.getSeriesKey_(mainMetric,displayLabel);chart.getDataSeries(series).color=color;}}},getSeriesKey_(metricName,displayLabel){return metricName+'-'+displayLabel;},initializeColumnChart(title){const newChart=new tr.ui.b.NameColumnChart();newChart.isStacked=true;newChart.yAxisLabel='ms';newChart.hideXAxis=true;newChart.displayXInHover=true;newChart.isGrouped=true;newChart.enableToolTip=true;newChart.showTitleInLegend=true;newChart.chartTitle=title;newChart.titleHeight='14pt';return newChart;},initializeChildChart_(title,height,width){const childChart=new tr.ui.b.NameBarChart();childChart.xAxisLabel='ms';childChart.chartTitle=title;childChart.graphHeight=height;childChart.graphWidth=width;childChart.titleHeight='14pt';childChart.isStacked=true;childChart.hideLegend=true;childChart.isGrouped=true;childChart.isWaterfall=true;return childChart;},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},initializeSelectors_(mainStep){const select=this.$.selectors.cloneNode(true);select.style.display='block';Polymer.dom(select).querySelector('#start').addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_(select,mainStep);});Polymer.dom(select).querySelector('#end').addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_(select,mainStep);});Polymer.dom(select).querySelector('#filter').addEventListener('click',()=>{this.filterByPercentile_(select,mainStep);});Polymer.dom(select).querySelector('#search_page').addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_(select,mainStep);});Polymer.dom(select).querySelector('#search').addEventListener('click',()=>{this.searchByPage_(select,mainStep);});return select;},openMetricsChart_(mainStep){const div=document.createElement('div');div.classList.add('child_container');Polymer.dom(this.$.container).appendChild(div);const selectors=this.initializeSelectors_(mainStep);div.appendChild(selectors);const childChart=this.initializeColumnChart(mainStep+' Breakdown');childChart.toolTipCallBack=(rect)=>this.openChildChart_(rect,mainStep);div.appendChild(childChart);const button=this.initializeCloseButton_(div,this.$.container);div.appendChild(button);this.populateChart_(this.histograms,mainStep,childChart,false);this.charts_.set(mainStep,childChart);},initializeChild_(title,height,width){const div=document.createElement('div');div.classList.add('child_container');Polymer.dom(this.$.children).insertBefore(div,this.$.children.firstChild);const childChart=this.initializeChildChart_(title,height,width);div.appendChild(childChart);const button=this.initializeCloseButton_(div,this.$.children);div.appendChild(button);return childChart;},openChildChart_(rect,metricName){let mainStep;let mainStepIndex;for(let i=0;i<METRICS.get(metricName).length;++i){if(rect.key.startsWith(METRICS.get(metricName)[i])){mainStep=METRICS.get(metricName)[i];mainStepIndex=i;break;}}
-const subSteps=this.subMetricNames_.get(mainStep);const width=tr.b.math.clamp(subSteps.length*150,300,700);const height=tr.b.math.clamp(subSteps.length*this.displayLabels_.get(metricName).length*50,300,700);const pageName=rect.datum.group;const title=mainStep+': '+pageName;const childChart=this.initializeChild_(title,height,width);const pageData=this.groups_.get(metricName).get(pageName);const subStepData=this.processSubStepData(childChart,mainStepIndex,mainStep,pageData,pageName,0);childChart.data=subStepData.childData;},processSubStepData(childChart,mainStepIndex,mainStep,pageData,pageName,total){const childData=[];const subSteps=this.subMetricNames_.get(mainStep);if(subSteps===undefined)return{childData,total};for(const subStep of subSteps){const currentTotal=total;let j=0;for(const[displayLabel,labelMap]of pageData){const data={x:subStep,hide:currentTotal,group:displayLabel};const metricMap=labelMap.get(mainStep);const series=this.getSeriesKey_(subStep,displayLabel);const mean=metricMap.get(subStep).mean;const roundedMean=Math.round(mean*100)/100;data[series]=roundedMean===undefined?0:roundedMean;childData.push(data);if(j===0)total+=data[series];else data.x='.';const subColorIndex=j%COLORS[mainStepIndex].length;const color=COLORS[mainStepIndex][subColorIndex];childChart.getDataSeries(series).color=color;j++;}
-childData.push({x:'.'});}
-return{childData,total};},filterByPercentile_(select,metricName){const startPercentile=Polymer.dom(select).querySelector('#start').value;const endPercentile=Polymer.dom(select).querySelector('#end').value;if(startPercentile===''||endPercentile==='')return;const length=this.sortedPages_.get(metricName).length;const startIndex=this.getPercentileIndex_(startPercentile,length);const endIndex=this.getPercentileIndex_(endPercentile,length);const slicedPages=this.sortedPages_.get(metricName).slice(startIndex,endIndex);this.setChartData_(this.groups_.get(metricName),slicedPages,this.displayLabels_.get(metricName),this.charts_.get(metricName));},getPercentileIndex_(percentile,arrayLength){const index=Math.ceil(arrayLength*(percentile/100.0));if(index===-1)return 0;if(index>=arrayLength)return arrayLength;return index;},searchByPage_(select,metricName){const criteria=Polymer.dom(select).querySelector('#search_page').value;if(criteria==='')return;const query=new RegExp(criteria);const filteredGroups=[...this.groups_.get(metricName)].filter(group=>group[0].match(query));if(filteredGroups.length<1){Polymer.dom(select).querySelector('#search_error').style.display='block';return;}
-Polymer.dom(select).querySelector('#search_error').style.display='none';const matchedPageName=filteredGroups[0][0];const match=this.groups_.get(metricName).get(matchedPageName);const title=metricName+' Breakdown: '+matchedPageName;let totalSteps=0;for(const[mainStep,subSteps]of this.subMetricNames_){totalSteps+=subSteps.length;}
-const width=tr.b.math.clamp(totalSteps*150,300,700);const height=tr.b.math.clamp(totalSteps*this.displayLabels_.get(metricName).length*30,300,700);const childChart=this.initializeChild_(title,height,width);const childData=[];let total=0;for(let i=0;i<METRICS.get(metricName).length;++i){const stepData=this.processSubStepData(childChart,i,METRICS.get(metricName)[i],match,matchedPageName,total);childData.push(...stepData.childData);total=stepData.total;}
-childChart.data=childData;},});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-view',listeners:{export:'onExport_',loadVisualization:'onLoadVisualization_'},created(){this.brushingStateController_=new tr.ui.NullBrushingStateController();this.viewState_=new tr.v.ui.HistogramSetViewState();this.metricsVisualizationLoaded_=false;},ready(){this.$.table.viewState=this.viewState;this.$.controls.viewState=this.viewState;},attached(){this.brushingStateController.parentController=tr.c.BrushingStateController.getControllerForElement(this.parentNode);},get brushingStateController(){return this.brushingStateController_;},get viewState(){return this.viewState_;},get histograms(){return this.$.table.histograms;},async build(histograms,opt_options){const options=opt_options||{};const progress=options.progress||(()=>Promise.resolve());if(options.helpHref)this.$.controls.helpHref=options.helpHref;if(options.feedbackHref){this.$.controls.feedbackHref=options.feedbackHref;}
+chartData.shift();return{title:chartName,aggregate:aggregateChart,page:chartData,submetrics:this.processSubmetricsData_(chartName)};},submetricsHelper_(submetric,value,benchmark,metricToSubmetricMap){let submetricToBenchmarkMap=metricToSubmetricMap.get(submetric);if(!submetricToBenchmarkMap){submetricToBenchmarkMap=[];metricToSubmetricMap.set(submetric,submetricToBenchmarkMap);}
+const data={x:submetric,hide:0,group:benchmark};const mean=value;const roundedMean=Math.round(mean*100)/100;if(!roundedMean)return;data[this.getSeriesKey_(submetric,benchmark)]=roundedMean;submetricToBenchmarkMap.push(data);},processSubmetricsData_(chartName){const submetrics=new Map();for(const[page,pageMap]of this.groupedData_.entries()){if(page===AGGREGATE_KEY)continue;const pageToMetricMap=getValueFromMap(page,submetrics);for(const benchmark of this.orderedBenchmarks_){const benchmarkMap=pageMap.get(benchmark);if(!benchmarkMap)continue;for(const metric of METRICS.get(chartName)){const metricMap=benchmarkMap.get(metric);const metricToSubmetricMap=getValueFromMap(metric,pageToMetricMap);const submetrics=metricMap.get(SUBMETRICS_KEY);if(!submetrics){this.submetricsHelper_(metric,metricMap.get(STATISTICS_KEY),benchmark,metricToSubmetricMap);continue;}
+for(const[submetric,value]of[...submetrics]){this.submetricsHelper_(submetric,value,benchmark,metricToSubmetricMap);}}}}
+return submetrics;},sortByTotal_(a,b,chartName){if(a===AGGREGATE_KEY)return-1;if(b===AGGREGATE_KEY)return 1;let aValue=0;const aMap=this.groupedData_.get(a);if(aMap.get(this.orderedBenchmarks_[0])!==undefined){for(const metric of METRICS.get(chartName)){const aMetricMap=aMap.get(this.orderedBenchmarks_[0]).get(metric);const aStats=aMetricMap.get(STATISTICS_KEY);aValue+=aStats?aStats.mean:0;}}
+let bValue=0;const bMap=this.groupedData_.get(b);if(bMap.get(this.orderedBenchmarks_[0])!==undefined){for(const metric of METRICS.get(chartName)){const bMetricMap=bMap.get(this.orderedBenchmarks_[0]).get(metric);const bStats=bMetricMap.get(STATISTICS_KEY);bValue+=bStats?bStats.mean:0;}}
+return aValue-bValue;},filterPagesWithoutRasterMetric_(page){const pageMap=this.groupedData_.get(page);for(const benchmark of this.orderedBenchmarks_){const pageMetricMap=pageMap.get(benchmark);if(!pageMetricMap)continue;const wantedMetric=pageMetricMap.get(RASTER_START_METRIC_KEY);if(wantedMetric!==undefined)return true;}
+return false;},sortByRasterStart_(a,b){if(a===AGGREGATE_KEY)return 1;if(b===AGGREGATE_KEY)return-1;let aValue=0;const aMap=this.groupedData_.get(a);if(aMap.get(this.orderedBenchmarks_[0])!==undefined){const aMetricMap=aMap.get(this.orderedBenchmarks_[0]).get(RASTER_START_METRIC_KEY);const aStats=aMetricMap.get(STATISTICS_KEY);aValue=aStats?aStats.mean:0;}
+let bValue=0;const bMap=this.groupedData_.get(b);if(bMap.get(this.orderedBenchmarks_[0])!==undefined){const bMetricMap=bMap.get(this.orderedBenchmarks_[0]).get(RASTER_START_METRIC_KEY);const bStats=bMetricMap.get(STATISTICS_KEY);bValue=bStats?bStats.mean:0;}
+return bValue-aValue;},});return{STATISTICS_KEY,SUBMETRICS_KEY,AGGREGATE_KEY,COLORS,FRAME,METRICS,getValueFromMap,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-view',listeners:{export:'onExport_',loadVisualization:'onLoadVisualization_'},created(){this.brushingStateController_=new tr.ui.NullBrushingStateController();this.viewState_=new tr.v.ui.HistogramSetViewState();this.visualizationLoaded_=false;},ready(){this.$.table.viewState=this.viewState;this.$.controls.viewState=this.viewState;},attached(){this.brushingStateController.parentController=tr.c.BrushingStateController.getControllerForElement(this.parentNode);},get brushingStateController(){return this.brushingStateController_;},get viewState(){return this.viewState_;},get histograms(){return this.$.table.histograms;},async build(histograms,opt_options){const options=opt_options||{};const progress=options.progress||(()=>Promise.resolve());if(options.helpHref)this.$.controls.helpHref=options.helpHref;if(options.feedbackHref){this.$.controls.feedbackHref=options.feedbackHref;}
if(histograms===undefined||histograms.length===0){this.$.container.style.display='none';this.$.zero.style.display='block';this.style.display='block';return;}
this.$.zero.style.display='none';this.$.container.style.display='block';this.$.container.style.maxHeight=(window.innerHeight-16)+'px';const buildMark=tr.b.Timing.mark('histogram-set-view','build');await progress('Finding important Histograms...');const sourceHistogramsMark=tr.b.Timing.mark('histogram-set-view','sourceHistograms');const sourceHistograms=histograms.sourceHistograms;sourceHistogramsMark.end();this.$.controls.showAllEnabled=(sourceHistograms.length!==histograms.length);await progress('Collecting parameters...');const collectParametersMark=tr.b.Timing.mark('histogram-set-view','collectParameters');const parameterCollector=new tr.v.HistogramParameterCollector();parameterCollector.process(histograms);this.$.controls.baseStatisticNames=parameterCollector.statisticNames;this.$.controls.possibleGroupings=parameterCollector.possibleGroupings;const displayLabels=parameterCollector.labels;this.$.controls.displayLabels=displayLabels;collectParametersMark.end();const hist=[...histograms][0];const benchmarks=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARKS);let enable=false;if(benchmarks!==undefined&&benchmarks.length>0){for(const benchmark of benchmarks){if(benchmark.includes('rendering')){enable=true;break;}}}
this.$.controls.enableVisualization=enable;await this.$.table.build(histograms,sourceHistograms,displayLabels,progress);buildMark.end();},onExport_(event){const mark=tr.b.Timing.mark('histogram-set-view','export'+
(event.merged?'Merged':'Raw')+event.format.toUpperCase());const histograms=event.merged?this.$.table.leafHistograms:this.histograms;let blob;if(event.format==='csv'){const csv=new tr.v.CSVBuilder(histograms);csv.build();blob=new window.Blob([csv.toString()],{type:'text/csv'});}else if(event.format==='json'){blob=new window.Blob([JSON.stringify(histograms.asDicts())],{type:'text/json'});}else{throw new Error(`Unable to export format "${event.format}"`);}
-const path=window.location.pathname.split('/');const basename=path[path.length-1].split('.')[0]||'histograms';const anchor=document.createElement('a');anchor.download=`${basename}.${event.format}`;anchor.href=window.URL.createObjectURL(blob);anchor.click();mark.end();},onLoadVisualization_(event){if(!this.metricsVisualizationLoaded_){this.$.metrics.build(this.$.table.leafHistograms,this.histograms);this.metricsVisualizationLoaded_=true;}else if(this.$.metrics.style.display==='none'){this.$.metrics.style.display='block';}else{this.$.metrics.style.display='none';}},});return{};});'use strict';tr.exportTo('tr.ui',function(){Polymer({is:'tr-ui-sp-metrics-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.rangeOfInterest_=undefined;this.metricLatenciesMs_=[];this.metrics_=[];tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(function(m){if(m.constructor.name==='sampleMetric')return;this.metrics_.push({label:m.constructor.name,value:m.constructor.name});},this);this.metrics_.sort((x,y)=>x.label.localeCompare(y.label));this.settingsKey_='metrics-side-panel-metric-name';this.currentMetricName_='responsivenessMetric';const metricSelector=tr.ui.b.createSelector(this,'currentMetricName_',this.settingsKey_,this.currentMetricName_,this.metrics_);Polymer.dom(this.$.top_left_controls).appendChild(metricSelector);metricSelector.addEventListener('change',this.onMetricChange_.bind(this));this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.recomputeButton_=tr.ui.b.createButton('Recompute',this.onRecompute_,this);Polymer.dom(this.$.top_left_controls).appendChild(this.recomputeButton_);this.$.results.addEventListener('display-ready',()=>{this.$.results.style.display='';});},async build(model){this.model_=model;await this.updateContents_();},get metricLatencyMs(){return tr.b.math.Statistics.mean(this.metricLatenciesMs_);},onMetricChange_(){this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.metricLatenciesMs_=[];this.updateContents_();},onRecompute_(){this.updateContents_();},get textLabel(){return'Metrics';},supportsModel(m){if(!m){return{supported:false,reason:'No model available'};}
+const path=window.location.pathname.split('/');const basename=path[path.length-1].split('.')[0]||'histograms';const anchor=document.createElement('a');anchor.download=`${basename}.${event.format}`;anchor.href=window.URL.createObjectURL(blob);anchor.click();mark.end();},onLoadVisualization_(event){if(!this.visualizationLoaded_){this.$.visualizations.style.display='block';this.$.visualizations.build(this.$.table.leafHistograms,this.histograms);this.visualizationLoaded_=true;}else if(this.$.visualizations.style.display==='none'){this.$.visualizations.style.display='block';}else{this.$.visualizations.style.display='none';}},});return{};});'use strict';tr.exportTo('tr.ui',function(){Polymer({is:'tr-ui-sp-metrics-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.rangeOfInterest_=undefined;this.metricLatenciesMs_=[];this.metrics_=[];tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(function(m){if(m.constructor.name==='sampleMetric')return;this.metrics_.push({label:m.constructor.name,value:m.constructor.name});},this);this.metrics_.sort((x,y)=>x.label.localeCompare(y.label));this.settingsKey_='metrics-side-panel-metric-name';this.currentMetricName_='responsivenessMetric';const metricSelector=tr.ui.b.createSelector(this,'currentMetricName_',this.settingsKey_,this.currentMetricName_,this.metrics_);Polymer.dom(this.$.top_left_controls).appendChild(metricSelector);metricSelector.addEventListener('change',this.onMetricChange_.bind(this));this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.recomputeButton_=tr.ui.b.createButton('Recompute',this.onRecompute_,this);Polymer.dom(this.$.top_left_controls).appendChild(this.recomputeButton_);this.$.results.addEventListener('display-ready',()=>{this.$.results.style.display='';});},async build(model){this.model_=model;await this.updateContents_();},get metricLatencyMs(){return tr.b.math.Statistics.mean(this.metricLatenciesMs_);},onMetricChange_(){this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.metricLatenciesMs_=[];this.updateContents_();},onRecompute_(){this.updateContents_();},get textLabel(){return'Metrics';},supportsModel(m){if(!m){return{supported:false,reason:'No model available'};}
return{supported:true};},get model(){return this.model_;},set model(model){this.build(model);},get selection(){},set selection(_){},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){this.rangeOfInterest_=range;if(this.currentMetricTypeInfo_&&this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest){if((this.metricLatencyMs===undefined)||(this.metricLatencyMs<100)){this.updateContents_();}else{this.recomputeButton_.style.background='red';}}},async updateContents_(){Polymer.dom(this.$.error).textContent='';this.$.results.style.display='none';if(!this.model_){Polymer.dom(this.$.error).textContent='Missing model';return;}
const options={metrics:[this.currentMetricName_]};if(this.currentMetricTypeInfo_&&this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest&&this.rangeOfInterest&&!this.rangeOfInterest.isEmpty){options.rangeOfInterest=this.rangeOfInterest;}
const startDate=new Date();const addFailureCb=failure=>{Polymer.dom(this.$.error).textContent=failure.description;};const histograms=tr.metrics.runMetrics(this.model_,options,addFailureCb);this.metricLatenciesMs_.push(new Date()-startDate);while(this.metricLatenciesMs_.length>20){this.metricLatenciesMs_.shift();}
diff --git a/catapult/systrace/systrace/tracing_agents/atrace_agent.py b/catapult/systrace/systrace/tracing_agents/atrace_agent.py
index f699fc05..caf78f44 100644
--- a/catapult/systrace/systrace/tracing_agents/atrace_agent.py
+++ b/catapult/systrace/systrace/tracing_agents/atrace_agent.py
@@ -241,19 +241,28 @@ class AtraceAgent(tracing_agents.TracingAgent):
def _stop_collect_trace(self):
"""Stops atrace.
- Note that prior to Api 23, --async-stop may not actually stop tracing.
- Thus, this uses a fallback method of running a zero-length synchronous
- trace if tracing is still on."""
- result = self._device_utils.RunShellCommand(
- self._tracer_args + ['--async_stop'], raw_output=True,
- large_output=True, check_return=True, timeout=ADB_LARGE_OUTPUT_TIMEOUT)
- is_trace_enabled_file = '/sys/kernel/debug/tracing/tracing_on'
-
+ Note that prior to Api 23, --async-stop isn't working correctly. It
+ doesn't stop tracing and clears trace buffer before dumping it rendering
+ results unusable."""
if self._device_sdk_version < version_codes.MARSHMALLOW:
- if int(self._device_utils.ReadFile(is_trace_enabled_file)):
- # tracing was incorrectly left on, disable it
- self._device_utils.RunShellCommand(
- self._tracer_args + ['-t 0'], check_return=True)
+ is_trace_enabled_file = '/sys/kernel/debug/tracing/tracing_on'
+ # Stop tracing first so new data won't arrive while dump is performed (it
+ # may take a non-trivial time and tracing buffer may overflow).
+ self._device_utils.WriteFile(is_trace_enabled_file, '0')
+ result = self._device_utils.RunShellCommand(
+ self._tracer_args + ['--async_dump'], raw_output=True,
+ large_output=True, check_return=True,
+ timeout=ADB_LARGE_OUTPUT_TIMEOUT)
+ # Run synchronous tracing for 0 seconds to stop tracing, clear buffers
+ # and other state.
+ self._device_utils.RunShellCommand(
+ self._tracer_args + ['-t 0'], check_return=True)
+ else:
+ # On M+ --async_stop does everything necessary
+ result = self._device_utils.RunShellCommand(
+ self._tracer_args + ['--async_stop'], raw_output=True,
+ large_output=True, check_return=True,
+ timeout=ADB_LARGE_OUTPUT_TIMEOUT)
return result
diff --git a/catapult/systrace/systrace/tracing_agents/atrace_agent_unittest.py b/catapult/systrace/systrace/tracing_agents/atrace_agent_unittest.py
index 9ccc6e33..203e8469 100755
--- a/catapult/systrace/systrace/tracing_agents/atrace_agent_unittest.py
+++ b/catapult/systrace/systrace/tracing_agents/atrace_agent_unittest.py
@@ -16,6 +16,7 @@ from systrace.tracing_agents import atrace_agent
from devil.android import device_utils
from devil.android.sdk import intent
+from py_utils import tempfile_ext
DEVICE_SERIAL = 'AG8404EC0444AGC'
@@ -50,9 +51,7 @@ class AtraceAgentTest(unittest.TestCase):
devices = device_utils.DeviceUtils.HealthyDevices()
package_info = util.get_supported_browsers()['stable']
device = devices[0]
- output_file_name = util.generate_random_filename_for_test()
-
- try:
+ with tempfile_ext.TemporaryFileName() as output_file_name:
# Launch the browser before tracing.
device.StartActivity(
intent.Intent(activity=package_info.activity,
@@ -76,12 +75,7 @@ class AtraceAgentTest(unittest.TestCase):
# Verify results.
with open(output_file_name, 'r') as f:
full_trace = f.read()
- self.assertTrue('CPU#'in full_trace)
- except:
- raise
- finally:
- if os.path.exists(output_file_name):
- os.remove(output_file_name)
+ self.assertTrue('CPU#' in full_trace)
@decorators.HostOnlyTest
def test_construct_atrace_args(self):
diff --git a/catapult/systrace/systrace/tracing_agents/atrace_from_file_agent.py b/catapult/systrace/systrace/tracing_agents/atrace_from_file_agent.py
index 58ddb7a3..4765e73f 100644
--- a/catapult/systrace/systrace/tracing_agents/atrace_from_file_agent.py
+++ b/catapult/systrace/systrace/tracing_agents/atrace_from_file_agent.py
@@ -2,13 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import hashlib
import os
import re
import stat
import subprocess
import sys
-import urllib
+import urllib2
import py_utils
@@ -22,9 +21,6 @@ TRACE_START_REGEXP = r'TRACE\:'
# Text that ADB sends, but does not need to be displayed to the user.
ADB_IGNORE_REGEXP = r'^capturing trace\.\.\. done|^capturing trace\.\.\.'
-# Constants required for converting perfetto traces.
-LINUX_SHA1 = 'cd9dbc5c92ed0167245c4559bf1971bb21378928'
-MAC_SHA1 = 'aed4ad02da526a3f1e4f9df47d4989ae9305b30e'
T2T_OUTPUT = 'trace.systrace'
def try_create_agent(options):
@@ -42,34 +38,17 @@ def try_create_agent(options):
return False
def convert_perfetto_trace(in_file):
- t2t_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
- '../trace_to_text'))
- loaded_t2t = False
- if sys.platform.startswith('linux'):
- t2t_path += '-linux-' + LINUX_SHA1
- loaded_t2t = load_trace_to_text(t2t_path, 'linux', LINUX_SHA1)
- elif sys.platform.startswith('darwin'):
- t2t_path += '-mac-' + MAC_SHA1
- loaded_t2t = load_trace_to_text(t2t_path, 'mac', MAC_SHA1)
- if loaded_t2t:
- os.chmod(t2t_path, stat.S_IXUSR)
- return subprocess.call([t2t_path, 'systrace', in_file, T2T_OUTPUT]) == 0
- return False
-
-def load_trace_to_text(t2t_path, platform, sha_value):
- if not os.path.exists(t2t_path):
- with open(t2t_path, 'w') as t2t:
- url = ('https://storage.googleapis.com/chromium-telemetry/binary_dependencies/trace_to_text-'
- + platform + '-' + sha_value)
- return urllib.urlretrieve(url, t2t_path)
- os.chmod(t2t_path, stat.S_IRUSR)
- with open(t2t_path, 'rb') as t2t:
- existing_file_hash = hashlib.sha1(t2t.read()).hexdigest()
- if existing_file_hash != sha_value:
- print 'Hash of trace_to_text binary does not match.'
- os.remove(t2t_path)
- return False
- return True
+ traceconv_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ '../traceconv'))
+ try:
+ traceconv = urllib2.urlopen('https://get.perfetto.dev/traceconv')
+ with open(traceconv_path, 'w') as out:
+ out.write(traceconv.read())
+ except urllib2.URLError:
+ print 'Could not download traceconv to convert the Perfetto trace.'
+ sys.exit(1)
+ os.chmod(traceconv_path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
+ return subprocess.call([traceconv_path, 'systrace', in_file, T2T_OUTPUT]) == 0
def is_perfetto(from_file):
# Starts with a preamble for field ID=1 (TracePacket)
diff --git a/catapult/systrace/systrace/tracing_agents/atrace_from_file_agent_unittest.py b/catapult/systrace/systrace/tracing_agents/atrace_from_file_agent_unittest.py
index 610b5707..53e79438 100755
--- a/catapult/systrace/systrace/tracing_agents/atrace_from_file_agent_unittest.py
+++ b/catapult/systrace/systrace/tracing_agents/atrace_from_file_agent_unittest.py
@@ -8,10 +8,11 @@ import contextlib
import os
import unittest
+from py_utils import tempfile_ext
from systrace import decorators
from systrace import run_systrace
from systrace import update_systrace_trace_viewer
-from systrace import util
+
TEST_DIR = os.path.join(os.path.dirname(__file__), '..', 'test_data')
@@ -20,32 +21,29 @@ DECOMPRESSED_ATRACE_DATA = os.path.join(TEST_DIR,
'decompressed_atrace_data.txt')
NON_EXISTENT_DATA = os.path.join(TEST_DIR, 'THIS_FILE_DOES_NOT_EXIST.txt')
+
class AtraceFromFileAgentTest(unittest.TestCase):
@decorators.HostOnlyTest
def test_from_file(self):
update_systrace_trace_viewer.update(force_update=True)
self.assertTrue(os.path.exists(
update_systrace_trace_viewer.SYSTRACE_TRACE_VIEWER_HTML_FILE))
- output_file_name = util.generate_random_filename_for_test()
try:
- # use from-file to create a specific expected output
- run_systrace.main_impl(['./run_systrace.py',
- '--from-file',
- COMPRESSED_ATRACE_DATA,
- '-o',
- output_file_name])
- # and verify file contents
- with contextlib.nested(open(output_file_name, 'r'),
- open(DECOMPRESSED_ATRACE_DATA, 'r')) as (f1, f2):
- full_trace = f1.read()
- expected_contents = f2.read()
- self.assertTrue(expected_contents in full_trace)
- except:
- raise
+ with tempfile_ext.TemporaryFileName() as output_file_name:
+ # use from-file to create a specific expected output
+ run_systrace.main_impl(['./run_systrace.py',
+ '--from-file',
+ COMPRESSED_ATRACE_DATA,
+ '-o',
+ output_file_name])
+ # and verify file contents
+ with contextlib.nested(open(output_file_name, 'r'),
+ open(DECOMPRESSED_ATRACE_DATA, 'r')) as (f1, f2):
+ full_trace = f1.read()
+ expected_contents = f2.read()
+ self.assertTrue(expected_contents in full_trace)
finally:
os.remove(update_systrace_trace_viewer.SYSTRACE_TRACE_VIEWER_HTML_FILE)
- if os.path.exists(output_file_name):
- os.remove(output_file_name)
@decorators.HostOnlyTest
diff --git a/catapult/systrace/systrace/tracing_controller.py b/catapult/systrace/systrace/tracing_controller.py
index a40222c1..86f13104 100644
--- a/catapult/systrace/systrace/tracing_controller.py
+++ b/catapult/systrace/systrace/tracing_controller.py
@@ -281,7 +281,7 @@ def CreateAgentsWithConfig(options, modules):
class TracingControllerConfig(tracing_agents.TracingConfig):
def __init__(self, output_file, trace_time, write_json,
link_assets, asset_dir, timeout, collection_timeout,
- device_serial_number, target):
+ device_serial_number, target, trace_buf_size):
tracing_agents.TracingConfig.__init__(self)
self.output_file = output_file
self.trace_time = trace_time
@@ -292,6 +292,7 @@ class TracingControllerConfig(tracing_agents.TracingConfig):
self.collection_timeout = collection_timeout
self.device_serial_number = device_serial_number
self.target = target
+ self.trace_buf_size = trace_buf_size
def GetControllerConfig(options):
@@ -299,9 +300,10 @@ def GetControllerConfig(options):
options.write_json,
options.link_assets, options.asset_dir,
options.timeout, options.collection_timeout,
- options.device_serial_number, options.target)
+ options.device_serial_number, options.target,
+ options.trace_buf_size)
def GetChromeStartupControllerConfig(options):
return TracingControllerConfig(None, options.trace_time,
options.write_json, None, None, None, None,
- None, None)
+ None, None, options.trace_buf_size)
diff --git a/catapult/systrace/systrace/util.py b/catapult/systrace/systrace/util.py
index b13dd51f..c9571b6f 100644
--- a/catapult/systrace/systrace/util.py
+++ b/catapult/systrace/systrace/util.py
@@ -4,8 +4,6 @@
import optparse
import os
-import random
-import string
import sys
from devil.android.constants import chrome
@@ -95,18 +93,6 @@ def get_device_sdk_version():
return version
-def generate_random_filename_for_test():
- """Used for temporary files used in tests.
-
- Files created from 'NamedTemporaryFile' have inconsistent reuse support across
- platforms, so it's not guaranteed that they can be reopened. Since many tests
- communicate files via path, we typically use this method, as well as
- manual file removal."""
- name = ''.join(random.choice(string.ascii_uppercase +
- string.digits) for _ in range(10))
- return os.path.abspath(name)
-
-
def get_supported_browsers():
"""Returns the package names of all supported browsers."""
# Add aliases for backwards compatibility.