diff options
author | Wei Wang <wvw@google.com> | 2021-01-31 14:41:15 -0800 |
---|---|---|
committer | Wei Wang <wvw@google.com> | 2021-01-31 14:41:15 -0800 |
commit | 07a9f048f159df9fcedabcb0359ece38549aa8ce (patch) | |
tree | 4fae679f441b84389fa75886c45a246891176bba | |
parent | 01475bd1c746c98178fdc60cb665074e0b1c5e4c (diff) | |
download | chromium-trace-07a9f048f159df9fcedabcb0359ece38549aa8ce.tar.gz |
Update catapult to latest version (91735e2e6)
git log --oneline --no-merges c4d3ff474..91735e2e6 tracing systrace
91735e2e6 Rename webuiMetric to customMetric
7a253c40a [v8][wasm] Match compilation events by ID
7646ce870 [wasm] Add metric for WebAssembly sync compilation
9d5ec4692 Add CppGC events to v8 gc metrics
bb9414aff [tracing] Fix DOCUMENTATION_URLS reserved name in html
ae206b8b8 [trace-viewer] Speed up event histogram computation
de6e3a9d8 [trace-viewer] Fix displaying args when value is 0.
be9a4317e Fix typo and add quotes for better readability
92c771005 Revert "Reland "Switch to vpython version of mock""
f22b977bc Reland "Switch to vpython version of mock"
a4d2246a2 Add freezing / roughness to media telemetry tests
8b9cff42b Revert "Switch to vpython version of mock"
2c271ab27 Switch to vpython version of mock
e43bd0925 WebUI metric: Implement benchmark_value
4565794f5 Add ProcessCreateToApplicationStart metric to androidStartup
88efddc6a Implement the unified V8 and CppGC metric computation
5537c0394 PCScan: Add metrics for PCScan.
146912bb6 blink_gc_metric: Fix missing import.
759827265 Fix NaN that appears in RunningStatistics::meanlogs
a629d81fa Revert "Add .vpython file for histogram_proto.py."
cb4bb2088 Add .vpython file for histogram_proto.py.
2ed6fc040 atrace_agent: pass device_serial to get_tracing_path when possible.
0c019226a [tbmv2] Add a way to add alert groupings to histograms
80f68fb06 Remove uma_metric Subtract
6fe79c7c6 Fork WebView startup metric to use for WebLayer
b8b4d61dd Implement webuiMetric
da58605a6 Start using polyfill for tracing ui tests
888c27281 Fix some tracing UI tests under the polyfill
584ab4910 GN: Export tracing include directory.
2019c0bb9 Change :generate_about_tracing to be a python2_action.
703029135 Add a way to skip tests
87da8e01e Add msm gpu trace support
22b0de95c trace-viewer: Don't show warning bar for polyfill
982bf51c4 Add way to have a hidden container slice
cd48ca049 [uma metric] Restrict check for linear bins.
3fc3588cd [uma metric] Show the name of the metric on error.
b7c1c3f11 fix v8 sample processing in multiprocess context
504ee6e60 Revert "Reland #2 "Make Catapult build as a part of Chromium under Python 3.""
a989f948c Remove frame_lengths from frame_time metrics
c70f06e2c Reland #2 "Make Catapult build as a part of Chromium under Python 3."
7ad7a98bf Revert "Reland "Make Catapult build as a part of Chromium under Python 3.""
532e564f6 Reland "Make Catapult build as a part of Chromium under Python 3."
b494582b9 Revert "Make Catapult build as a part of Chromium under Python 3."
25c6e0901 Make Catapult build as a part of Chromium under Python 3.
1d8e2d5ac Include the first valid tab switch latency
cb190dce0 [rendering benchmark] Remove a noisy metric.
4e51400c4 [systrace] Show absolute timestamp for selected slices
69d93258d heap: Add epoch based metric for blink gc
9f3ce85ba heap: Add ServiceWorker threads to gc metrics.
Test: systrace
Bug: 178973505
Change-Id: Ic59e217c8969bd10e446836692fc2873c8a7399c
36 files changed, 1263 insertions, 460 deletions
diff --git a/UPSTREAM_REVISION b/UPSTREAM_REVISION index 2997d941..ab641bd2 100644 --- a/UPSTREAM_REVISION +++ b/UPSTREAM_REVISION @@ -1 +1 @@ -c4d3ff474abec0ece4c42552b25aea9b54ecc047 +91735e2e6775c098eb32840a8903e5a9111fad77 diff --git a/catapult/common/node_runner/node_runner/node_binaries.json b/catapult/common/node_runner/node_runner/node_binaries.json index d5e1cc5d..89a73eeb 100644 --- a/catapult/common/node_runner/node_runner/node_binaries.json +++ b/catapult/common/node_runner/node_runner/node_binaries.json @@ -9,19 +9,19 @@ "cloud_storage_hash": "27ad092b0ce59d2da32090a00f717f0c31e65240", "download_path": "bin/node/node-linux64.zip", "path_within_archive": "node-v10.14.1-linux-x64/bin/node", - "version_in_cs": "6.7.0" + "version_in_cs": "10.14.1" }, "mac_x86_64": { - "cloud_storage_hash": "1af7c221e530165af8a6ab8ff7ccb1f2dd54036d", + "cloud_storage_hash": "1bd87abe88492d52b366e97ae9404f082b34fd15", "download_path": "bin/node/node-mac64.zip", - "path_within_archive": "node-v6.7.0-darwin-x64/bin/node", - "version_in_cs": "6.7.0" + "path_within_archive": "node-v10.14.1-darwin-x64/bin/node", + "version_in_cs": "10.14.1" }, "win_AMD64": { - "cloud_storage_hash": "23f21bfb2edf874a8b6bdb6c1acb408bc7edeced", + "cloud_storage_hash": "f1162c6343dc6a3a1acecf76966d4c2acd17fc46", "download_path": "bin/node/node-win64.zip", - "path_within_archive": "node-v6.7.0-win-x64/node.exe", - "version_in_cs": "6.7.0" + "path_within_archive": "node-v10.14.1-win-x64/node.exe", + "version_in_cs": "10.14.1" } } }, @@ -30,22 +30,22 @@ "cloud_storage_bucket": "chromium-telemetry", "file_info": { "linux_x86_64": { - "cloud_storage_hash": "5750e968975e7f5ab8cb694f5e92a34a890e129d", + "cloud_storage_hash": "830b8f6761bf82a945b57facfb49925b579c471c", "download_path": "bin/node/npm-linux64.zip", - "path_within_archive": "node-v6.7.0-linux-x64/lib/node_modules/npm/bin/npm-cli.js", - "version_in_cs": "6.7.0" + "path_within_archive": "node-v10.14.1-linux-x64/lib/node_modules/npm/bin/npm-cli.js", + "version_in_cs": "10.14.1" }, "mac_x86_64": { - "cloud_storage_hash": "1af7c221e530165af8a6ab8ff7ccb1f2dd54036d", + "cloud_storage_hash": "1bd87abe88492d52b366e97ae9404f082b34fd15", "download_path": "bin/node/npm-mac64.zip", - "path_within_archive": "node-v6.7.0-darwin-x64/lib/node_modules/npm/bin/npm-cli.js", - "version_in_cs": "6.7.0" + "path_within_archive": "node-v10.14.1-darwin-x64/lib/node_modules/npm/bin/npm-cli.js", + "version_in_cs": "10.14.1" }, "win_AMD64": { - "cloud_storage_hash": "23f21bfb2edf874a8b6bdb6c1acb408bc7edeced", + "cloud_storage_hash": "f1162c6343dc6a3a1acecf76966d4c2acd17fc46", "download_path": "bin/node/npm-win64.zip", - "path_within_archive": "node-v6.7.0-win-x64\\node_modules\\npm\\bin\\npm-cli.js", - "version_in_cs": "6.7.0" + "path_within_archive": "node-v10.14.1-win-x64\\node_modules\\npm\\bin\\npm-cli.js", + "version_in_cs": "10.14.1" } } } diff --git a/catapult/common/node_runner/node_runner/package-lock.json b/catapult/common/node_runner/node_runner/package-lock.json index 683cae9e..2e8ef2a2 100644 --- a/catapult/common/node_runner/node_runner/package-lock.json +++ b/catapult/common/node_runner/node_runner/package-lock.json @@ -4,6 +4,157 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/generator": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", + "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", + "requires": { + "@babel/types": "^7.11.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + } + } + }, + "@babel/parser": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", + "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==" + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/types": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, "@chopsui/batch-iterator": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@chopsui/batch-iterator/-/batch-iterator-0.1.0.tgz", @@ -232,11 +383,83 @@ "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", "integrity": "sha1-jaXGUwkVZT86Hzj9XxAdjD+AecU=" }, + "@types/babel-generator": { + "version": "6.25.3", + "resolved": "https://registry.npmjs.org/@types/babel-generator/-/babel-generator-6.25.3.tgz", + "integrity": "sha512-pGgnuxVddKcYIc+VJkRDop7gxLhqclNKBdlsm/5Vp8d+37pQkkDK7fef8d9YYImRzw9xcojEPc18pUYnbxmjqA==", + "requires": { + "@types/babel-types": "*" + } + }, + "@types/babel-traverse": { + "version": "6.25.5", + "resolved": "https://registry.npmjs.org/@types/babel-traverse/-/babel-traverse-6.25.5.tgz", + "integrity": "sha512-WrMbwmu+MWf8FiUMbmVOGkc7bHPzndUafn1CivMaBHthBBoo0VNIcYk1KV71UovYguhsNOwf3UF5oRmkkGOU3w==", + "requires": { + "@types/babel-types": "*" + } + }, + "@types/babel-types": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.8.tgz", + "integrity": "sha512-jvu8g4LR7+p6ao30RhTREnEhHxmP4/R9D9/rOR/Kq14FztORty9SKgtOZUNZNMB9CXLxZ54EWu4dArUE8WdTsw==" + }, + "@types/babylon": { + "version": "6.16.5", + "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz", + "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==", + "requires": { + "@types/babel-types": "*" + } + }, + "@types/chai": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.12.tgz", + "integrity": "sha512-aN5IAC8QNtSUdQzxu7lGBgYAOuU1tmRU4c9dIq5OKGf/SBVjXo+ffM2wEjudAWbgpOhy60nLoAGH1xm8fpCKFQ==" + }, + "@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "requires": { + "@types/chai": "*" + } + }, + "@types/chalk": { + "version": "0.4.31", + "resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz", + "integrity": "sha1-ox10JBprHtu5c8822XooloNKUfk=" + }, "@types/clone": { "version": "0.1.30", "resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz", "integrity": "sha1-5zZWSMG0ITalnH1QQGN7O1yDthQ=" }, + "@types/cssbeautify": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@types/cssbeautify/-/cssbeautify-0.3.1.tgz", + "integrity": "sha1-jgvuj33suVIlDaDK6+BeMFkcF+8=" + }, + "@types/doctrine": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.1.tgz", + "integrity": "sha1-uZny2fe0PKvgoaLzm8IDvH3K2p0=" + }, + "@types/estree": { + "version": "0.0.45", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz", + "integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==" + }, + "@types/is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-byTuSHMdMRaOpRBhDW3RXl/Jxv8=" + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + }, "@types/node": { "version": "4.2.23", "resolved": "https://registry.npmjs.org/@types/node/-/node-4.2.23.tgz", @@ -257,6 +480,27 @@ } } }, + "@types/path-is-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/path-is-inside/-/path-is-inside-1.0.0.tgz", + "integrity": "sha512-hfnXRGugz+McgX2jxyy5qz9sB21LRzlGn24zlwN2KEgoPtEvjzNRrLtUkOOebPDPZl3Rq7ywKxYvylVcEZDnEw==" + }, + "@types/resolve": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.6.tgz", + "integrity": "sha512-g+Rg8uMWY76oYTyaL+m7ZcblqF/oj7pE6uEUyACluJx4zcop1Lk14qQiocdEkEVMDFm6DmKpxJhsER+ZuTwG3g==", + "requires": { + "@types/node": "*" + } + }, + "@types/whatwg-url": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-6.4.0.tgz", + "integrity": "sha512-tonhlcbQ2eho09am6RHnHOgvtDfDYINd5rgxD+2YSkKENooVCFsWizJz139MQW/PV8FfClyKrNe9ZbdHrSCxGg==", + "requires": { + "@types/node": "*" + } + }, "@webassemblyjs/ast": { "version": "1.7.10", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.10.tgz", @@ -632,6 +876,11 @@ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==" + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1317,6 +1566,14 @@ } } }, + "cancel-token": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/cancel-token/-/cancel-token-0.1.1.tgz", + "integrity": "sha1-wYGXZ0uxyEwdaTPr8V2NWlznm08=", + "requires": { + "@types/node": "^4.0.30" + } + }, "capture-stack-trace": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", @@ -1506,6 +1763,43 @@ "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", "integrity": "sha1-OeAF1Uav4B4B+cTKj6UPaGoBIF0=" }, + "command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "requires": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + } + }, + "command-line-usage": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-5.0.5.tgz", + "integrity": "sha512-d8NrGylA5oCXSbGoKz05FkehDAzSmIm4K03S5VDh4d5lZAtTWfc3D1RuETtuQCn8129nYfJfDdF7P/lwcz1BlA==", + "requires": { + "array-back": "^2.0.0", + "chalk": "^2.4.1", + "table-layout": "^0.4.3", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "requires": { + "typical": "^2.6.1" + } + }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" + } + } + }, "commander": { "version": "2.13.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", @@ -1725,6 +2019,11 @@ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" }, + "cssbeautify": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cssbeautify/-/cssbeautify-0.3.1.tgz", + "integrity": "sha1-Et0fc0A1wub6ymfcvc73TkKBE5c=" + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -2829,6 +3128,14 @@ "pkg-dir": "^2.0.0" } }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "requires": { + "array-back": "^3.0.1" + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -2958,8 +3265,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -2977,13 +3283,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2996,18 +3300,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -3110,8 +3411,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -3121,7 +3421,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3134,20 +3433,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3164,7 +3460,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3237,8 +3532,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -3248,7 +3542,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3324,8 +3617,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -3355,7 +3647,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3373,7 +3664,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3412,13 +3702,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -3808,6 +4096,11 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, + "indent": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/indent/-/indent-0.0.2.tgz", + "integrity": "sha1-jHnwgBkFWbaHA0uEx676l9WpEdk=" + }, "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", @@ -4342,6 +4635,11 @@ "graceful-fs": "^4.1.6" } }, + "jsonschema": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.6.tgz", + "integrity": "sha512-SqhURKZG07JyKKeo/ir24QnS4/BV7a6gQy93bUSe4lUdNp0QNpIz2c9elWJQ9dpc5cQYY6cvCzgRwy0MQCLyqA==" + }, "just-extend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", @@ -4544,11 +4842,26 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "integrity": "sha1-s56mIp72B+zYniyN8SU2iRysm40=" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -4629,6 +4942,14 @@ "yallist": "^2.1.2" } }, + "magic-string": { + "version": "0.22.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", + "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", + "requires": { + "vlq": "^0.2.2" + } + }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -5458,6 +5779,169 @@ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=" }, + "polymer-analyzer": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/polymer-analyzer/-/polymer-analyzer-3.2.4.tgz", + "integrity": "sha512-JmxUhMajTuC18tLXbTtu2+aN2x9bTX+4MvCD4IZKJ0rtAL8jWi1iRLfogpHJB4Ig9Dc8EEEuEYipLuzPFl3vqA==", + "requires": { + "@babel/generator": "^7.0.0-beta.42", + "@babel/traverse": "^7.0.0-beta.42", + "@babel/types": "^7.0.0-beta.42", + "@types/babel-generator": "^6.25.1", + "@types/babel-traverse": "^6.25.2", + "@types/babel-types": "^6.25.1", + "@types/babylon": "^6.16.2", + "@types/chai-subset": "^1.3.0", + "@types/chalk": "^0.4.30", + "@types/clone": "^0.1.30", + "@types/cssbeautify": "^0.3.1", + "@types/doctrine": "^0.0.1", + "@types/is-windows": "^0.2.0", + "@types/minimatch": "^3.0.1", + "@types/parse5": "^2.2.34", + "@types/path-is-inside": "^1.0.0", + "@types/resolve": "0.0.6", + "@types/whatwg-url": "^6.4.0", + "babylon": "^7.0.0-beta.42", + "cancel-token": "^0.1.1", + "chalk": "^1.1.3", + "clone": "^2.0.0", + "cssbeautify": "^0.3.1", + "doctrine": "^2.0.2", + "dom5": "^3.0.0", + "indent": "0.0.2", + "is-windows": "^1.0.2", + "jsonschema": "^1.1.0", + "minimatch": "^3.0.4", + "parse5": "^4.0.0", + "path-is-inside": "^1.0.2", + "resolve": "^1.5.0", + "shady-css-parser": "^0.1.0", + "stable": "^0.1.6", + "strip-indent": "^2.0.0", + "vscode-uri": "=1.0.6", + "whatwg-url": "^6.4.0" + }, + "dependencies": { + "@types/babel-types": { + "version": "6.25.2", + "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-6.25.2.tgz", + "integrity": "sha512-+3bMuktcY4a70a0KZc8aPJlEOArPuAKQYHU5ErjkOqGJdx8xuEEVK6nWogqigBOJ8nKPxRpyCUDTCPmZ3bUxGA==" + }, + "@types/parse5": { + "version": "2.2.34", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-2.2.34.tgz", + "integrity": "sha1-44cKEOgnNacg9i1x3NGDunjvOp0=", + "requires": { + "@types/node": "*" + } + }, + "babylon": { + "version": "7.0.0-beta.47", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", + "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "dom5": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dom5/-/dom5-3.0.1.tgz", + "integrity": "sha512-JPFiouQIr16VQ4dX6i0+Hpbg3H2bMKPmZ+WZgBOSSvOPx9QHwwY8sPzeM2baUtViESYto6wC2nuZOMC/6gulcA==", + "requires": { + "@types/parse5": "^2.2.34", + "clone": "^2.1.0", + "parse5": "^4.0.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "polymer-bundler": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/polymer-bundler/-/polymer-bundler-4.0.10.tgz", + "integrity": "sha512-nwlN3LQlQDqbZ2sUH3394C/dHZUDHq8tpdS5HARvPDb0Q9IXWD+znOR1cr7wSjF0EZN4LiUH5hWyUoV4QSjhpQ==", + "requires": { + "@types/babel-generator": "^6.25.1", + "@types/babel-traverse": "^6.25.3", + "babel-generator": "^6.26.1", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "clone": "^2.1.0", + "command-line-args": "^5.0.2", + "command-line-usage": "^5.0.5", + "dom5": "^3.0.0", + "espree": "^3.5.2", + "magic-string": "^0.22.4", + "mkdirp": "^0.5.1", + "parse5": "^4.0.0", + "polymer-analyzer": "^3.2.2", + "rollup": "^1.3.0", + "source-map": "^0.5.6", + "vscode-uri": "=1.0.6" + }, + "dependencies": { + "@types/parse5": { + "version": "2.2.34", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-2.2.34.tgz", + "integrity": "sha1-44cKEOgnNacg9i1x3NGDunjvOp0=", + "requires": { + "@types/node": "*" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "dom5": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dom5/-/dom5-3.0.1.tgz", + "integrity": "sha512-JPFiouQIr16VQ4dX6i0+Hpbg3H2bMKPmZ+WZgBOSSvOPx9QHwwY8sPzeM2baUtViESYto6wC2nuZOMC/6gulcA==", + "requires": { + "@types/parse5": "^2.2.34", + "clone": "^2.1.0", + "parse5": "^4.0.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -5745,6 +6229,11 @@ "strip-indent": "^2.0.0" } }, + "reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=" + }, "redux": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz", @@ -5896,6 +6385,23 @@ "inherits": "^2.0.1" } }, + "rollup": { + "version": "1.32.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.32.1.tgz", + "integrity": "sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A==", + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==" + } + } + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -6033,6 +6539,11 @@ "safe-buffer": "^5.0.1" } }, + "shady-css-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/shady-css-parser/-/shady-css-parser-0.1.0.tgz", + "integrity": "sha512-irfJUUkEuDlNHKZNAp2r7zOyMlmbfVJ+kWSfjlCYYUx/7dJnANLCyTzQZsuxy5NJkvtNwSxY5Gj8MOlqXUQPyA==" + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -6325,6 +6836,11 @@ "safe-buffer": "^5.1.1" } }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -6471,6 +6987,33 @@ "string-width": "^2.1.1" } }, + "table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "requires": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "requires": { + "typical": "^2.6.1" + } + }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" + } + } + }, "tapable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", @@ -6587,6 +7130,14 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=" }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + } + }, "trim-newlines": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", @@ -6634,6 +7185,11 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==" + }, "uglify-es": { "version": "3.3.9", "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", @@ -6880,6 +7436,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==" + }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -6893,6 +7454,11 @@ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" }, + "vscode-uri": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz", + "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==" + }, "vulcanize": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/vulcanize/-/vulcanize-1.16.0.tgz", @@ -6923,6 +7489,11 @@ "defaults": "^1.0.3" } }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, "webpack": { "version": "4.23.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.23.1.tgz", @@ -7067,6 +7638,16 @@ "source-map": "~0.6.1" } }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -7088,6 +7669,22 @@ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, + "wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "requires": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "dependencies": { + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" + } + } + }, "worker-farm": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", diff --git a/catapult/common/py_utils/py_utils/chrome_binaries.json b/catapult/common/py_utils/py_utils/chrome_binaries.json index badb3642..03f0afd3 100644 --- a/catapult/common/py_utils/py_utils/chrome_binaries.json +++ b/catapult/common/py_utils/py_utils/chrome_binaries.json @@ -12,16 +12,16 @@ "version_in_cs": "85.0.4169.0" }, "win_AMD64": { - "cloud_storage_hash": "c0b02f47afb6bacdd8d12eda6f03488583404b60", + "cloud_storage_hash": "121271e6e917886bd2e5b539dd643e74a3aae395", "download_path": "bin\\reference_build\\chrome-win64-clang.zip", "path_within_archive": "chrome-win64-clang\\chrome.exe", - "version_in_cs": "85.0.4169.0" + "version_in_cs": "86.0.4240.111" }, "win_x86": { - "cloud_storage_hash": "5879958eda4edc5b0eaffeda4c7369a07937af73", + "cloud_storage_hash": "83e9d11b28d01c10bbcccb7b882288b192b5e756", "download_path": "bin\\reference_build\\chrome-win32-clang.zip", "path_within_archive": "chrome-win32-clang\\chrome.exe", - "version_in_cs": "85.0.4169.0" + "version_in_cs": "86.0.4240.111" } } }, @@ -169,4 +169,4 @@ } } } -}
\ No newline at end of file +} diff --git a/catapult/common/py_utils/py_utils/cloud_storage.py b/catapult/common/py_utils/py_utils/cloud_storage.py index a359a065..919add69 100644 --- a/catapult/common/py_utils/py_utils/cloud_storage.py +++ b/catapult/common/py_utils/py_utils/cloud_storage.py @@ -192,10 +192,33 @@ def IsNetworkIOEnabled(): return disable_cloud_storage_env_val != '1' -def List(bucket): - query = 'gs://%s/' % bucket - stdout = _RunCommand(['ls', query]) - return [url[len(query):] for url in stdout.splitlines()] +def List(bucket, prefix=None): + """Returns all paths matching the given prefix in bucket. + + Returned paths are relative to the bucket root. + If path is given, 'gsutil ls gs://<bucket>/<path>' will be executed, otherwise + 'gsutil ls gs://<bucket>' will be executed. + + For more details, see: + https://cloud.google.com/storage/docs/gsutil/commands/ls#directory-by-directory,-flat,-and-recursive-listings + + Args: + bucket: Name of cloud storage bucket to look at. + prefix: Path within the bucket to filter to. + + Returns: + A list of files. All returned path are relative to the bucket root + directory. For example, List('my-bucket', path='foo/') will returns results + of the form ['/foo/123', '/foo/124', ...], as opposed to ['123', '124', + ...]. + """ + bucket_prefix = 'gs://%s' % bucket + if prefix is None: + full_path = bucket_prefix + else: + full_path = '%s/%s' % (bucket_prefix, prefix) + stdout = _RunCommand(['ls', full_path]) + return [url[len(bucket_prefix):] for url in stdout.splitlines()] def ListDirs(bucket, path=''): diff --git a/catapult/common/py_utils/py_utils/cloud_storage_unittest.py b/catapult/common/py_utils/py_utils/cloud_storage_unittest.py index 2e663a76..afd03945 100644 --- a/catapult/common/py_utils/py_utils/cloud_storage_unittest.py +++ b/catapult/common/py_utils/py_utils/cloud_storage_unittest.py @@ -171,6 +171,24 @@ class CloudStorageFakeFsUnitTest(BaseFakeFsUnitTest): cloud_storage._RunCommand = orig_run_command @mock.patch('py_utils.cloud_storage._RunCommand') + def testListNoPrefix(self, mock_run_command): + mock_run_command.return_value = '\n'.join(['gs://bucket/foo-file.txt', + 'gs://bucket/foo1/', + 'gs://bucket/foo2/']) + + self.assertEqual(cloud_storage.List('bucket'), + ['/foo-file.txt', '/foo1/', '/foo2/']) + + @mock.patch('py_utils.cloud_storage._RunCommand') + def testListWithPrefix(self, mock_run_command): + mock_run_command.return_value = '\n'.join(['gs://bucket/foo/foo-file.txt', + 'gs://bucket/foo/foo1/', + 'gs://bucket/foo/foo2/']) + + self.assertEqual(cloud_storage.List('bucket', 'foo'), + ['/foo/foo-file.txt', '/foo/foo1/', '/foo/foo2/']) + + @mock.patch('py_utils.cloud_storage._RunCommand') def testListDirs(self, mock_run_command): mock_run_command.return_value = '\n'.join(['gs://bucket/foo-file.txt', '', diff --git a/catapult/common/py_utils/py_utils/ts_proxy_server.py b/catapult/common/py_utils/py_utils/ts_proxy_server.py index b71d143d..0e168a53 100644 --- a/catapult/common/py_utils/py_utils/ts_proxy_server.py +++ b/catapult/common/py_utils/py_utils/ts_proxy_server.py @@ -196,11 +196,13 @@ class TsProxyServer(object): try: py_utils.WaitFor(lambda: self._proc.poll() is not None, 10) except py_utils.TimeoutException: - try: - # Use a SIGNINT so that it can do graceful cleanup - self._proc.send_signal(signal.SIGINT) - except ValueError: - logging.warning('Unable to stop ts_proxy_server gracefully.\n') + # signal.SIGINT is not supported on Windows. + if not sys.platform.startswith('win'): + try: + # Use a SIGNINT so that it can do graceful cleanup + self._proc.send_signal(signal.SIGINT) + except ValueError: + logging.warning('Unable to stop ts_proxy_server gracefully.\n') self._proc.terminate() _, err = self._proc.communicate() diff --git a/catapult/common/py_utils/py_utils/webpagereplay_go_server.py b/catapult/common/py_utils/py_utils/webpagereplay_go_server.py index 950e8adc..95e44954 100644 --- a/catapult/common/py_utils/py_utils/webpagereplay_go_server.py +++ b/catapult/common/py_utils/py_utils/webpagereplay_go_server.py @@ -17,7 +17,6 @@ import py_utils from py_utils import atexit_with_log from py_utils import binary_manager - _WPR_DIR = os.path.abspath(os.path.join( py_utils.GetCatapultDir(), 'web_page_replay_go')) @@ -31,6 +30,8 @@ CHROME_BINARY_CONFIG = os.path.join( RECORD = '--record' INJECT_SCRIPTS = '--inject_scripts=' +USE_LOCAL_WPR = '--use-local-wpr' +DISABLE_FUZZY_URL_MATCHING = '--disable-fuzzy-url-matching' class ReplayError(Exception): """Catch-all exception for the module.""" @@ -102,16 +103,10 @@ class ReplayServer(object): # subprocess. self._temp_log_file_path = None - # Assign the downloader func and binary_manager - downloader = None - if binary_downloader: - downloader = binary_downloader - else: - configs = [CHROME_BINARY_CONFIG, TELEMETRY_PROJECT_CONFIG] - downloader = binary_manager.BinaryManager(configs).FetchPath - + self._downloader = binary_downloader + self._replay_options = replay_options self._cmd_line = self._GetCommandLine( - self._GetGoBinaryPath(downloader=downloader), http_port, https_port, + self._GetGoBinaryPath(replay_options), http_port, https_port, replay_options, archive_path) if RECORD in replay_options or 'record' in replay_options: @@ -122,19 +117,57 @@ class ReplayServer(object): self.replay_process = None - @classmethod - def _GetGoBinaryPath(cls, downloader): - if not cls._go_binary_path: - cls._go_binary_path = downloader( + def _GetDownloader(self): + """Gets the downloader used to download wpr_go binary from GCS.""" + if ReplayServer._go_binary_path: + # If the _go_binary_path was already set, then no need to use downloader + # to download via binary_manager. + self._downloader = None + elif not self._downloader: + configs = [CHROME_BINARY_CONFIG, TELEMETRY_PROJECT_CONFIG] + self._downloader = binary_manager.BinaryManager(configs).FetchPath + return self._downloader + + def _GetGoBinaryPath(self, replay_options): + """Gets the _go_binary_path if it already set, or downloads it.""" + if USE_LOCAL_WPR in replay_options: + # Build WPR + go_folder = os.path.join(_WPR_DIR, 'src') + cur_cwd = os.getcwd() + os.chdir(go_folder) + try: + print subprocess.check_output(['go', 'build', os.path.join(go_folder, 'wpr.go')]) + except subprocess.CalledProcessError: + exit(1) + os.chdir(cur_cwd) + + return os.path.join(go_folder, 'wpr') + + if not ReplayServer._go_binary_path: + downloader = self._GetDownloader() + if not downloader: + raise RuntimeError('downloader should not be None ' + 'while _go_binary_path is None') + ReplayServer._go_binary_path = downloader( 'wpr_go', py_utils.GetHostOsName(), py_utils.GetHostArchName()) - return cls._go_binary_path + return ReplayServer._go_binary_path @classmethod def SetGoBinaryPath(cls, go_binary_path): """Overrides the _go_binary_path. This allows the server to use WPRGO files retrieved from somewhere - other than GCS, such as CIPD.""" + other than GCS via binary_manager, such as test isolation. + + For chromium project to use WPR, it is encourage to use test isolation, + and therefore should call SetGoBinaryPath to set _go_binary_path. + + For Catapult/Telemetry project, the tradition is to download wpr_go + binary via binary_manager. So do not call SetGoBinaryPath. + """ + if not os.path.exists(go_binary_path): + raise ValueError('SetGoBinaryPath could not set {} as it does not exist' + .format(go_binary_path)) cls._go_binary_path = go_binary_path @property @@ -162,7 +195,8 @@ class ReplayServer(object): """ bad_options = [] for option in options: - if option not in [RECORD, INJECT_SCRIPTS]: + if option not in [RECORD, INJECT_SCRIPTS, + USE_LOCAL_WPR, DISABLE_FUZZY_URL_MATCHING]: bad_options.append(option) if len(bad_options) > 0: raise ValueError("Invalid replay options %s" % bad_options) @@ -172,6 +206,8 @@ class ReplayServer(object): cmd_line.append('record') else: cmd_line.append('replay') + if DISABLE_FUZZY_URL_MATCHING in options: + cmd_line.append('--disable_fuzzy_url_matching') key_file = os.path.join(_WPR_DIR, 'wpr_key.pem') cert_file = os.path.join(_WPR_DIR, 'wpr_cert.pem') inject_script = os.path.join(_WPR_DIR, 'deterministic.js') @@ -347,13 +383,17 @@ class ReplayServer(object): def _CleanUpTempLogFilePath(self, log_level): if not self._temp_log_file_path: return '' - if logging.getLogger('').isEnabledFor(log_level): + if logging.getLogger('').isEnabledFor(log_level) or USE_LOCAL_WPR in self._replay_options: with open(self._temp_log_file_path, 'r') as f: wpr_log_output = f.read() - logging.log(log_level, '\n'.join([ - '************************** WPR LOG *****************************', - wpr_log_output, - '************************** END OF WPR LOG **********************'])) + output = ('************************** WPR LOG *****************************\n' + + '\n'.join(wpr_log_output.split('\n')) + + '************************** END OF WPR LOG **********************') + if logging.getLogger('').isEnabledFor(log_level): + logging.log(log_level, output) + else: + print output + os.remove(self._temp_log_file_path) self._temp_log_file_path = None diff --git a/catapult/dependency_manager/dependency_manager/__init__.py b/catapult/dependency_manager/dependency_manager/__init__.py index 84cca5a2..3b18f06a 100644 --- a/catapult/dependency_manager/dependency_manager/__init__.py +++ b/catapult/dependency_manager/dependency_manager/__init__.py @@ -15,7 +15,7 @@ DEPENDENCY_MANAGER_PATH = os.path.join(CATAPULT_PATH, 'dependency_manager') def _AddDirToPythonPath(*path_parts): path = os.path.abspath(os.path.join(*path_parts)) if os.path.isdir(path) and path not in sys.path: - sys.path.append(path) + sys.path.insert(0, path) _AddDirToPythonPath(CATAPULT_PATH, 'common', 'py_utils') diff --git a/catapult/devil/bin/generate_md_docs b/catapult/devil/bin/generate_md_docs index 1cca44c1..d1dbf06f 100755 --- a/catapult/devil/bin/generate_md_docs +++ b/catapult/devil/bin/generate_md_docs @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env vpython # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/catapult/devil/bin/run_py_devicetests b/catapult/devil/bin/run_py_devicetests index 6a6da188..9329f3a8 100755 --- a/catapult/devil/bin/run_py_devicetests +++ b/catapult/devil/bin/run_py_devicetests @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env vpython # Copyright 2016 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/catapult/devil/bin/run_py_tests b/catapult/devil/bin/run_py_tests index 112451c6..be245c6c 100755 --- a/catapult/devil/bin/run_py_tests +++ b/catapult/devil/bin/run_py_tests @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env vpython # Copyright 2016 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/catapult/devil/build/cipd.yaml b/catapult/devil/build/cipd.yaml index fcb4db3b..204400a9 100644 --- a/catapult/devil/build/cipd.yaml +++ b/catapult/devil/build/cipd.yaml @@ -1,3 +1,9 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# To create CIPD package run the following command. +# cipd create --pkg-def cipd.yaml -ref latest package: chromium/third_party/catapult/devil/${platform} description: All of devil along with its dependencies in catapult. @@ -11,4 +17,5 @@ data: - dir: common/py_utils - dir: dependency_manager - dir: devil + - dir: third_party/gsutil - dir: third_party/zipfile diff --git a/catapult/devil/devil/android/device_blacklist.py b/catapult/devil/devil/android/device_blacklist.py deleted file mode 100644 index 7112204e..00000000 --- a/catapult/devil/devil/android/device_blacklist.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -from devil.android import device_denylist - -# TODO(crbug.com/1097306): Remove this (and this file) once existing uses -# have switched to using device_denylist directly. -Blacklist = device_denylist.Denylist diff --git a/catapult/devil/devil/android/device_errors.py b/catapult/devil/devil/android/device_errors.py index d1454683..6e710876 100644 --- a/catapult/devil/devil/android/device_errors.py +++ b/catapult/devil/devil/android/device_errors.py @@ -14,6 +14,7 @@ The class hierarchy for device exceptions is: | +-- FastbootCommandFailedError | +-- DeviceVersionError | +-- DeviceChargingError + | +-- RootUserBuildError +-- CommandTimeoutError +-- DeviceUnreachableError +-- NoDevicesError @@ -228,3 +229,11 @@ class DeviceChargingError(CommandFailedError): def __init__(self, message, device_serial=None): super(DeviceChargingError, self).__init__(message, device_serial) + + +class RootUserBuildError(CommandFailedError): + """Exception for being unable to root a device with "user" build.""" + + def __init__(self, message=None, device_serial=None): + super(RootUserBuildError, self).__init__( + message or 'Unable to root device with user build.', device_serial) diff --git a/catapult/devil/devil/android/device_utils.py b/catapult/devil/devil/android/device_utils.py index 0a041edb..7b7dad24 100644 --- a/catapult/devil/devil/android/device_utils.py +++ b/catapult/devil/devil/android/device_utils.py @@ -45,7 +45,8 @@ from devil.utils import reraiser_thread from devil.utils import timeout_retry from devil.utils import zip_utils -from py_utils import tempfile_ext +with devil_env.SysPath(devil_env.PY_UTILS_PATH): + from py_utils import tempfile_ext try: from devil.utils import reset_usb @@ -132,6 +133,7 @@ _PERMISSIONS_DENYLIST_RE = re.compile('|'.join( 'android.permission.MANAGE_ACCOUNTS', 'android.permission.MODIFY_AUDIO_SETTINGS', 'android.permission.NFC', + 'android.permission.QUERY_ALL_PACKAGES', 'android.permission.READ_SYNC_SETTINGS', 'android.permission.READ_SYNC_STATS', 'android.permission.RECEIVE_BOOT_COMPLETED', @@ -277,6 +279,15 @@ _WEBVIEW_SYSUPDATE_MIN_VERSION_CODE = re.compile( _GOOGLE_FEATURES_RE = re.compile(r'^\s*com\.google\.') +_EMULATOR_RE = re.compile(r'^generic_.*$') + +# Regular expressions for determining if a package is installed using the +# output of `dumpsys package`. +# Matches lines like "Package [com.google.android.youtube] (c491050):". +# or "Package [org.chromium.trichromelibrary_425300033] (e476383):" +_DUMPSYS_PACKAGE_RE_STR =\ + r'^\s*Package\s*\[%s(_(?P<version_code>\d*))?\]\s*\(\w*\):$' + PS_COLUMNS = ('name', 'pid', 'ppid') ProcessInfo = collections.namedtuple('ProcessInfo', PS_COLUMNS) @@ -556,22 +567,14 @@ class DeviceUtils(object): CommandTimeoutError on timeout. DeviceUnreachableError on missing device. """ - try: - if self.build_type == 'eng': - # 'eng' builds have root enabled by default and the adb session cannot - # be unrooted. - return True - # Devices using the system-as-root partition layout appear to not have - # a /root directory. See http://bit.ly/37F34sx for more context. - if (self.build_system_root_image == 'true' - or self.build_version_sdk >= version_codes.Q - # This may be redundant with the checks above. - or self.product_name in _SPECIAL_ROOT_DEVICE_LIST): - return self.GetProp('service.adb.root') == '1' - self.RunShellCommand(['ls', '/root'], check_return=True) + if self.build_type == 'eng': + # 'eng' builds have root enabled by default and the adb session cannot + # be unrooted. return True - except device_errors.AdbCommandFailedError: - return False + # Check if uid is 0. Such behavior has remained unchanged since + # android 2.2.3 (https://bit.ly/2QQzg67) + output = self.RunShellCommand(['id'], single_line=True) + return output.startswith('uid=0(root)') def NeedsSU(self, timeout=DEFAULT, retries=DEFAULT): """Checks whether 'su' is needed to access protected resources. @@ -638,8 +641,7 @@ class DeviceUtils(object): self.adb.Root() except device_errors.AdbCommandFailedError as e: if self.IsUserBuild(): - raise device_errors.CommandFailedError( - 'Unable to root device with user build.', str(self)) + raise device_errors.RootUserBuildError(device_serial=str(self)) elif e.output and _WAIT_FOR_DEVICE_TIMEOUT_STR in e.output: # adb 1.0.41 added a call to wait-for-device *inside* root # with a timeout that can be too short in some cases. @@ -768,21 +770,50 @@ class DeviceUtils(object): raise device_errors.CommandFailedError('Unable to fetch IMEI.') @decorators.WithTimeoutAndRetriesFromInstance() - def IsApplicationInstalled(self, package, timeout=None, retries=None): + def IsApplicationInstalled( + self, package, version_code=None, timeout=None, retries=None): """Determines whether a particular package is installed on the device. Args: package: Name of the package. + version_code: The version of the package to check for as an int, if + applicable. Only used for static shared libraries, otherwise ignored. Returns: True if the application is installed, False otherwise. """ - # `pm list packages` allows matching substrings, but we want exact matches - # only. - matching_packages = self.RunShellCommand( - ['pm', 'list', 'packages', package], check_return=True) - desired_line = 'package:' + package - return desired_line in matching_packages + # `pm list packages` doesn't include the version code, so if it was + # provided, skip this since we can't guarantee that the installed + # version is the requested version. + if version_code is None: + # `pm list packages` allows matching substrings, but we want exact matches + # only. + matching_packages = self.RunShellCommand( + ['pm', 'list', 'packages', package], check_return=True) + desired_line = 'package:' + package + found_package = desired_line in matching_packages + if found_package: + return True + + # Some packages do not properly show up via `pm list packages`, so fall back + # to checking via `dumpsys package`. + matcher = re.compile(_DUMPSYS_PACKAGE_RE_STR % package) + dumpsys_output = self.RunShellCommand( + ['dumpsys', 'package'], check_return=True, large_output=True) + for line in dumpsys_output: + match = matcher.match(line) + # We should have one of these cases: + # 1. The package is a regular app, in which case it will show up without + # its version code in the line we're filtering for. + # 2. The package is a static shared library, in which case one or more + # entries with the version code can show up, but not one without the + # version code. + if match: + installed_version_code = match.groupdict().get('version_code') + if (installed_version_code is None + or installed_version_code == str(version_code)): + return True + return False @decorators.WithTimeoutAndRetriesFromInstance() def GetApplicationPaths(self, package, timeout=None, retries=None): @@ -1062,6 +1093,10 @@ class DeviceUtils(object): retries=None): """Reboot the device. + Note if the device has the root privilege, it will likely lose it after the + reboot. When |block| is True, it will try to restore the root status if + applicable. + Args: block: A boolean indicating if we should wait for the reboot to complete. wifi: A boolean indicating if we should wait for wifi to be enabled after @@ -1081,11 +1116,15 @@ class DeviceUtils(object): def device_offline(): return not self.IsOnline() + # Only check the root when block is True + should_restore_root = self.HasRoot() if block else False self.adb.Reboot() self.ClearCache() timeout_retry.WaitFor(device_offline, wait_period=1) if block: self.WaitUntilFullyBooted(wifi=wifi, decrypt=decrypt) + if should_restore_root: + self.EnableRoot() INSTALL_DEFAULT_TIMEOUT = 8 * _DEFAULT_TIMEOUT MODULES_SRC_DIRECTORY_PATH = '/data/local/tmp/modules' @@ -1282,6 +1321,7 @@ class DeviceUtils(object): apks_to_install = apk_paths if device_apk_paths and apks_to_install and not reinstall: + logger.info('Uninstalling package %s', package_name) self.Uninstall(package_name) if apks_to_install: @@ -1292,6 +1332,8 @@ class DeviceUtils(object): streaming = None if self.product_name in _NO_STREAMING_DEVICE_LIST: streaming = False + logger.info('Installing package %s using APKs %s', + package_name, apks_to_install) if len(apks_to_install) > 1 or partial: self.adb.InstallMultiple( apks_to_install, @@ -1306,10 +1348,20 @@ class DeviceUtils(object): streaming=streaming, allow_downgrade=allow_downgrade) else: + logger.info('Skipping installation of package %s', package_name) # Running adb install terminates running instances of the app, so to be # consistent, we explicitly terminate it when skipping the install. self.ForceStop(package_name) + # There have been cases of APKs not being detected after being explicitly + # installed, so perform a sanity check now and fail early if the + # installation somehow failed. + apk_version = apk.GetVersionCode() + if not self.IsApplicationInstalled(package_name, apk_version): + raise device_errors.CommandFailedError( + 'Package %s with version %s not installed on device after explicit ' + 'install attempt.' % (package_name, apk_version)) + if (permissions is None and self.build_version_sdk >= version_codes.MARSHMALLOW): permissions = apk.GetPermissions() @@ -2045,9 +2097,14 @@ class DeviceUtils(object): def _ComputeDeviceChecksumsForApks(self, package_name): ret = self._cache['package_apk_checksums'].get(package_name) if ret is None: - device_paths = self._GetApplicationPathsInternal(package_name) - file_to_checksums = md5sum.CalculateDeviceMd5Sums(device_paths, self) - ret = set(file_to_checksums.values()) + if self.PathExists('/data/data/' + package_name, as_root=True): + device_paths = self._GetApplicationPathsInternal(package_name) + file_to_checksums = md5sum.CalculateDeviceMd5Sums(device_paths, self) + ret = set(file_to_checksums.values()) + else: + logger.info('Cannot reuse package %s (data directory missing)', + package_name) + ret = set() self._cache['package_apk_checksums'][package_name] = ret return ret @@ -2720,11 +2777,16 @@ class DeviceUtils(object): @property def pixel_density(self): density = self.GetProp('ro.sf.lcd_density', cache=True) - if not density and self.adb.is_emulator: + if not density: + # It might be an emulator, try the qemu prop. density = self.GetProp('qemu.sf.lcd_density', cache=True) return int(density) @property + def is_emulator(self): + return _EMULATOR_RE.match(self.GetProp('ro.product.device', cache=True)) + + @property def build_description(self): """Returns the build description of the system. @@ -3186,11 +3248,12 @@ class DeviceUtils(object): WebViewPackages: Dict of installed WebView providers, mapping "package name" to "reason it's valid/invalid." - It may return an empty dictionary if device does not - support the "dumpsys webviewupdate" command. + The returned dictionary may not include all of the above keys: this depends + on the support of the platform's underlying WebViewUpdateService. This may + return an empty dictionary on OS versions which do not support querying the + WebViewUpdateService. Raises: - CommandFailedError on failure. CommandTimeoutError on timeout. DeviceUnreachableError on missing device. """ @@ -3229,12 +3292,6 @@ class DeviceUtils(object): result['MinimumWebViewVersionCode'] = int(match.group(1)) if webview_packages: result['WebViewPackages'] = webview_packages - - missing_fields = set(['CurrentWebViewPackage', 'FallbackLogicEnabled']) - \ - set(result.keys()) - if len(missing_fields) > 0: - raise device_errors.CommandFailedError( - '%s not found in dumpsys webviewupdate' % str(list(missing_fields))) return result @decorators.WithTimeoutAndRetriesFromInstance() @@ -3552,9 +3609,6 @@ class DeviceUtils(object): retries=1, enable_usb_resets=False, abis=None, - # TODO(crbug.com/1097306): Remove this once clients have - # stopped passing it. - blacklist=None, **kwargs): """Returns a list of DeviceUtils instances. @@ -3607,10 +3661,6 @@ class DeviceUtils(object): if device_arg: device_arg = (device_arg, ) - # TODO(crbug.com/1097306): Remove this once clients have switched. - if blacklist and not denylist: - denylist = blacklist - denylisted_devices = denylist.Read() if denylist else [] # adb looks for ANDROID_SERIAL, so support it as well. diff --git a/catapult/devil/devil/android/device_utils_test.py b/catapult/devil/devil/android/device_utils_test.py index 38e64a97..62313c5b 100755 --- a/catapult/devil/devil/android/device_utils_test.py +++ b/catapult/devil/devil/android/device_utils_test.py @@ -31,8 +31,7 @@ from devil.android.sdk import version_codes from devil.utils import cmd_helper from devil.utils import mock_calls -with devil_env.SysPath( - os.path.join(devil_env.CATAPULT_ROOT_PATH, 'common', 'py_utils')): +with devil_env.SysPath(os.path.join(devil_env.PY_UTILS_PATH)): from py_utils import tempfile_ext with devil_env.SysPath(devil_env.PYMOCK_PATH): @@ -80,6 +79,7 @@ class _MockApkHelper(object): self.perms = perms self.splits = splits if splits else [] self.abis = [abis.ARM] + self.version_code = None def GetPackageName(self): return self.package_name @@ -87,6 +87,9 @@ class _MockApkHelper(object): def GetPermissions(self): return self.perms + def GetVersionCode(self): + return self.version_code + def GetAbis(self): return self.abis @@ -332,119 +335,21 @@ class DeviceUtilsIsOnlineTest(DeviceUtilsTest): class DeviceUtilsHasRootTest(DeviceUtilsTest): def testHasRoot_true(self): - with self.patch_call( - self.call.device.build_type, - return_value='userdebug'), (self.patch_call( - self.call.device.build_system_root_image, - return_value='')), (self.patch_call( - self.call.device.build_version_sdk, - return_value=version_codes.PIE)), (self.patch_call( - self.call.device.product_name, - return_value='notasailfish')), (self.assertCall( - self.call.adb.Shell('ls /root'), 'foo\n')): - self.assertTrue(self.device.HasRoot()) - - def testhasRootSpecial_true(self): - with self.patch_call( - self.call.device.build_type, - return_value='userdebug'), (self.patch_call( - self.call.device.build_system_root_image, - return_value='')), (self.patch_call( - self.call.device.build_version_sdk, - return_value=version_codes.PIE)), (self.patch_call( - self.call.device.product_name, - return_value='sailfish')), (self.assertCall( - self.call.adb.Shell('getprop service.adb.root'), - '1\n')): + with self.patch_call(self.call.device.build_type, + return_value='userdebug'), (self.assertCall( + self.call.adb.Shell('id'), 'uid=0(root)\n')): self.assertTrue(self.device.HasRoot()) - def testhasRootSpecialAosp_true(self): - with self.patch_call( - self.call.device.build_type, - return_value='userdebug'), (self.patch_call( - self.call.device.build_system_root_image, - return_value='')), (self.patch_call( - self.call.device.build_version_sdk, - return_value=version_codes.PIE)), (self.patch_call( - self.call.device.product_name, - return_value='aosp_sailfish')), (self.assertCall( - self.call.adb.Shell('getprop service.adb.root'), - '1\n')): - self.assertTrue(self.device.HasRoot()) - - def testhasRootEngBuild_true(self): + def testHasRootEngBuild_true(self): with self.patch_call(self.call.device.build_type, return_value='eng'): self.assertTrue(self.device.HasRoot()) def testHasRoot_false(self): - with self.patch_call( - self.call.device.build_type, - return_value='userdebug'), (self.patch_call( - self.call.device.build_system_root_image, - return_value='')), (self.patch_call( - self.call.device.build_version_sdk, - return_value=version_codes.PIE)), (self.patch_call( - self.call.device.product_name, - return_value='notasailfish')), (self.assertCall( - self.call.adb.Shell('ls /root'), self.ShellError())): + with self.patch_call(self.call.device.build_type, + return_value='userdebug'), (self.assertCall( + self.call.adb.Shell('id'), 'uid=2000(shell)\n')): self.assertFalse(self.device.HasRoot()) - def testHasRootSpecial_false(self): - with self.patch_call( - self.call.device.build_type, - return_value='userdebug'), (self.patch_call( - self.call.device.build_system_root_image, - return_value='')), (self.patch_call( - self.call.device.build_version_sdk, - return_value=version_codes.PIE)), (self.patch_call( - self.call.device.product_name, - return_value='sailfish')), (self.assertCall( - self.call.adb.Shell('getprop service.adb.root'), '\n')): - self.assertFalse(self.device.HasRoot()) - - def testHasRootSpecialAosp_false(self): - with self.patch_call( - self.call.device.build_type, - return_value='userdebug'), (self.patch_call( - self.call.device.build_system_root_image, - return_value='')), (self.patch_call( - self.call.device.build_version_sdk, - return_value=version_codes.PIE)), (self.patch_call( - self.call.device.product_name, - return_value='aosp_sailfish')), (self.assertCall( - self.call.adb.Shell('getprop service.adb.root'), '\n')): - self.assertFalse(self.device.HasRoot()) - - def testHasRootSystemRootImage(self): - with self.patch_call( - self.call.device.build_type, - return_value='userdebug'), (self.patch_call( - self.call.device.build_system_root_image, - return_value='true')), (self.patch_call( - self.call.device.build_version_sdk, - return_value=version_codes.PIE)), (self.patch_call( - self.call.device.product_name, - return_value='notasailfish')), (self.assertCall( - self.call.adb.Shell('getprop service.adb.root'), - '1\n')): - self.assertTrue(self.device.HasRoot()) - - def testHasRoot10(self): - # All devices on Android 10 / Q and above should use the system-as-root - # partition layout, though they may not have the property set. - with self.patch_call( - self.call.device.build_type, - return_value='userdebug'), (self.patch_call( - self.call.device.build_system_root_image, - return_value='')), (self.patch_call( - self.call.device.build_version_sdk, - return_value=version_codes.Q)), (self.patch_call( - self.call.device.product_name, - return_value='notasailfish')), (self.assertCall( - self.call.adb.Shell('getprop service.adb.root'), - '1\n')): - self.assertTrue(self.device.HasRoot()) - class DeviceUtilsEnableRootTest(DeviceUtilsTest): def testEnableRoot_succeeds(self): @@ -530,21 +435,54 @@ class DeviceUtilsIsApplicationInstalledTest(DeviceUtilsTest): self.assertTrue(self.device.IsApplicationInstalled('some.installed.app')) def testIsApplicationInstalled_notInstalled(self): - with self.assertCalls((self.call.device.RunShellCommand( - ['pm', 'list', 'packages', 'not.installed.app'], check_return=True), - '')): + with self.assertCalls( + (self.call.device.RunShellCommand( + ['pm', 'list', 'packages', 'not.installed.app'], check_return=True), + ''), + (self.call.device.RunShellCommand( + ['dumpsys', 'package'], check_return=True, large_output=True), [])): self.assertFalse(self.device.IsApplicationInstalled('not.installed.app')) def testIsApplicationInstalled_substringMatch(self): - with self.assertCalls((self.call.device.RunShellCommand( - ['pm', 'list', 'packages', 'substring.of.package'], check_return=True), - [ - 'package:first.substring.of.package', - 'package:second.substring.of.package', - ])): + with self.assertCalls( + (self.call.device.RunShellCommand( + ['pm', 'list', 'packages', 'substring.of.package'], + check_return=True), + [ + 'package:first.substring.of.package', + 'package:second.substring.of.package', + ]), + (self.call.device.RunShellCommand( + ['dumpsys', 'package'], check_return=True, large_output=True), [])): self.assertFalse( self.device.IsApplicationInstalled('substring.of.package')) + def testIsApplicationInstalled_dumpsysFallback(self): + with self.assertCalls( + (self.call.device.RunShellCommand( + ['pm', 'list', 'packages', 'some.installed.app'], + check_return=True), []), + (self.call.device.RunShellCommand( + ['dumpsys', 'package'], check_return=True, large_output=True), + ['Package [some.installed.app] (a12345):'])): + self.assertTrue(self.device.IsApplicationInstalled('some.installed.app')) + + def testIsApplicationInstalled_dumpsysFallbackVersioned(self): + with self.assertCalls( + (self.call.device.RunShellCommand( + ['dumpsys', 'package'], check_return=True, large_output=True), + ['Package [some.installed.app_1234] (a12345):'])): + self.assertTrue( + self.device.IsApplicationInstalled('some.installed.app', 1234)) + + def testIsApplicationInstalled_dumpsysFallbackVersionNotNeeded(self): + with self.assertCalls( + (self.call.device.RunShellCommand( + ['dumpsys', 'package'], check_return=True, large_output=True), + ['Package [some.installed.app] (a12345):'])): + self.assertTrue( + self.device.IsApplicationInstalled('some.installed.app', 1234)) + class DeviceUtilsGetApplicationPathsInternalTest(DeviceUtilsTest): def testGetApplicationPathsInternal_exists(self): @@ -913,13 +851,24 @@ class DeviceUtilsRebootTest(DeviceUtilsTest): def testReboot_blocking(self): with self.assertCalls( + (self.call.device.HasRoot(), False), self.call.adb.Reboot(), (self.call.device.IsOnline(), True), (self.call.device.IsOnline(), False), self.call.device.WaitUntilFullyBooted(wifi=False, decrypt=False)): self.device.Reboot(block=True) + def testReboot_blockingWithRoot(self): + with self.assertCalls( + (self.call.device.HasRoot(), True), + self.call.adb.Reboot(), (self.call.device.IsOnline(), True), + (self.call.device.IsOnline(), False), + self.call.device.WaitUntilFullyBooted(wifi=False, decrypt=False), + self.call.device.EnableRoot()): + self.device.Reboot(block=True) + def testReboot_blockUntilWifi(self): with self.assertCalls( + (self.call.device.HasRoot(), False), self.call.adb.Reboot(), (self.call.device.IsOnline(), True), (self.call.device.IsOnline(), False), self.call.device.WaitUntilFullyBooted(wifi=True, decrypt=False)): @@ -927,6 +876,7 @@ class DeviceUtilsRebootTest(DeviceUtilsTest): def testReboot_blockUntilDecrypt(self): with self.assertCalls( + (self.call.device.HasRoot(), False), self.call.adb.Reboot(), (self.call.device.IsOnline(), True), (self.call.device.IsOnline(), False), self.call.device.WaitUntilFullyBooted(wifi=False, decrypt=True)): @@ -950,6 +900,7 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): reinstall=False, streaming=None, allow_downgrade=False), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), (self.call.device.GrantPermissions(TEST_PACKAGE, ['p1']), [])): self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) @@ -966,6 +917,7 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): reinstall=False, streaming=False, allow_downgrade=False), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), (self.call.device.GrantPermissions(TEST_PACKAGE, ['p1']), [])): self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) @@ -981,7 +933,8 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): (self.call.adb.Install(TEST_APK_PATH, reinstall=False, streaming=None, - allow_downgrade=False))): + allow_downgrade=False)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) def testInstall_findPermissions(self): @@ -997,6 +950,7 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): reinstall=False, streaming=None, allow_downgrade=False)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), (self.call.device.GrantPermissions(TEST_PACKAGE, ['p1']), [])): self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) @@ -1011,6 +965,7 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): reinstall=False, streaming=None, allow_downgrade=False)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), (self.call.device.GrantPermissions(TEST_PACKAGE, ['p1', 'p2']), [])): self.device.Install( DeviceUtilsInstallTest.mock_apk, @@ -1024,7 +979,8 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), ['/fake/data/app/test.package.apk']), (self.call.device._ComputeStaleApks(TEST_PACKAGE, [TEST_APK_PATH]), - ([], None)), (self.call.device.ForceStop(TEST_PACKAGE))): + ([], None)), (self.call.device.ForceStop(TEST_PACKAGE)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.Install( DeviceUtilsInstallTest.mock_apk, retries=0, permissions=[]) @@ -1041,7 +997,8 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): self.call.adb.Install(TEST_APK_PATH, reinstall=False, streaming=None, - allow_downgrade=False)): + allow_downgrade=False), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.Install( DeviceUtilsInstallTest.mock_apk, retries=0, permissions=[]) @@ -1058,7 +1015,8 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): self.call.adb.Install(TEST_APK_PATH, reinstall=False, streaming=None, - allow_downgrade=False)): + allow_downgrade=False), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.Install( DeviceUtilsInstallTest.mock_apk, retries=0, permissions=[]) @@ -1075,7 +1033,8 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): self.call.adb.Install(TEST_APK_PATH, reinstall=True, streaming=None, - allow_downgrade=False)): + allow_downgrade=False), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.Install( DeviceUtilsInstallTest.mock_apk, reinstall=True, @@ -1089,7 +1048,8 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), ['/fake/data/app/test.package.apk']), (self.call.device._ComputeStaleApks(TEST_PACKAGE, [TEST_APK_PATH]), - ([], None)), (self.call.device.ForceStop(TEST_PACKAGE))): + ([], None)), (self.call.device.ForceStop(TEST_PACKAGE)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.Install( DeviceUtilsInstallTest.mock_apk, reinstall=True, @@ -1131,7 +1091,8 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): self.call.adb.Install(TEST_APK_PATH, reinstall=True, streaming=None, - allow_downgrade=True)): + allow_downgrade=True), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.Install( DeviceUtilsInstallTest.mock_apk, reinstall=True, @@ -1164,10 +1125,32 @@ class DeviceUtilsInstallTest(DeviceUtilsTest): reinstall=False, streaming=None, allow_downgrade=False), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), (self.call.device.GrantPermissions(TEST_PACKAGE, None), [])): self.device.Install( mock_apk_with_fake, fake_modules=fake_modules, retries=0) + def testInstall_packageNotAvailableAfterInstall(self): + with self.patch_call( + self.call.device.product_name, + return_value='notflounder'), (self.patch_call( + self.call.device.build_version_sdk, return_value=23)), ( + self.patch_call(self.call.device.IsApplicationInstalled, + return_value=False)): + with self.assertCalls( + (self.call.device._FakeInstall(set(), None, 'test.package')), + (mock.call.os.path.exists(TEST_APK_PATH), True), + (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), + self.call.adb.Install(TEST_APK_PATH, + reinstall=False, + streaming=None, + allow_downgrade=False)): + with self.assertRaisesRegexp( + device_errors.CommandFailedError, + 'not installed on device after explicit install attempt'): + self.device.Install( + DeviceUtilsInstallTest.mock_apk, retries=0) + class DeviceUtilsInstallSplitApkTest(DeviceUtilsTest): @@ -1191,7 +1174,8 @@ class DeviceUtilsInstallSplitApkTest(DeviceUtilsTest): partial=None, reinstall=False, streaming=None, - allow_downgrade=False))): + allow_downgrade=False)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.InstallSplitApk( 'base.apk', ['split1.apk', 'split2.apk'], permissions=[], retries=0) @@ -1212,7 +1196,8 @@ class DeviceUtilsInstallSplitApkTest(DeviceUtilsTest): partial=None, reinstall=False, streaming=False, - allow_downgrade=False))): + allow_downgrade=False)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.InstallSplitApk( 'base.apk', ['split1.apk', 'split2.apk'], permissions=[], retries=0) @@ -1237,7 +1222,8 @@ class DeviceUtilsInstallSplitApkTest(DeviceUtilsTest): partial=TEST_PACKAGE, reinstall=True, streaming=None, - allow_downgrade=False))): + allow_downgrade=False)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.InstallSplitApk( DeviceUtilsInstallSplitApkTest.mock_apk, ['split1.apk', 'split2.apk'], @@ -1266,7 +1252,8 @@ class DeviceUtilsInstallSplitApkTest(DeviceUtilsTest): partial=TEST_PACKAGE, reinstall=True, streaming=None, - allow_downgrade=True))): + allow_downgrade=True)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.InstallSplitApk( DeviceUtilsInstallSplitApkTest.mock_apk, ['split1.apk', 'split2.apk'], @@ -1311,7 +1298,8 @@ class DeviceUtilsInstallSplitApkTest(DeviceUtilsTest): partial=None, reinstall=False, streaming=None, - allow_downgrade=False))): + allow_downgrade=False)), + (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): self.device.InstallSplitApk( DeviceUtilsInstallSplitApkTest.mock_apk, ['split1.apk', 'split2.apk'], @@ -3132,8 +3120,8 @@ class DeviceUtilsGetWebViewUpdateServiceDumpTest(DeviceUtilsTest): with self.assertCall( self.call.adb.Shell('dumpsys webviewupdate'), 'Fallback logic enabled: true'): - with self.assertRaises(device_errors.CommandFailedError): - self.device.GetWebViewUpdateServiceDump() + update = self.device.GetWebViewUpdateServiceDump() + self.assertEqual(True, update['FallbackLogicEnabled']) def testGetWebViewUpdateServiceDump_noop(self): with self.patch_call( diff --git a/catapult/devil/devil/android/forwarder.py b/catapult/devil/devil/android/forwarder.py index bf4c5ca1..9b1f82e4 100644 --- a/catapult/devil/devil/android/forwarder.py +++ b/catapult/devil/devil/android/forwarder.py @@ -435,14 +435,10 @@ class Forwarder(object): (exit_code, output) = cmd_helper.GetCmdStatusAndOutputWithTimeout( kill_cmd, Forwarder._TIMEOUT) if exit_code == -9: - # pkill can exit with -9, seemingly in cases where the process it's - # asked to kill dies sometime during pkill running. In this case, - # re-running should result in pkill succeeding. - logging.warning( - 'pkilling host forwarder returned -9, retrying through strace. ' - 'Output: %s', output) - exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout( - ['strace', '-f', '-s', '256'] + kill_cmd, Forwarder._TIMEOUT) + # pkill can exit with -9, which indicates that it was killed. It's + # possible that the forwarder was still killed, though, which will + # be checked later. + logging.warning('pkilling host forwarder returned -9.') if exit_code in (0, 1): # pkill exits with a 0 if it was able to signal at least one process. # pkill exits with a 1 if it wasn't able to signal a process because @@ -458,6 +454,7 @@ class Forwarder(object): '\n '.join(host_forwarder_lines)) else: logger.error('No remaining host_forwarder processes?') + return _DumpHostLog() error_msg = textwrap.dedent("""\ `{kill_cmd}` failed to kill host_forwarder. diff --git a/catapult/devil/devil/android/sdk/adb_wrapper.py b/catapult/devil/devil/android/sdk/adb_wrapper.py index 8cd73136..71928d58 100644 --- a/catapult/devil/devil/android/sdk/adb_wrapper.py +++ b/catapult/devil/devil/android/sdk/adb_wrapper.py @@ -35,11 +35,13 @@ ADB_KEYS_FILE = '/data/misc/adb/adb_keys' ADB_HOST_KEYS_DIR = os.path.join(os.path.expanduser('~'), '.android') DEFAULT_TIMEOUT = 30 +DEFAULT_LONG_TIMEOUT = DEFAULT_TIMEOUT * 10 +DEFAULT_SUPER_LONG_TIMEOUT = DEFAULT_LONG_TIMEOUT * 2 DEFAULT_RETRIES = 2 _ADB_VERSION_RE = re.compile(r'Android Debug Bridge version (\d+\.\d+\.\d+)') _EMULATOR_RE = re.compile(r'^emulator-[0-9]+$') -_DEVICE_NOT_FOUND_RE = re.compile(r"error: device '(?P<serial>.+)' not found") +_DEVICE_NOT_FOUND_RE = re.compile(r"device '(?P<serial>.+)' not found") _READY_STATE = 'device' _VERITY_DISABLE_RE = re.compile(r'(V|v)erity (is )?(already )?disabled' r'|Successfully disabled verity') @@ -303,7 +305,7 @@ class AdbWrapper(object): # inconsistent with error reporting so many command failures present # differently. if status != 0 or (check_error and output.startswith('error:')): - not_found_m = _DEVICE_NOT_FOUND_RE.match(output) + not_found_m = _DEVICE_NOT_FOUND_RE.search(output) device_waiting_m = _WAITING_FOR_DEVICE_RE.match(output) if (device_waiting_m is not None or (not_found_m is not None @@ -476,7 +478,7 @@ class AdbWrapper(object): local, remote, sync=False, - timeout=60 * 5, + timeout=DEFAULT_SUPER_LONG_TIMEOUT, retries=DEFAULT_RETRIES): """Pushes a file from the host to the device. @@ -549,7 +551,11 @@ class AdbWrapper(object): self._RunDeviceAdbCmd(push_cmd, timeout, retries) - def Pull(self, remote, local, timeout=60 * 5, retries=DEFAULT_RETRIES): + def Pull(self, + remote, + local, + timeout=DEFAULT_LONG_TIMEOUT, + retries=DEFAULT_RETRIES): """Pulls a file from the device to the host. Args: @@ -832,7 +838,7 @@ class AdbWrapper(object): reinstall=False, sd_card=False, streaming=None, - timeout=60 * 2, + timeout=DEFAULT_LONG_TIMEOUT, retries=DEFAULT_RETRIES): """Install an apk on the device. @@ -883,7 +889,7 @@ class AdbWrapper(object): allow_downgrade=False, partial=False, streaming=None, - timeout=60 * 2, + timeout=DEFAULT_LONG_TIMEOUT, retries=DEFAULT_RETRIES): """Install an apk with splits on the device. @@ -1002,7 +1008,8 @@ class AdbWrapper(object): VerifyLocalFileExists(path) self._RunDeviceAdbCmd(['restore'] + [path], timeout, retries) - def WaitForDevice(self, timeout=60 * 5, retries=DEFAULT_RETRIES): + def WaitForDevice(self, timeout=DEFAULT_LONG_TIMEOUT, + retries=DEFAULT_RETRIES): """Block until the device is online. Args: @@ -1047,7 +1054,9 @@ class AdbWrapper(object): """Remounts the /system partition on the device read-write.""" self._RunDeviceAdbCmd(['remount'], timeout, retries) - def Reboot(self, to_bootloader=False, timeout=60 * 5, + def Reboot(self, + to_bootloader=False, + timeout=DEFAULT_LONG_TIMEOUT, retries=DEFAULT_RETRIES): """Reboots the device. @@ -1069,7 +1078,16 @@ class AdbWrapper(object): timeout: (optional) Timeout per try in seconds. retries: (optional) Number of retries to attempt. """ - output = self._RunDeviceAdbCmd(['root'], timeout, retries) + try: + output = self._RunDeviceAdbCmd(['root'], timeout, retries) + except device_errors.AdbCommandFailedError as e: + # For some devices, root can occasionally fail with this error and kick + # the device into adb 'offline' mode. Assuming this is transient, try + # waiting for the device to come back up before re-raising the exception + # and proceeding with any retries. + if 'unable to connect for root: closed' in e.output: + self.WaitForDevice() + raise if 'cannot' in output: raise device_errors.AdbCommandFailedError( ['root'], output, device_serial=self._device_serial) @@ -1115,6 +1133,7 @@ class AdbWrapper(object): ['enable-verity'], output, device_serial=self._device_serial) return output + # Deprecated use device_utils#is_emulator instead. @property def is_emulator(self): return _EMULATOR_RE.match(self._device_serial) diff --git a/catapult/devil/devil/android/sdk/adb_wrapper_test.py b/catapult/devil/devil/android/sdk/adb_wrapper_test.py index f30ab152..1b3d5841 100755 --- a/catapult/devil/devil/android/sdk/adb_wrapper_test.py +++ b/catapult/devil/devil/android/sdk/adb_wrapper_test.py @@ -68,3 +68,12 @@ class AdbWrapperTest(unittest.TestCase): get_cmd_mock.return_value = (1, '- waiting for device - ') self.assertRaises(device_errors.DeviceUnreachableError, self.adb.Shell, '/bin/true') + + @mock.patch('devil.utils.cmd_helper.GetCmdStatusAndOutputWithTimeout') + def testRootConnectionClosedFailure(self, get_cmd_mock): + get_cmd_mock.side_effect = [ + (1, 'unable to connect for root: closed'), + (0, ''), + ] + self.assertRaises(device_errors.AdbCommandFailedError, self.adb.Root, + retries=0) diff --git a/catapult/devil/devil/android/sdk/bundletool.py b/catapult/devil/devil/android/sdk/bundletool.py index 5c181c56..f210db14 100644 --- a/catapult/devil/devil/android/sdk/bundletool.py +++ b/catapult/devil/devil/android/sdk/bundletool.py @@ -9,7 +9,9 @@ from devil import base_error from devil import devil_env from devil.utils import cmd_helper from devil.utils import lazy -from py_utils import tempfile_ext + +with devil_env.SysPath(devil_env.PY_UTILS_PATH): + from py_utils import tempfile_ext _bundletool_path = lazy.WeakConstant(lambda: devil_env.config.FetchPath( 'bundletool')) diff --git a/catapult/devil/devil/android/tools/device_monitor.py b/catapult/devil/devil/android/tools/device_monitor.py index 6128dae8..26e89a24 100755 --- a/catapult/devil/devil/android/tools/device_monitor.py +++ b/catapult/devil/devil/android/tools/device_monitor.py @@ -203,11 +203,6 @@ def main(argv): parser = argparse.ArgumentParser(description='Launches the device monitor.') script_common.AddEnvironmentArguments(parser) parser.add_argument('--denylist-file', help='Path to device denylist file.') - # TODO(crbug.com/1097306): Remove this once chromium_android/api.py stops - # using it. - parser.add_argument('--blacklist-file', - dest='denylist_file', - help=argparse.SUPPRESS) args = parser.parse_args(argv) logger = logging.getLogger() diff --git a/catapult/devil/devil/android/tools/device_recovery.py b/catapult/devil/devil/android/tools/device_recovery.py index f25c5a25..10c5fe51 100755 --- a/catapult/devil/devil/android/tools/device_recovery.py +++ b/catapult/devil/devil/android/tools/device_recovery.py @@ -114,6 +114,7 @@ def RecoverDevice(device, denylist, should_reboot=lambda device: True): return if should_reboot(device): + should_restore_root = device.HasRoot() try: device.WaitUntilFullyBooted(retries=0) except (device_errors.CommandTimeoutError, device_errors.CommandFailedError, @@ -154,6 +155,8 @@ def RecoverDevice(device, denylist, should_reboot=lambda device: True): try: device.WaitUntilFullyBooted( retries=0, timeout=device.REBOOT_DEFAULT_TIMEOUT) + if should_restore_root: + device.EnableRoot() except (device_errors.CommandFailedError, device_errors.DeviceUnreachableError): logger.exception('Failure while waiting for %s.', str(device)) @@ -230,8 +233,6 @@ def main(): parser = argparse.ArgumentParser() logging_common.AddLoggingArguments(parser) script_common.AddEnvironmentArguments(parser) - # TODO(crbug.com/1097306): Remove this once callers switch to --denylist-file. - parser.add_argument('--blacklist-file', help=argparse.SUPPRESS) parser.add_argument('--denylist-file', help='Device denylist JSON file.') parser.add_argument( '--known-devices-file', @@ -248,9 +249,6 @@ def main(): denylist = (device_denylist.Denylist(args.denylist_file) if args.denylist_file else None) - # TODO(crbug.com/1097306): Remove this once callers switch to --denylist-file. - if not denylist and args.blacklist_file: - denylist = device_denylist.Denylist(args.blacklist_file) expected_devices = device_status.GetExpectedDevices(args.known_devices_files) usb_devices = set(lsusb.get_android_devices()) diff --git a/catapult/devil/devil/android/tools/device_status.py b/catapult/devil/devil/android/tools/device_status.py index d0eb7df1..40f714aa 100755 --- a/catapult/devil/devil/android/tools/device_status.py +++ b/catapult/devil/devil/android/tools/device_status.py @@ -226,11 +226,6 @@ def AddArguments(parser): parser.add_argument( '--json-output', help='Output JSON information into a specified file.') parser.add_argument('--denylist-file', help='Device denylist JSON file.') - # TODO(crbug.com/1097306): Remove this once //testing/scripts/host_info.py - # stops using it. - parser.add_argument('--blacklist-file', - dest='denylist_file', - help=argparse.SUPPRESS) parser.add_argument( '--known-devices-file', action='append', diff --git a/catapult/devil/devil/android/tools/provision_devices.py b/catapult/devil/devil/android/tools/provision_devices.py index 4b0f44a2..9a324c48 100755 --- a/catapult/devil/devil/android/tools/provision_devices.py +++ b/catapult/devil/devil/android/tools/provision_devices.py @@ -625,9 +625,6 @@ def main(raw_args): metavar='NUM', help='wait for the device to reach this minimum battery' ' level before trying to continue') - # TODO(crbug.com/1097306): Remove after updating clients. - parser.add_argument('--output-device-blacklist', - help=argparse.SUPPRESS) parser.add_argument('--output-device-denylist', help='Json file to output the device denylist.') parser.add_argument( @@ -674,10 +671,6 @@ def main(raw_args): logging_common.InitializeLogging(args) script_common.InitializeEnvironment(args) - output_device_denylist = args.output_device_denylist - if not output_device_denylist and args.output_device_blacklist: - output_device_denylist = args.output_device_blacklist - try: return ProvisionDevices( args.devices, @@ -691,7 +684,7 @@ def main(raw_args): enable_java_debug=args.enable_java_debug, max_battery_temp=args.max_battery_temp, min_battery_level=args.min_battery_level, - output_device_denylist=output_device_denylist, + output_device_denylist=args.output_device_denylist, reboot_timeout=args.reboot_timeout, remove_system_webview=args.remove_system_webview, system_app_remove_list=args.system_app_remove_list, diff --git a/catapult/devil/devil/android/tools/script_common.py b/catapult/devil/devil/android/tools/script_common.py index ae2b7a84..de823662 100644 --- a/catapult/devil/devil/android/tools/script_common.py +++ b/catapult/devil/devil/android/tools/script_common.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import argparse import os from devil import devil_env @@ -66,22 +65,8 @@ def AddDeviceArguments(parser): default=[], help='Serial number of the Android device to use. (default: use all)') - # TODO(crbug.com/1097306): Simplify this to an ungrouped --denylist-file - # once all uses of --blacklist-file / args.blacklist_file have been updated. - class DenylistAction(argparse.Action): - - #override - def __call__(self, parser, namespace, values, option_string=None): - setattr(namespace, 'denylist_file', values) - setattr(namespace, 'blacklist_file', values) - - denylist_group = parser.add_mutually_exclusive_group() - denylist_group.add_argument('--denylist-file', - help='Device denylist JSON file.', - action=DenylistAction) - denylist_group.add_argument('--blacklist-file', - help=argparse.SUPPRESS, - action=DenylistAction) + parser.add_argument('--denylist-file', + help='Device denylist JSON file.') def GetDevices(requested_devices, denylist_file): diff --git a/catapult/devil/devil/android/tools/system_app.py b/catapult/devil/devil/android/tools/system_app.py index c2f058e0..62bf5a59 100755 --- a/catapult/devil/devil/android/tools/system_app.py +++ b/catapult/devil/devil/android/tools/system_app.py @@ -34,8 +34,9 @@ logger = logging.getLogger(__name__) SPECIAL_SYSTEM_APP_LOCATIONS = { # Older versions of ArCore were installed in /data/app/ regardless of # whether they were system apps or not. Newer versions install in /system/ - # if they are system apps, and in /data/app/ if they aren't. - 'com.google.ar.core': ['/data/app/', '/system/'], + # if they are system apps, and in /data/app/ if they aren't. Some newer + # devices/OSes install in /product/app/ for system apps, as well. + 'com.google.ar.core': ['/data/app/', '/system/', '/product/app/'], # On older versions of VrCore, the system app version is installed in # /system/ like normal. However, at some point, this moved to /data/. # So, we have to handle both cases. Like ArCore, this means we'll end up diff --git a/catapult/devil/devil/android/tools/webview_app.py b/catapult/devil/devil/android/tools/webview_app.py index 406de1cb..5866a66c 100755 --- a/catapult/devil/devil/android/tools/webview_app.py +++ b/catapult/devil/devil/android/tools/webview_app.py @@ -12,15 +12,11 @@ import re import sys if __name__ == '__main__': - sys.path.append( - os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..'))) - sys.path.append( - os.path.abspath( - os.path.join( - os.path.dirname(__file__), '..', '..', '..', '..', 'common', - 'py_utils'))) + _DEVIL_ROOT_DIR = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', '..')) + sys.path.append(_DEVIL_ROOT_DIR) +from devil import devil_env from devil.android import apk_helper from devil.android import device_errors from devil.android.sdk import version_codes @@ -29,7 +25,9 @@ from devil.android.tools import system_app from devil.utils import cmd_helper from devil.utils import parallelizer from devil.utils import run_tests_helper -from py_utils import tempfile_ext + +with devil_env.SysPath(devil_env.PY_UTILS_PATH): + from py_utils import tempfile_ext logger = logging.getLogger(__name__) diff --git a/catapult/devil/devil/devil_dependencies.json b/catapult/devil/devil/devil_dependencies.json index 8e15e357..03e8d98a 100644 --- a/catapult/devil/devil/devil_dependencies.json +++ b/catapult/devil/devil/devil_dependencies.json @@ -16,7 +16,7 @@ "cloud_storage_bucket": "chromium-telemetry", "file_info": { "linux2_x86_64": { - "cloud_storage_hash": "8bd43e3930f6eec643d5dc64cab9e5bb4ddf4909", + "cloud_storage_hash": "528d0e88a0d876b0549840f0797beffca4a6a796", "download_path": "../bin/deps/linux2/x86_64/bin/adb" } } diff --git a/catapult/devil/devil/devil_env.py b/catapult/devil/devil/devil_env.py index b39e01c8..b61d1b0e 100644 --- a/catapult/devil/devil/devil_env.py +++ b/catapult/devil/devil/devil_env.py @@ -15,6 +15,7 @@ CATAPULT_ROOT_PATH = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..')) DEPENDENCY_MANAGER_PATH = os.path.join(CATAPULT_ROOT_PATH, 'dependency_manager') PYMOCK_PATH = os.path.join(CATAPULT_ROOT_PATH, 'third_party', 'mock') +PY_UTILS_PATH = os.path.join(CATAPULT_ROOT_PATH, 'common', 'py_utils') @contextlib.contextmanager @@ -151,7 +152,9 @@ class _Environment(object): devil_logger.propagate = False devil_logger.addHandler(handler) - import py_utils.cloud_storage + with SysPath(PY_UTILS_PATH): + import py_utils.cloud_storage + lock_logger = py_utils.cloud_storage.logger lock_logger.setLevel(log_level) lock_logger.propagate = False diff --git a/catapult/devil/devil/utils/update_dependencies.py b/catapult/devil/devil/utils/update_dependencies.py index df1f88b2..513c6382 100755 --- a/catapult/devil/devil/utils/update_dependencies.py +++ b/catapult/devil/devil/utils/update_dependencies.py @@ -116,7 +116,7 @@ def UpdateDependency(dependency_name, dependency_info, local_path, platform): remote_path = '%s_%s' % (dependency_name, dependency_sha1) gs_dest = 'gs://%s/%s/%s' % (bucket, folder, remote_path) ec, gsutil_output = cmd_helper.GetCmdStatusAndOutput( - ['gsutil', 'cp', local_path, gs_dest]) + ['gsutil.py', 'cp', local_path, gs_dest]) if ec: raise base_error.BaseError( 'Failed to upload %s to %s: %s' % (remote_path, gs_dest, gsutil_output)) diff --git a/catapult/devil/devil/utils/zip_utils.py b/catapult/devil/devil/utils/zip_utils.py index 35c59056..aac9641e 100644 --- a/catapult/devil/devil/utils/zip_utils.py +++ b/catapult/devil/devil/utils/zip_utils.py @@ -9,18 +9,17 @@ import os import sys import zipfile -_DEVIL_ROOT_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..')) if __name__ == '__main__': + _DEVIL_ROOT_DIR = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..')) sys.path.append(_DEVIL_ROOT_DIR) -_PY_UTILS_ROOT_DIR = os.path.abspath( - os.path.join(_DEVIL_ROOT_DIR, '..', 'common', 'py_utils')) -sys.path.append(_PY_UTILS_ROOT_DIR) - +from devil import devil_env from devil import base_error from devil.utils import cmd_helper -from py_utils import tempfile_ext + +with devil_env.SysPath(devil_env.PY_UTILS_PATH): + from py_utils import tempfile_ext logger = logging.getLogger(__name__) diff --git a/catapult/devil/devil/utils/zip_utils_test.py b/catapult/devil/devil/utils/zip_utils_test.py index 96a55f55..1afc3f48 100644 --- a/catapult/devil/devil/utils/zip_utils_test.py +++ b/catapult/devil/devil/utils/zip_utils_test.py @@ -6,8 +6,11 @@ import os import unittest import zipfile +from devil import devil_env from devil.utils import zip_utils -from py_utils import tempfile_ext + +with devil_env.SysPath(devil_env.PY_UTILS_PATH): + from py_utils import tempfile_ext class WriteZipFileTest(unittest.TestCase): diff --git a/catapult/systrace/systrace/systrace_trace_viewer.html b/catapult/systrace/systrace/systrace_trace_viewer.html index 04e8089b..473261d8 100644 --- a/catapult/systrace/systrace/systrace_trace_viewer.html +++ b/catapult/systrace/systrace/systrace_trace_viewer.html @@ -2901,8 +2901,6 @@ <div id="collapsing_controls"></div> <tr-ui-b-info-bar-group id="import-warnings"> </tr-ui-b-info-bar-group> - <tr-ui-b-info-bar-group id="polyfill-warning"> - </tr-ui-b-info-bar-group> </div> <middle-container> <slot></slot> @@ -3468,7 +3466,22 @@ * Do not edit directly. */ -'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(window.Polymer){throw new Error('Cannot proceed. Polymer already present.');} +'use strict';const global=this.window||this.global;this.tr=(function(){if(global.tr)return global.tr;function exportPath(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{cur=cur[part]={};}} +return cur;} +function isExported(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{return false;}} +return true;} +function isDefined(name){const parts=name.split('.');let curObject=global;for(let i=0;i<parts.length;i++){const partName=parts[i];const nextObject=curObject[partName];if(nextObject===undefined)return false;curObject=nextObject;} +return true;} +let panicElement=undefined;const rawPanicMessages=[];function showPanicElementIfNeeded(){if(panicElement)return;const panicOverlay=document.createElement('div');panicOverlay.style.backgroundColor='white';panicOverlay.style.border='3px solid red';panicOverlay.style.boxSizing='border-box';panicOverlay.style.color='black';panicOverlay.style.display='flex';panicOverlay.style.height='100%';panicOverlay.style.left=0;panicOverlay.style.padding='8px';panicOverlay.style.position='fixed';panicOverlay.style.top=0;panicOverlay.style.webkitFlexDirection='column';panicOverlay.style.width='100%';panicElement=document.createElement('div');panicElement.style.webkitFlex='1 1 auto';panicElement.style.overflow='auto';panicOverlay.appendChild(panicElement);if(!document.body){setTimeout(function(){document.body.appendChild(panicOverlay);},150);}else{document.body.appendChild(panicOverlay);}} +function showPanic(panicTitle,panicDetails){if(tr.isHeadless){if(panicDetails instanceof Error)throw panicDetails;throw new Error('Panic: '+panicTitle+':\n'+panicDetails);} +if(panicDetails instanceof Error){panicDetails=panicDetails.stack;} +showPanicElementIfNeeded();const panicMessageEl=document.createElement('div');panicMessageEl.innerHTML='<h2 id="message"></h2>'+'<pre id="details"></pre>';panicMessageEl.querySelector('#message').textContent=panicTitle;panicMessageEl.querySelector('#details').textContent=panicDetails;panicElement.appendChild(panicMessageEl);rawPanicMessages.push({title:panicTitle,details:panicDetails});} +function hasPanic(){return rawPanicMessages.length!==0;} +function getPanicText(){return rawPanicMessages.map(function(msg){return msg.title;}).join(', ');} +function exportTo(namespace,fn){const obj=exportPath(namespace);const exports=fn();for(const propertyName in exports){const propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor){Object.defineProperty(obj,propertyName,propertyDescriptor);}}} +function initialize(){if(global.isVinn){tr.isVinn=true;}else if(global.process&&global.process.versions.node){tr.isNode=true;}else{tr.isVinn=false;tr.isNode=false;tr.doc=document;tr.isMac=/Mac/.test(navigator.platform);tr.isWindows=/Win/.test(navigator.platform);tr.isChromeOS=/CrOS/.test(navigator.userAgent);tr.isLinux=/Linux/.test(navigator.userAgent);} +tr.isHeadless=tr.isVinn||tr.isNode;} +return{initialize,exportTo,isExported,isDefined,showPanic,hasPanic,getPanicText,};})();tr.initialize();'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(window.Polymer){throw new Error('Cannot proceed. Polymer already present.');} window.Polymer={};window.Polymer.dom='shadow';} (function(){function resolve(){document.body.removeAttribute('unresolved');} if(window.WebComponents){addEventListener('WebComponentsReady',resolve);}else{if(document.readyState==='interactive'||document.readyState==='complete'){resolve();}else{addEventListener('DOMContentLoaded',resolve);}}}());window.Polymer={Settings:function(){var settings=window.Polymer||{};if(!settings.noUrlSettings){var parts=location.search.slice(1).split('&');for(var i=0,o;i<parts.length&&(o=parts[i]);i++){o=o.split('=');o[0]&&(settings[o[0]]=o[1]||true);}} @@ -4062,22 +4075,7 @@ if(parentNode){if(!this._instance){this._instance=this.stamp();var root=this._in this._instance=null;}},_showHideChildren:function(){var hidden=this.__hideTemplateChildren__||!this.if;if(this._instance){this._instance._showHideChildren(hidden);}},_forwardParentProp:function(prop,value){if(this._instance){this._instance.__setProperty(prop,value,true);}},_forwardParentPath:function(path,value){if(this._instance){this._instance._notifyPath(path,value,true);}}});Polymer({is:'dom-bind',properties:{notifyDomChange:{type:Boolean}},extends:'template',_template:null,created:function(){var self=this;Polymer.RenderStatus.whenReady(function(){if(document.readyState=='loading'){document.addEventListener('DOMContentLoaded',function(){self._markImportsReady();});}else{self._markImportsReady();}});},_ensureReady:function(){if(!this._readied){this._readySelf();}},_markImportsReady:function(){this._importsReady=true;this._ensureReady();},_registerFeatures:function(){this._prepConstructor();},_insertChildren:function(){var refNode;var parentNode=Polymer.dom(this).parentNode;if(parentNode.localName==this.is){refNode=parentNode;parentNode=Polymer.dom(parentNode).parentNode;}else{refNode=this;} Polymer.dom(parentNode).insertBefore(this.root,refNode);},_removeChildren:function(){if(this._children){for(var i=0;i<this._children.length;i++){this.root.appendChild(this._children[i]);}}},_initFeatures:function(){},_scopeElementClass:function(element,selector){if(this.dataHost){return this.dataHost._scopeElementClass(element,selector);}else{return selector;}},_configureInstanceProperties:function(){},_prepConfigure:function(){var config={};for(var prop in this._propertyEffects){config[prop]=this[prop];} var setupConfigure=this._setupConfigure;this._setupConfigure=function(){setupConfigure.call(this,config);};},attached:function(){if(this._importsReady){this.render();}},detached:function(){this._removeChildren();},render:function(){this._ensureReady();if(!this._children){this._template=this;this._prepAnnotations();this._prepEffects();this._prepBehaviors();this._prepConfigure();this._prepBindings();this._prepPropertyInfo();Polymer.Base._initFeatures.call(this);this._children=Polymer.TreeApi.arrayCopyChildNodes(this.root);} -this._insertChildren();if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}}});'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(!Polymer.Settings.useNativeShadow){tr.showPanic('Polymer error','base should use native shadow when possible.');}}'use strict';const global=this.window||this.global;this.tr=(function(){if(global.tr)return global.tr;function exportPath(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{cur=cur[part]={};}} -return cur;} -function isExported(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{return false;}} -return true;} -function isDefined(name){const parts=name.split('.');let curObject=global;for(let i=0;i<parts.length;i++){const partName=parts[i];const nextObject=curObject[partName];if(nextObject===undefined)return false;curObject=nextObject;} -return true;} -let panicElement=undefined;const rawPanicMessages=[];function showPanicElementIfNeeded(){if(panicElement)return;const panicOverlay=document.createElement('div');panicOverlay.style.backgroundColor='white';panicOverlay.style.border='3px solid red';panicOverlay.style.boxSizing='border-box';panicOverlay.style.color='black';panicOverlay.style.display='flex';panicOverlay.style.height='100%';panicOverlay.style.left=0;panicOverlay.style.padding='8px';panicOverlay.style.position='fixed';panicOverlay.style.top=0;panicOverlay.style.webkitFlexDirection='column';panicOverlay.style.width='100%';panicElement=document.createElement('div');panicElement.style.webkitFlex='1 1 auto';panicElement.style.overflow='auto';panicOverlay.appendChild(panicElement);if(!document.body){setTimeout(function(){document.body.appendChild(panicOverlay);},150);}else{document.body.appendChild(panicOverlay);}} -function showPanic(panicTitle,panicDetails){if(tr.isHeadless){if(panicDetails instanceof Error)throw panicDetails;throw new Error('Panic: '+panicTitle+':\n'+panicDetails);} -if(panicDetails instanceof Error){panicDetails=panicDetails.stack;} -showPanicElementIfNeeded();const panicMessageEl=document.createElement('div');panicMessageEl.innerHTML='<h2 id="message"></h2>'+'<pre id="details"></pre>';panicMessageEl.querySelector('#message').textContent=panicTitle;panicMessageEl.querySelector('#details').textContent=panicDetails;panicElement.appendChild(panicMessageEl);rawPanicMessages.push({title:panicTitle,details:panicDetails});} -function hasPanic(){return rawPanicMessages.length!==0;} -function getPanicText(){return rawPanicMessages.map(function(msg){return msg.title;}).join(', ');} -function exportTo(namespace,fn){const obj=exportPath(namespace);const exports=fn();for(const propertyName in exports){const propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor){Object.defineProperty(obj,propertyName,propertyDescriptor);}}} -function initialize(){if(global.isVinn){tr.isVinn=true;}else if(global.process&&global.process.versions.node){tr.isNode=true;}else{tr.isVinn=false;tr.isNode=false;tr.doc=document;tr.isMac=/Mac/.test(navigator.platform);tr.isWindows=/Win/.test(navigator.platform);tr.isChromeOS=/CrOS/.test(navigator.userAgent);tr.isLinux=/Linux/.test(navigator.userAgent);} -tr.isHeadless=tr.isVinn||tr.isNode;} -return{initialize,exportTo,isExported,isDefined,showPanic,hasPanic,getPanicText,};})();tr.initialize();'use strict';tr.exportTo('tr.b',function(){function EventTarget(){} +this._insertChildren();if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}}});'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(!Polymer.Settings.useNativeShadow){tr.showPanic('Polymer error','base should use native shadow when possible.');}}'use strict';tr.exportTo('tr.b',function(){function EventTarget(){} EventTarget.decorate=function(target){for(const k in EventTarget.prototype){if(k==='decorate')continue;const v=EventTarget.prototype[k];if(typeof v!=='function')continue;target[k]=v;}};EventTarget.prototype={addEventListener(type,handler){if(!this.listeners_){this.listeners_=Object.create(null);} if(!(type in this.listeners_)){this.listeners_[type]=[handler];}else{const handlers=this.listeners_[type];if(handlers.indexOf(handler)<0){handlers.push(handler);}}},removeEventListener(type,handler){if(!this.listeners_)return;if(type in this.listeners_){const handlers=this.listeners_[type];const index=handlers.indexOf(handler);if(index>=0){if(handlers.length===1){delete this.listeners_[type];}else{handlers.splice(index,1);}}}},dispatchEvent(event){if(!this.listeners_)return true;event.__defineGetter__('target',()=>this);const realPreventDefault=event.preventDefault;event.preventDefault=function(){realPreventDefault.call(this);this.rawReturnValue=false;};const type=event.type;let prevented=0;if(type in this.listeners_){const handlers=this.listeners_[type].concat();for(let i=0,handler;handler=handlers[i];i++){if(handler.handleEvent){prevented|=handler.handleEvent.call(handler,event)===false;}else{prevented|=handler.call(this,event)===false;}}} return!prevented&&event.rawReturnValue;},async dispatchAsync(event){if(!this.listeners_)return true;const listeners=this.listeners_[event.type];if(listeners===undefined)return;await Promise.all(listeners.slice().map(listener=>{if(listener.handleEvent){return listener.handleEvent.call(listener,event);} @@ -4574,8 +4572,8 @@ 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.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_=[];} +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.serviceWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ServiceWorker');});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 serviceWorkerThreads(){return this.serviceWorkerThreads_;},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);}} @@ -4799,7 +4797,8 @@ const markers=this.markersBySyncId_.get(syncId);if(markers.length===2){throw new if(markers[0].domainId===domainId){throw new Error('A clock domain cannot sync with itself.');} 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 "'+ +return this.getTimeTransformerRaw_(domainId,this.modelDomainId_).fn;},getModelTimeTransformerInverse(domainId){this.onDomainSeen_(domainId);if(!this.modelDomainId_){this.selectModelDomainId_();} +return this.getTimeTransformerRaw_(this.modelDomainId_,domainId).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+'".');} return transformer;},getTransformerBetween_(fromDomainId,toDomainId){const visitedDomainIds=new Set();const queue=[{domainId:fromDomainId,transformer:Transformer.IDENTITY}];while(queue.length>0){queue.sort((domain1,domain2)=>domain1.transformer.error-domain2.transformer.error);const current=queue.shift();if(current.domainId===toDomainId){return current.transformer;} @@ -5154,7 +5153,8 @@ for(const event of this.childEvents()){event.addBoundsToRange(bounds);}},shiftWo for(const event of this.childEvents()){event.start+=shiftAmount;} this.updateBounds();},convertTimestampToModelTime(sourceClockDomainName,ts){if(sourceClockDomainName!=='traceEventClock'){throw new Error('Only traceEventClock is supported.');} return tr.b.Unit.timestampFromUs(ts)+ -this.timestampShiftToZeroAmount_;},get numProcesses(){let n=0;for(const p in this.processes){n++;} +this.timestampShiftToZeroAmount_;},convertTimestampFromModelTime(targetClockDomainName,ts){if(targetClockDomainName!=='traceEventClock'){throw new Error('Only traceEventClock is supported.');} +const convertFn=this.clockSyncManager.getModelTimeTransformerInverse(tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL);return convertFn(ts)-this.timestampShiftToZeroAmount_;},get numProcesses(){let n=0;for(const p in this.processes){n++;} return n;},getProcess(pid){return this.processes[pid];},getOrCreateProcess(pid){if(!this.processes[pid]){this.processes[pid]=new Process(this,pid);} return this.processes[pid];},addStackFrame(stackFrame){if(this.stackFrames[stackFrame.id]){throw new Error('Stack frame already exists');} this.stackFrames[stackFrame.id]=stackFrame;return stackFrame;},updateCategories_(){const categoriesDict={};this.userModel.addCategoriesToDict(categoriesDict);this.device.addCategoriesToDict(categoriesDict);this.kernel.addCategoriesToDict(categoriesDict);for(const pid in this.processes){this.processes[pid].addCategoriesToDict(categoriesDict);} @@ -5683,10 +5683,10 @@ const profileTreeMap=this.profileTrees_.get(sampleType);if(profileTreeMap.has(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;} if(event.id===undefined){throw new Error('No event ID in sample');} -const data=event.args.data;if(data.startTime!==undefined){this.profileInfo_.set(event.id,{startTime:data.startTime,pid:event.pid,tid:event.tid});} +const data=event.args.data;if(data.startTime!==undefined){this.profileInfo_.set(`${event.pid} ${event.id}`,{startTime:data.startTime,pid:event.pid,tid:event.tid});} const timeDeltas=data.timeDeltas;for(const sampleType in data){if(sampleType==='timeDeltas'||sampleType==='startTime'){continue;} if(data[sampleType].samples&&timeDeltas&&data[sampleType].samples.length!==timeDeltas.length){throw new Error('samples and timeDeltas array should have same length');} -const profileTree=this.getOrCreateProfileTree_(sampleType,event.id);const nodes=data[sampleType].nodes;const samples=data[sampleType].samples;if(nodes!==undefined){for(const node of nodes){const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);const profileNode=ProfileNodeType.constructFromObject(profileTree,node);if(profileNode===undefined){continue;} +const profileTree=this.getOrCreateProfileTree_(sampleType,`${event.pid} ${event.id}`);const nodes=data[sampleType].nodes;const samples=data[sampleType].samples;if(nodes!==undefined){for(const node of nodes){const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);const profileNode=ProfileNodeType.constructFromObject(profileTree,node);if(profileNode===undefined){continue;} profileTree.add(profileNode);}} if(samples!==undefined){const thread=this.model_.getOrCreateProcess(profileTree.pid).getOrCreateThread(profileTree.tid);for(let i=0,len=samples.length;i<len;++i){const node=profileTree.getNode(samples[i]);profileTree.endTime+=timeDeltas[i];if(node===undefined)continue;const start=this.toModelTimeFromUs_(profileTree.endTime);this.model_.samples.push(new tr.model.Sample(start,node.sampleTitle,node,thread));}}}},processLegacyV8Sample(event){const data=event.args.data;const sampleType='legacySample';const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);if(data.vm_state==='js'&&!data.stack.length)return;const profileTree=this.getOrCreateProfileTree_(sampleType,event.pid);if(profileTree.getNode(-1)===undefined){profileTree.add(new ProfileNodeType(-1,{url:'',scriptId:-1,functionName:'unknown'},undefined));} let node=undefined;if(data.stack.length>0&&this.v8ProcessCodeMaps_[event.pid]){const map=this.v8ProcessCodeMaps_[event.pid];data.stack.reverse();let parentNode=undefined;for(let i=0;i<data.stack.length;i++){const entry=map.lookupEntry(data.stack[i]);if(entry===undefined){node=profileTree.getNode(-1);}else{node=profileTree.getNode(entry.id);if(node===undefined){const sourceInfo=entry.sourceInfo;node=new ProfileNodeType(entry.id,{functionName:entry.name,url:entry.sourceInfo.file,lineNumber:sourceInfo.line!==-1?sourceInfo.line:undefined,columnNumber:sourceInfo.column!==-1?sourceInfo.column:undefined,scriptid:entry.sourceInfo.scriptId},parentNode);profileTree.add(node);}} @@ -6066,7 +6066,10 @@ this.importer.registerEventHandler(hwcEventName,handler.bind(this));}};Parser.re const kswapdWakeRE=/nid=(\d+) order=(\d+)/;const kswapdSleepRE=/nid=(\d+)/;const reclaimBeginRE=/order=(\d+) may_writepage=\d+ gfp_flags=(.+)/;const reclaimEndRE=/nr_reclaimed=(\d+)/;const lowmemoryRE=/([^ ]+) \((\d+)\), page cache (\d+)kB \(limit (\d+)kB\), free (-?\d+)Kb/;MemReclaimParser.prototype={__proto__:Parser.prototype,kswapdWake(eventName,cpuNumber,pid,ts,eventBase){const event=kswapdWakeRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const nid=parseInt(event[1]);const order=parseInt(event[2]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS){if(order>kthread.order){kthread.order=order;}}else{kthread.openSliceTS=ts;kthread.order=order;} kthread.waitingFor='kswapSleep';return true;},kswapdSleep(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.waitingFor!=='kswapSleep')return false;kthread.waitingFor=undefined;if(kthread.openSliceTS){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim',eventBase.threadName,kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order});} kthread.openSliceTS=undefined;kthread.order=undefined;return true;},reclaimBegin(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimBeginRE.exec(eventBase.details);if(!event)return false;const order=parseInt(event[1]);const gfp=event[2];const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.openMemReclaimSliceTS=ts;kthread.order=order;kthread.gfp=gfp;kthread.waitingFor='reclaimEnd';return true;},reclaimEnd(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimEndRE.exec(eventBase.details);if(!event)return false;const nrReclaimed=parseInt(event[1]);const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.waitingFor!=='reclaimEnd')return false;kthread.waitingFor=undefined;if(kthread.openMemReclaimSliceTS!==undefined){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim','direct reclaim',kthread.openMemReclaimSliceTS,ts-kthread.openMemReclaimSliceTS,0,0,{order:kthread.order,gfp:kthread.gfp,nr_reclaimed:nrReclaimed});kthread.openMemReclaimSliceTS=undefined;kthread.order=undefined;kthread.gfp=undefined;return true;} -return false;},lowmemoryKill(eventName,cpuNumber,pid,ts,eventBase){const event=lowmemoryRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const killedName=event[1];const killedPid=parseInt(event[2]);const cache=parseInt(event[3]);const free=parseInt(event[5]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.thread.sliceGroup.pushCompleteSlice('lowmemory','low memory kill',ts,0,0,0,{killed_name:killedName,killed_pid:killedPid,cache,free});return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency_limits',PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));} +return false;},lowmemoryKill(eventName,cpuNumber,pid,ts,eventBase){const event=lowmemoryRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const killedName=event[1];const killedPid=parseInt(event[2]);const cache=parseInt(event[3]);const free=parseInt(event[5]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.thread.sliceGroup.pushCompleteSlice('lowmemory','low memory kill',ts,0,0,0,{killed_name:killedName,killed_pid:killedPid,cache,free});return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function MSMParser(importer){Parser.call(this,importer);importer.registerEventHandler('msm_gpu_freq_change',MSMParser.prototype.gpuFrequency.bind(this));importer.registerEventHandler('msm_gpu_submit_flush',MSMParser.prototype.gpuSubmitFlush.bind(this));importer.registerEventHandler('msm_gpu_submit_retired',MSMParser.prototype.gpuSubmitRetired.bind(this));this.model_=importer.model_;this.submits={};this.num_submits=0;} +MSMParser.prototype={__proto__:Parser.prototype,gpuFrequency(eventName,cpuNumber,pid,ts,eventBase){const event=/new_freq=(\d+)/.exec(eventBase.details);if(!event)return false;const freq=parseInt(event[1]);const counter=this.model_.kernel.getOrCreateCounter('GPU','GPU Frequency');if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries('frequency',ColorScheme.getColorIdForGeneralPurposeString(counter.name)));} +counter.series.forEach(function(series){series.addCounterSample(ts,freq);});return true;},gpuSubmitFlush(eventName,cpuNumber,pid,ts,eventBase){const event=/id=(\d+) pid=(\d+) ring=(\d+):(\d+) ticks=(\d+)/.exec(eventBase.details);if(!event)return false;const id=parseInt(event[1]);const submit={};submit.flushTS=ts;submit.flushTicks=parseInt(event[5]);submit.pid=parseInt(event[2]);this.submits[id]=submit;this.num_submits++;return true;},gpuSubmitRetired(eventName,cpuNumber,pid,ts,eventBase){const event=/id=(\d+) pid=(\d+) ring=(\d+):(\d+) elapsed=(\d+) ns mhz=(\d+) start=(\d+) end=(\d+)/.exec(eventBase.details);if(!event)return false;const id=parseInt(event[1]);if(!(id in this.submits))return true;const submit=this.submits[id];delete this.submits[id];this.num_submits--;const gpuThread=this.importer.getOrCreatePseudoThread('GPU');submit.elapsedNs=parseInt(event[5]);submit.mhz=parseInt(event[6]);submit.startTicks=parseInt(event[7]);submit.endTicks=parseInt(event[8]);function ticks2ms(ticks){return ticks/19200;} +const queuedDuration=ticks2ms(submit.startTicks-submit.flushTicks);const runningDuration=ticks2ms(submit.endTicks-submit.startTicks);submit.queuedDuration=queuedDuration;submit.runningDuration=runningDuration;const queued=new tr.model.AsyncSlice('',event[1]+' queued',tr.b.ColorScheme.getColorIdForReservedName('thread_state_runnable'),submit.flushTS,submit,queuedDuration);const running=new tr.model.AsyncSlice('',event[1]+' running',tr.b.ColorScheme.getColorIdForReservedName('thread_state_running'),submit.flushTS+queuedDuration,submit,runningDuration);const async=new tr.model.AsyncSlice('','pipeline',ColorScheme.getColorIdForGeneralPurposeString('ongpu:'+submit.pid),submit.flushTS,submit,queuedDuration+runningDuration);async.hidden=true;async.subSlices.push(queued);async.subSlices.push(running);gpuThread.thread.asyncSliceGroup.push(async);const onGpu=new tr.model.ThreadSlice('',event[1],ColorScheme.getColorIdForGeneralPurposeString('ongpu:'+submit.pid),submit.flushTS+queuedDuration,submit,runningDuration);gpuThread.thread.sliceGroup.pushSlice(onGpu);return true;}};Parser.register(MSMParser);return{MSMParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency_limits',PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));} PowerParser.prototype={__proto__:Parser.prototype,cpuStateSlice(ts,targetCpuNumber,eventType,cpuState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);if(eventType!=='1'){this.importer.model.importWarning({type:'parse_error',message:'Don\'t understand power_start events of '+'type '+eventType});return;} const powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));} powerCounter.series.forEach(function(series){series.addCounterSample(ts,cpuState);});},cpuIdleSlice(ts,targetCpuNumber,cpuState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);const powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name)));} @@ -6472,8 +6475,7 @@ return tr.b.math.Rect.fromXYWH(position[0],position[1],size[0],size[1]);} function scrollIntoViewIfNeeded(el){const pr=el.parentElement.getBoundingClientRect();const cr=el.getBoundingClientRect();if(cr.top<pr.top){el.scrollIntoView(true);}else if(cr.bottom>pr.bottom){el.scrollIntoView(false);}} function extractUrlString(url){let extracted=url.replace(/url\((.*)\)/,'$1');extracted=extracted.replace(/\"(.*)\"/,'$1');return extracted;} function toThreeDigitLocaleString(value){return value.toLocaleString(undefined,{minimumFractionDigits:3,maximumFractionDigits:3});} -function isUnknownElementName(name){return document.createElement(name)instanceof HTMLUnknownElement;} -return{isUnknownElementName,toThreeDigitLocaleString,instantiateTemplate,windowRectForElement,scrollIntoViewIfNeeded,extractUrlString,};});'use strict';tr.exportTo('tr.ui.b',function(){if(tr.isHeadless)return{};const THIS_DOC=document._currentScript.ownerDocument;const Overlay=tr.ui.b.define('overlay');Overlay.prototype={__proto__:HTMLDivElement.prototype,decorate(){Polymer.dom(this).classList.add('overlay');this.parentEl_=this.ownerDocument.body;this.visible_=false;this.userCanClose_=true;this.onKeyDown_=this.onKeyDown_.bind(this);this.onClick_=this.onClick_.bind(this);this.onFocusIn_=this.onFocusIn_.bind(this);this.onDocumentClick_=this.onDocumentClick_.bind(this);this.onClose_=this.onClose_.bind(this);this.addEventListener('visible-change',tr.ui.b.Overlay.prototype.onVisibleChange_.bind(this),true);const createShadowRoot=this.createShadowRoot||this.webkitCreateShadowRoot;this.shadow_=createShadowRoot.call(this);Polymer.dom(this.shadow_).appendChild(tr.ui.b.instantiateTemplate('#overlay-template',THIS_DOC));this.closeBtn_=Polymer.dom(this.shadow_).querySelector('close-button');this.closeBtn_.addEventListener('click',this.onClose_);Polymer.dom(this.shadow_).querySelector('overlay-frame').addEventListener('click',this.onClick_);this.observer_=new MutationObserver(this.didButtonBarMutate_.bind(this));this.observer_.observe(Polymer.dom(this.shadow_).querySelector('button-bar'),{childList:true});Object.defineProperty(this,'title',{get(){return Polymer.dom(Polymer.dom(this.shadow_).querySelector('title')).textContent;},set(title){Polymer.dom(Polymer.dom(this.shadow_).querySelector('title')).textContent=title;}});},set userCanClose(userCanClose){this.userCanClose_=userCanClose;this.closeBtn_.style.display=userCanClose?'block':'none';},get buttons(){return Polymer.dom(this.shadow_).querySelector('button-bar');},get visible(){return this.visible_;},set visible(newValue){if(this.visible_===newValue)return;this.visible_=newValue;const e=new tr.b.Event('visible-change');this.dispatchEvent(e);},onVisibleChange_(){this.visible_?this.show_():this.hide_();},show_(){Polymer.dom(this.parentEl_).appendChild(this);if(this.userCanClose_){this.addEventListener('keydown',this.onKeyDown_.bind(this));this.addEventListener('click',this.onDocumentClick_.bind(this));this.closeBtn_.addEventListener('click',this.onClose_);} +return{toThreeDigitLocaleString,instantiateTemplate,windowRectForElement,scrollIntoViewIfNeeded,extractUrlString,};});'use strict';tr.exportTo('tr.ui.b',function(){if(tr.isHeadless)return{};const THIS_DOC=document._currentScript.ownerDocument;const Overlay=tr.ui.b.define('overlay');Overlay.prototype={__proto__:HTMLDivElement.prototype,decorate(){Polymer.dom(this).classList.add('overlay');this.parentEl_=this.ownerDocument.body;this.visible_=false;this.userCanClose_=true;this.onKeyDown_=this.onKeyDown_.bind(this);this.onClick_=this.onClick_.bind(this);this.onFocusIn_=this.onFocusIn_.bind(this);this.onDocumentClick_=this.onDocumentClick_.bind(this);this.onClose_=this.onClose_.bind(this);this.addEventListener('visible-change',tr.ui.b.Overlay.prototype.onVisibleChange_.bind(this),true);const createShadowRoot=this.createShadowRoot||this.webkitCreateShadowRoot;this.shadow_=createShadowRoot.call(this);Polymer.dom(this.shadow_).appendChild(tr.ui.b.instantiateTemplate('#overlay-template',THIS_DOC));this.closeBtn_=Polymer.dom(this.shadow_).querySelector('close-button');this.closeBtn_.addEventListener('click',this.onClose_);Polymer.dom(this.shadow_).querySelector('overlay-frame').addEventListener('click',this.onClick_);this.observer_=new MutationObserver(this.didButtonBarMutate_.bind(this));this.observer_.observe(Polymer.dom(this.shadow_).querySelector('button-bar'),{childList:true});Object.defineProperty(this,'title',{get(){return Polymer.dom(Polymer.dom(this.shadow_).querySelector('title')).textContent;},set(title){Polymer.dom(Polymer.dom(this.shadow_).querySelector('title')).textContent=title;}});},set userCanClose(userCanClose){this.userCanClose_=userCanClose;this.closeBtn_.style.display=userCanClose?'block':'none';},get buttons(){return Polymer.dom(this.shadow_).querySelector('button-bar');},get visible(){return this.visible_;},set visible(newValue){if(this.visible_===newValue)return;this.visible_=newValue;const e=new tr.b.Event('visible-change');this.dispatchEvent(e);},onVisibleChange_(){this.visible_?this.show_():this.hide_();},show_(){Polymer.dom(this.parentEl_).appendChild(this);if(this.userCanClose_){this.addEventListener('keydown',this.onKeyDown_.bind(this));this.addEventListener('click',this.onDocumentClick_.bind(this));this.closeBtn_.addEventListener('click',this.onClose_);} this.parentEl_.addEventListener('focusin',this.onFocusIn_);this.tabIndex=0;const elList=Polymer.dom(this).querySelectorAll('button, input, list, select, a');if(elList.length>0){if(elList[0]===this.closeBtn_){if(elList.length>1)return elList[1].focus();}else{return elList[0].focus();}} this.focus();},hide_(){Polymer.dom(this.parentEl_).removeChild(this);this.parentEl_.removeEventListener('focusin',this.onFocusIn_);if(this.closeBtn_){this.closeBtn_.removeEventListener('click',this.onClose_);} document.removeEventListener('keydown',this.onKeyDown_);document.removeEventListener('click',this.onDocumentClick_);},onClose_(e){this.visible=false;if((e.type!=='keydown')||(e.type==='keydown'&&e.keyCode===27)){e.stopPropagation();} @@ -7090,7 +7092,7 @@ 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},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},INFO_BLURB:{name:'infoBlurb',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},WEBRTC_INTERNAL_REVISIONS:{name:'webrtcInternalRevisions',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={ALERT_GROUPING:{name:'alertGrouping',type:tr.v.d.GenericSet},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:'documentationLinks',type:tr.v.d.GenericSet},INFO_BLURB:{name:'infoBlurb',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},WEBRTC_INTERNAL_REVISIONS:{name:'webrtcInternalRevisions',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;} @@ -7134,13 +7136,17 @@ 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){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);} +static create(name,unit,samples,opt_options){const options=opt_options||{};const hist=new Histogram(name,unit,options.binBoundaries);if(options.alertGrouping!==undefined){hist.setAlertGrouping(options.alertGrouping);} +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){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_;} +setAlertGrouping(alertGrouping){if(alertGrouping===undefined||alertGrouping===null||alertGrouping.length===undefined){throw Error('alertGrouping must be an array');} +for(const alertGroup of alertGrouping){if(!Object.values(tr.v.d.ALERT_GROUPS).includes(alertGroup)){throw Error(`Alert group ${alertGroup} must be added to `+'/tracing/value/diagnostics/alert_groups.html');}} +this.diagnostics.set(tr.v.d.RESERVED_NAMES.ALERT_GROUPING,new tr.v.d.GenericSet(alertGrouping));} 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_);} @@ -7362,7 +7368,7 @@ return true;} Polymer({is:'tr-ui-a-generic-object-view',ready(){this.object_=undefined;},get object(){return this.object_;},set object(object){this.object_=object;this.updateContents_();},updateContents_(){Polymer.dom(this.$.content).textContent='';this.appendElementsForType_('',this.object_,0,0,5,'');},appendElementsForType_(label,object,indent,depth,maxDepth,suffix){if(depth>maxDepth){this.appendSimpleText_(label,indent,'<recursion limit reached>',suffix);return;} if(object===undefined){this.appendSimpleText_(label,indent,'undefined',suffix);return;} if(object===null){this.appendSimpleText_(label,indent,'null',suffix);return;} -if(!(object instanceof Object)){const type=typeof object;if(type!=='string'){return this.appendSimpleText_(label,indent,object,suffix);} +if(!(object instanceof Object)){const type=typeof object;if(type!=='string'){return this.appendSimpleText_(label,indent,String(object),suffix);} let objectReplaced=false;if((object[0]==='{'&&object[object.length-1]==='}')||(object[0]==='['&&object[object.length-1]===']')){try{object=JSON.parse(object);objectReplaced=true;}catch(e){}} if(!objectReplaced){if(object.includes('\n')){const lines=object.split('\n');lines.forEach(function(line,i){let text;let ioff;let ll;let ss;if(i===0){text='"'+line;ioff=0;ll=label;ss='';}else if(i<lines.length-1){text=line;ioff=1;ll='';ss='';}else{text=line+'"';ioff=1;ll='';ss=suffix;} const el=this.appendSimpleText_(ll,indent+ioff*label.length+ioff,text,ss);el.style.whiteSpace='pre';return el;},this);return;} @@ -7700,7 +7706,8 @@ rows.push({name:'Title',value:title});} if(event.category){rows.push({name:'Category',value:event.category});} if(event.model!==undefined){const ufc=event.model.getUserFriendlyCategoryFromEvent(event);if(ufc!==undefined){rows.push({name:'User Friendly Category',value:ufc});}} if(event.name){rows.push({name:'Name',value:event.name});} -rows.push({name:'Start',value:tr.v.ui.createScalarSpan(event.start,{unit:tr.b.Unit.byName.timeStampInMs})});if(event.duration){rows.push({name:'Wall Duration',value:tr.v.ui.createScalarSpan(event.duration,{unit:tr.b.Unit.byName.timeDurationInMs})});} +rows.push({name:'Start',value:tr.v.ui.createScalarSpan(event.start,{unit:tr.b.Unit.byName.timeStampInMs})});if(event.category==='android'&&event.model!==undefined){rows.push({name:'Start (Absolute time)',value:tr.v.ui.createScalarSpan(event.model.convertTimestampFromModelTime('traceEventClock',event.start),{unit:tr.b.Unit.byName.timeStampInMs})});} +if(event.duration){rows.push({name:'Wall Duration',value:tr.v.ui.createScalarSpan(event.duration,{unit:tr.b.Unit.byName.timeDurationInMs})});} if(event.cpuDuration){rows.push({name:'CPU Duration',value:tr.v.ui.createScalarSpan(event.cpuDuration,{unit:tr.b.Unit.byName.timeDurationInMs})});} if(event.subSlices!==undefined&&event.subSlices.length!==0){if(event.selfTime){rows.push({name:'Self Time',value:tr.v.ui.createScalarSpan(event.selfTime,{unit:tr.b.Unit.byName.timeDurationInMs})});} if(event.cpuSelfTime){const cpuSelfTimeEl=tr.v.ui.createScalarSpan(event.cpuSelfTime,{unit:tr.b.Unit.byName.timeDurationInMs});if(event.cpuSelfTime>event.selfTime){cpuSelfTimeEl.warning=' Note that CPU Self Time is larger than Self Time. '+'This is a known limitation of this system, which occurs '+'due to several subslices, rounding issues, and imprecise '+'time at which we get cpu- and real-time.';} @@ -8064,21 +8071,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.BrowserMessageLoopStartTime';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);}}} +tr.metrics.MetricRegistry.register(accessibilityMetric);return{accessibilityMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MESSAGE_LOOP_EVENT_NAME='Startup.BrowserMessageLoopStartTime';const CONTENT_START_EVENT_NAME='content::Start';const NAVIGATION_EVENT_NAME='Navigation StartToCommit';const FIRST_CONTENTFUL_PAINT_EVENT_NAME='firstContentfulPaint';const APPLICATION_START_EVENT_NAME='Startup.LoadTime.ProcessCreateToApplicationStart';function androidStartupMetric(histograms,model){let messageLoopStartEvents=[];let applicationStartEvents=[];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===APPLICATION_START_EVENT_NAME){applicationStartEvents.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);}} +let totalBrowserStarts=messageLoopStartEvents.length;let totalContentStartEvents=contentStartEvents.length;let totalFcpEvents=firstContentfulPaintEvents.length;let totalNavigations=navigationEvents.length;let totalApplicationStartEvents=applicationStartEvents.length;if(totalFcpEvents!==totalBrowserStarts||totalNavigations!==totalBrowserStarts||totalContentStartEvents!==totalBrowserStarts||totalApplicationStartEvents!==totalBrowserStarts||totalBrowserStarts===0){messageLoopStartEvents=[];contentStartEvents=[];navigationEvents=[];firstContentfulPaintEvents=[];applicationStartEvents=[];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===APPLICATION_START_EVENT_NAME){applicationStartEvents.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;totalContentStartEvents=contentStartEvents.length;totalNavigations=navigationEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;} +totalBrowserStarts=messageLoopStartEvents.length;totalContentStartEvents=contentStartEvents.length;totalNavigations=navigationEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;totalApplicationStartEvents=applicationStartEvents.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;} +messageLoopStartEvents.sort(orderEvents);applicationStartEvents.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,[]);const applicationStartHistogram=histograms.createHistogram('process_create_to_app_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);let contentIndex=0;let navIndex=0;let fcpIndex=0;for(let loopStartIndex=0;loopStartIndex<totalBrowserStarts;){const loopStartEvent=messageLoopStartEvents[loopStartIndex];const applicationStartEvent=applicationStartEvents[loopStartIndex];if(fcpIndex===totalFcpEvents){break;} +const contentStartEvent=contentIndex<contentStartEvents.length?contentStartEvents[contentIndex]:null;if(contentStartEvent&&contentStartEvent.start<loopStartEvent.start){contentIndex++;continue;} +const navEvent=navIndex<navigationEvents.length?navigationEvents[navIndex]:null;if(navEvent&&navEvent.start<loopStartEvent.start){navIndex++;continue;} +const fcpEvent=firstContentfulPaintEvents[fcpIndex];if(fcpEvent.start<loopStartEvent.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])});}} +messageLoopStartHistogram.addSample(loopStartEvent.duration,{events:new tr.v.d.RelatedEventSet([loopStartEvent])});if(contentStartEvent){contentStartHistogram.addSample(contentStartEvent.start-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,contentStartEvent])});} +if(navEvent){navigationStartHistogram.addSample(navEvent.start-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,navEvent])});navigationCommitHistogram.addSample(navEvent.end-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,navEvent])});} +firstContentfulPaintHistogram.addSample(fcpEvent.end-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,fcpEvent])});if(applicationStartEvent){applicationStartHistogram.addSample(applicationStartEvent.duration,{events:new tr.v.d.RelatedEventSet([applicationStartEvent])});}}} 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);}} @@ -8139,7 +8146,7 @@ function topGarbageCollectionEventName(event){if(event.title===FULL_GC_EVENT){if return TOP_GC_EVENTS[event.title];} function topGarbageCollectionEventNames(){return Object.values(TOP_GC_EVENTS);} 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 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);} +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.serviceWorkerThreads);threads=threads.concat(rendererHelper.foregroundWorkerThreads);} return threads;} function groupAndProcessEvents(model,filterCallback,groupCallback,processCallback,groups){const groupToEvents={};if(groups){for(const group of groups){groupToEvents[group]=[];}} const threads=jsExecutionThreads(model);for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;const group=groupCallback(event);if(groups&&!(group in groupToEvents)){continue;} @@ -8163,8 +8170,10 @@ return mu;} 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;if(rendererHelper.mainThread===undefined)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,filterEvents,filterAndOrderEvents,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isScavengerStackScanningEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,topGarbageCollectionEventNames,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP={'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.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step','BlinkGC.UnifiedMarkingStep':'blink-gc-unified-marking-by-v8','BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact'};const BLINK_TOP_GC_ROOTS_MARKING_EVENTS=['BlinkGC.VisitRoots'];const BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure'];const BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.IncrementalMarkingStep','BlinkGC.UnifiedMarkingStep'];const BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking',].concat(BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS);const BLINK_GC_FORCED_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking','BlinkGC.MarkBailOutObjects','BlinkGC.MarkFlushV8References','BlinkGC.MarkFlushEphemeronPairs',];const BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS=['BlinkGC.ConcurrentMarkingStep'];const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation'];const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS=['BlinkGC.ConcurrentSweepingStep'];const BLINK_TOP_GC_EVENTS=Object.keys(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP).concat(BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP[event.title];} +return{addMutatorUtilization,findParent,forcedGCEventName,filterEvents,filterAndOrderEvents,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isScavengerStackScanningEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,topGarbageCollectionEventNames,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP={'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.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step','BlinkGC.UnifiedMarkingStep':'blink-gc-unified-marking-by-v8','BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact'};const BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP={'BlinkGC.AtomicPauseMarkEpilogue':'blink:gc:main_thread:cycle:full:atomic:mark:epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink:gc:main_thread:cycle:full:atomic:mark:prologue','BlinkGC.AtomicPauseMarkRoots':'blink:gc:main_thread:cycle:full:atomic:mark:roots','BlinkGC.IncrementalMarkingStartMarking':'blink:gc:main_thread:cycle:full:incremental:mark:start','BlinkGC.IncrementalMarkingStep':'blink:gc:main_thread:cycle:full:incremental:mark:step','BlinkGC.UnifiedMarkingStep':'unified:gc:main_thread:cycle:full:mark:step','BlinkGC.CompleteSweep':'blink:gc:main_thread:cycle:full:sweep:complete','BlinkGC.LazySweepInIdle':'blink:gc:main_thread:cycle:full:sweep:idle','BlinkGC.LazySweepOnAllocation':'blink:gc:main_thread:cycle:full:sweep:on_allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink:gc:main_thread:cycle:full:atomic:sweep:compact'};const BLINK_TOP_GC_ROOTS_MARKING_EVENTS=['BlinkGC.VisitRoots'];const BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure'];const BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.IncrementalMarkingStep','BlinkGC.UnifiedMarkingStep'];const BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking',].concat(BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS);const BLINK_GC_FORCED_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking','BlinkGC.MarkBailOutObjects','BlinkGC.MarkFlushV8References','BlinkGC.MarkFlushEphemeronPairs',];const BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS=['BlinkGC.ConcurrentMarkingStep'];const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation'];const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS=['BlinkGC.ConcurrentSweepingStep'];const BLINK_TOP_GC_EVENTS=Object.keys(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP).concat(BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP[event.title];} function blinkGarbageCollectionEventNames(){return Object.values(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP);} +function blinkGarbageCollectionEventNewName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP[event.title];} +function blinkGarbageCollectionEventNewNames(){return Object.values(BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP);} function isNonForcedEvent(event){return(!event.args||!event.args.forced)&&!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);} function isNonForcedBlinkGarbageCollectionEvent(event){return BLINK_TOP_GC_EVENTS.includes(event.title)&&isNonForcedEvent(event);} function isNonForcedNonAggregatedBlinkGarbageCollectionEvent(event){return event.title in BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP&&isNonForcedEvent(event);} @@ -8181,32 +8190,27 @@ function isNonForcedBlinkGarbageCollectionForegroundSweepingEvent(event){return function isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent(event){return BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS.includes(event.title)&&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);addDurationOfAtomicPause(histograms,model);addDurationOfAtomicPauseTransitiveClosure(histograms,model);addTotalDurationOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);addTotalDurationOfRootsMarking(histograms,model);addTotalDurationOfMarkingTransitiveClosure(histograms,model);addTotalDurationOfForegroundMarking(histograms,model);addTotalDurationOfForcedForegroundMarking(histograms,model);addTotalDurationOfBackgroundMarking(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 addDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedNonAggregatedBlinkGarbageCollectionEvent,blinkGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForTopEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);} -histograms.addHistogram(cpuDuration);},blinkGarbageCollectionEventNames());} -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 addDurationOfAtomicPauseTransitiveClosure(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent,event=>event.args.epoch,function(group,events){const cpuDuration=createNumericForTopEventTime('blink-gc-atomic-pause-mark-transitive-closure');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);},['blink-gc-total']);} -function addTotalDurationOfRootsMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionRootsMarkingEvent,event=>'blink-gc-mark-roots',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);} -histograms.addHistogram(cpuDuration);},['blink-gc-mark-roots']);} -function addTotalDurationOfMarkingTransitiveClosure(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent,event=>'blink-gc-mark-transitive-closure',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);} -histograms.addHistogram(cpuDuration);},['blink-gc-mark-transitive-closure']);} -function addTotalDurationOfForegroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForegroundMarkingEvent,event=>'blink-gc-mark-foreground',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);} -histograms.addHistogram(cpuDuration);},['blink-gc-mark-foreground']);} -function addTotalDurationOfForcedForegroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent,event=>'blink-gc-mark-foreground-forced',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);} -histograms.addHistogram(cpuDuration);},['blink-gc-mark-foreground-forced']);} -function addTotalDurationOfBackgroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent,event=>'blink-gc-mark-background',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);} -histograms.addHistogram(cpuDuration);},['blink-gc-mark-background']);} -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);},['blink-gc-sweep-foreground']);} -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);},['blink-gc-sweep-background']);} +function getEventEpochUniqueId(event){return event.parentContainer.parent.stableId+':'+event.args.epoch;} +tr.metrics.MetricRegistry.register(blinkGcMetric);const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForEventTime(name){const n=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:true,std:true,sum:true,percentile:[0.90]});return n;} +function addDurationOfTopEvents(histograms,model){const nameToNumeric={};const nameToEpochNumeric={};for(const name of blinkGarbageCollectionEventNames()){nameToNumeric[name]=createNumericForEventTime(name);} +for(const name of blinkGarbageCollectionEventNewNames()){nameToEpochNumeric[name]=createNumericForEventTime(name);} +tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedNonAggregatedBlinkGarbageCollectionEvent,getEventEpochUniqueId,function(epoch,events){const namesToPerEpochDurations={};for(const event of events){nameToNumeric[blinkGarbageCollectionEventName(event)].addSample(event.cpuDuration);const name=blinkGarbageCollectionEventNewName(event);namesToPerEpochDurations[name]=(namesToPerEpochDurations[name]||0)+event.cpuDuration;} +for(const name in namesToPerEpochDurations){nameToEpochNumeric[name].addSample(namesToPerEpochDurations[name]);}});for(const name of blinkGarbageCollectionEventNames()){histograms.addHistogram(nameToNumeric[name]);} +for(const name of blinkGarbageCollectionEventNewNames()){histograms.addHistogram(nameToEpochNumeric[name]);}} +function addIndividualDurationsOfEvents(histograms,model,name,filter){const cpuDuration=createNumericForEventTime(name);tr.metrics.v8.utils.groupAndProcessEvents(model,filter,event=>name,function(group,events){for(const event of events){cpuDuration.addSample(event.cpuDuration);}},[name]);histograms.addHistogram(cpuDuration);} +function addPerEpochDurationsOfEvents(histograms,model,name,filter){const cpuDuration=createNumericForEventTime(name);tr.metrics.v8.utils.groupAndProcessEvents(model,filter,getEventEpochUniqueId,function(epoch,events){cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));});histograms.addHistogram(cpuDuration);} +function addDurationOfAtomicPause(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-atomic-pause',isNonForcedBlinkGarbageCollectionAtomicPauseEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:atomic',isNonForcedBlinkGarbageCollectionAtomicPauseEvent);} +function addDurationOfAtomicPauseTransitiveClosure(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-atomic-pause-mark-transitive-closure',isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:atomic:mark:transitive_closure',isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent);} +function addTotalDurationOfTopEvents(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-total',isNonForcedBlinkGarbageCollectionEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full',isNonForcedBlinkGarbageCollectionEvent);} +function addTotalDurationOfRootsMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-roots',isNonForcedBlinkGarbageCollectionRootsMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:roots',isNonForcedBlinkGarbageCollectionRootsMarkingEvent);} +function addTotalDurationOfMarkingTransitiveClosure(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-transitive-closure',isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:transitive_closure',isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent);} +function addTotalDurationOfForegroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-foreground',isNonForcedBlinkGarbageCollectionForegroundMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark',isNonForcedBlinkGarbageCollectionForegroundMarkingEvent);} +function addTotalDurationOfForcedForegroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-foreground-forced',isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:forced',isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent);} +function addTotalDurationOfBackgroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-background',isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:concurrent_thread:cycle:full:mark',isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent);} +function addTotalDurationOfForegroundSweeping(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-sweep-foreground',isNonForcedBlinkGarbageCollectionForegroundSweepingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:sweep',isNonForcedBlinkGarbageCollectionForegroundSweepingEvent);} +function addTotalDurationOfBackgroundSweeping(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-sweep-background',isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:concurrent_thread:cycle:full:sweep',isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent);} 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);},['unified-gc-total']);} +function addTotalDurationOfBlinkAndV8TopEvents(histograms,model){addIndividualDurationsOfEvents(histograms,model,'unified-gc-total',isV8OrBlinkTopLevelGarbageCollectionEvent);} return{blinkGcMetric,};});'use strict';tr.exportTo('tr.metrics.blink',function(){function leakDetectionMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper===undefined){throw new Error('Chrome is not present.');} const rendererHelpers=modelHelper.rendererHelpers;if(Object.keys(rendererHelpers).length===0){throw new Error('Renderer process is not present.');} const pids=Object.keys(rendererHelpers);const chromeDumps=tr.metrics.sh.splitGlobalDumpsByBrowserName(model,undefined).get('chrome');const sumCounter=new Map();for(const pid of pids){for(const[key,count]of countLeakedBlinkObjects(chromeDumps,pid)){sumCounter.set(key,(sumCounter.get(key)||0)+count);}} @@ -8233,10 +8237,21 @@ 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 videoThreads=rendererHelper.process.findAllThreadsMatching(thread=>(thread.name?thread.name.startsWith('ThreadPoolSingleThreadSharedForegroundBlocking'):false));const compositorThread=rendererHelper.compositorThread;if(compositorThread!==undefined){videoThreads.push(compositorThread);} +tr.metrics.MetricRegistry.register(cpuProcessMetric);return{cpuProcessMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function customMetric(histograms,model,opt_options){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper){return;} +const TITLE_PREFIX='custom_metric:';const traces=new Map();const benchmarkValues=new Map();for(const helper of chromeHelper.browserHelpers){if(!helper.mainThread)continue;for(const slice of helper.mainThread.sliceGroup.slices.concat(helper.mainThread.asyncSliceGroup.slices)){if(!slice.error&&slice.title.startsWith(TITLE_PREFIX)){if(!traces.has(slice.title)){traces.set(slice.title,[]);} +traces.get(slice.title).push(slice.duration);}}} +const BENCHMARK_BEGIN='benchmark_begin';const BENCHMARK_END='benchmark_end';const BENCHMARK_VALUE='benchmark_value';const marks=new Map();for(const helper of Object.values(chromeHelper.rendererHelpers)){for(const event of helper.mainThread.sliceGroup.childEvents()){const navId=getNavigationId(event);if(!navId||!event.category.includes('blink.user_timing'))continue;const{title}=event;const index=title.lastIndexOf(':');if(index===-1){continue;} +const name=title.substring(0,index);const lastPart=title.substring(index+1);if(lastPart===BENCHMARK_BEGIN){marks.set(name,event);}else if(lastPart===BENCHMARK_END){if(!marks.has(name)){continue;} +const range=tr.b.math.Range.fromExplicitRange(marks.get(name).start,event.start);if(!traces.has(name)){traces.set(name,[]);} +traces.get(name).push(range.duration);marks.delete(name);}else if(lastPart===BENCHMARK_VALUE){const index2=name.lastIndexOf(':');if(index2===-1){continue;} +const key=name.substring(0,index2);const value=Number(name.substring(index2+1));if(key&&!isNaN(value)){if(!benchmarkValues.has(key)){benchmarkValues.set(key,[]);} +benchmarkValues.get(key).push(value);}}}} +traces.forEach((value,key)=>{histograms.createHistogram(key,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value);});benchmarkValues.forEach((value,key)=>{histograms.createHistogram(key,tr.b.Unit.byName.unitlessNumber_smallerIsBetter,value);});} +function getNavigationId(event){return event.args.data&&event.args.data.navigationId;} +tr.metrics.MetricRegistry.register(customMetric,{supportsRangeOfInterest:false,});return{customMetric,};});'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);}} +processData.calculateSeekTimes(mainThread);processData.calculateBufferingTimes(mainThread);const allThreads=rendererHelper.process.findAllThreadsMatching(function(){return true;});processData.calculateVideoPlaybackQuality(allThreads);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));}}} @@ -8246,15 +8261,18 @@ calculateTimeToAudioPlays(audioThreads){for(const audioThread of audioThreads){f 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(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);}}}} +calculateVideoPlaybackQuality(threads){for(const thread of threads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoPlaybackRoughness'){this.getPerPlaybackObject_(event.args.id).processVideoRoughness(event.args.roughness);}else if(event.title==='VideoPlaybackFreezing'){this.getPerPlaybackObject_(event.args.id).processVideoFreezing(event.args.freezing);}}}} 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;}} -class PerPlaybackData{constructor(playStartTime){this.playStart_=playStartTime;this.timeToVideoPlay_=undefined;this.timeToAudioPlay_=undefined;this.bufferingTime_=undefined;this.droppedFrameCount_=0;this.seekError_=false;this.seekTimes_=new Map();this.currentSeek_=undefined;} +class PerPlaybackData{constructor(playStartTime){this.playStart_=playStartTime;this.timeToVideoPlay_=undefined;this.timeToAudioPlay_=undefined;this.bufferingTime_=undefined;this.droppedFrameCount_=0;this.seekError_=false;this.seekTimes_=new Map();this.currentSeek_=undefined;this.roughness_=undefined;this.freezing_=undefined;} get timeToVideoPlay(){return this.timeToVideoPlay_;} get timeToAudioPlay(){return this.timeToAudioPlay_;} get bufferingTime(){return this.bufferingTime_;} get droppedFrameCount(){return(this.timeToVideoPlay_!==undefined)?this.droppedFrameCount_:undefined;} get seekTimes(){if(this.seekError_||this.currentSeek_!==undefined)return new Map();return this.seekTimes_;} +get roughness(){return this.roughness_;} +get freezing(){return this.freezing_;} processVideoRenderTime(videoRenderTime){if(this.playStart_!==undefined&&this.timeToVideoPlay_===undefined){this.timeToVideoPlay_=videoRenderTime-this.playStart_;}} processAudioRenderTime(audioRenderTime){if(this.playStart_!==undefined&&this.timeToAudioPlay_===undefined){this.timeToAudioPlay_=audioRenderTime-this.playStart_;}} processVideoFramesDropped(count){this.droppedFrameCount_+=count;} @@ -8268,11 +8286,20 @@ processBufferingHaveEnough(time){if(this.seekError_)return;const currentSeek=thi if(currentSeek.pipelineSeekTime===undefined){return;} currentSeek.seekTime=time-currentSeek.startTime;this.currentSeek_=undefined;} processOnEnded(playEndTime,duration){if(this.playStart_===undefined)return;if(this.seekTimes_.size!==0||this.seekError_)return;if(this.bufferingTime_!==undefined)return;duration=tr.b.convertUnit(duration,tr.b.UnitPrefixScale.METRIC.NONE,tr.b.UnitPrefixScale.METRIC.MILLI);const playTime=playEndTime-this.playStart_;if(this.timeToVideoPlay_!==undefined){this.bufferingTime_=playTime-duration-this.timeToVideoPlay_;}else if(this.timeToAudioPlay!==undefined){this.bufferingTime_=playTime-duration-this.timeToAudioPlay_;}} +processVideoRoughness(roughness){if(this.roughness_===undefined||this.roughness_>roughness){this.roughness_=roughness;}} +processVideoFreezing(freezing){if(this.freezing_===undefined||this.freezing_>freezing){this.freezing_=freezing;}} 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);} +this.addSample_(histograms,'buffering_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.bufferingTime);this.addSample_(histograms,'roughness',tr.b.Unit.byName.count_smallerIsBetter,this.roughness);this.addSample_(histograms,'freezing',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.freezing);} 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',function(){function memoryAblationMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper.gpuHelper)return;const gpuProcess=modelHelper.gpuHelper.process;const events=[...gpuProcess.findTopmostSlicesNamed('Memory.GPU.PeakMemoryUsage.AblationTimes')];const allocHistogram=histograms.createHistogram('Ablation Alloc',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,10000,20),description:'The amount of time spent allocating the ablation '+'memory',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const deallocHistogram=histograms.createHistogram('Ablation Dealloc',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,10000,20),description:'The amount of time spent deallocating the ablation '+'memory',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});for(let i=0;i<events.length;i++){allocHistogram.addSample(events[i].args.alloc);deallocHistogram.addSample(events[i].args.dealloc);}} -tr.metrics.MetricRegistry.register(memoryAblationMetric,{requiredCategories:['gpu.memory'],});return{memoryAblationMetric,};});'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);} +tr.metrics.MetricRegistry.register(memoryAblationMetric,{requiredCategories:['gpu.memory'],});return{memoryAblationMetric,};});'use strict';tr.exportTo('tr.metrics.pa',function(){function pcscanMetric(histograms,model){function createNumericForProcess(name,processName,desc){function createNumericForEventTime(name,desc){const n=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);n.description=desc;n.customizeSummaryOptions({avg:true,count:true,max:true,min:true,std:true,sum:true});return n;} +const scheme=['pa','pcscan',processName];if(name)scheme.push(name);return createNumericForEventTime(scheme.join(':'),desc);} +function createHistsForProcess(processName){return{scan:createNumericForProcess('scan',processName,'Time for scanning heap for quarantine pointers'),sweep:createNumericForProcess('sweep',processName,'Time for sweeping quarantine'),clear:createNumericForProcess('clear',processName,'Time for clearing quarantine entries'),total:createNumericForProcess('',processName,'Total time for PCScan execution')};} +function addSample(hists,slice){if(!(slice instanceof tr.model.ThreadSlice))return;if(slice.category!=='partition_alloc')return;if(slice.title==='PCScan.Scan'){hists.scan.addSample(slice.duration);}else if(slice.title==='PCScan.Sweep'){hists.sweep.addSample(slice.duration);}else if(slice.title==='PCScan.Clear'){hists.clear.addSample(slice.duration);}else if(slice.title==='PCScan'){hists.total.addSample(slice.duration);}} +function addHistsForProcess(processHists,processHelpers){for(const helper of Object.values(processHelpers)){const processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(helper.process.name);if(!processHists.has(processName)){processHists.set(processName,createHistsForProcess(processName));} +for(const slice of helper.process.getDescendantEvents()){addSample(processHists.get(processName),slice);}}} +const helper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const processHists=new Map();addHistsForProcess(processHists,helper.browserHelpers);addHistsForProcess(processHists,helper.rendererHelpers);for(const hists of processHists.values()){for(const hist of Object.values(hists)){histograms.addHistogram(hist);}}} +tr.metrics.MetricRegistry.register(pcscanMetric);return{pcscanMetric,};});'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 addToArrayInMap_(map,key,value){const arr=map.get(key)||[];arr.push(value);map.set(key,arr);} 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';} @@ -8304,11 +8331,11 @@ if(eventsByEnvironment[BROWSER_ENVIRONMENT].length>0){return eventsByEnvironment return legacyEvents;} 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.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 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,});} 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_',false,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,(thread,segment)=>thread.getCpuTimeForRange(segment.boundsRange),category=>`thread_${category}_cpu_time_per_frame`,'CPU cores of a thread group per frame');tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getNumToplevelSlicesForRange(segment.boundsRange),category=>`tasks_per_frame_${category}`,'Number of tasks of a thread group per frame');let totalWallTime=0;let totalCpuTime=0;for(const segment of frameSegments){for(const thread of model.getAllThreads()){totalCpuTime+=thread.getCpuTimeForRange(segment.boundsRange);totalWallTime+=thread.getWallTimeForRange(segment.boundsRange);}} histograms.createHistogram('cpu_wall_time_ratio',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,totalCpuTime/totalWallTime,{description:'Ratio of total cpu-time vs. wall-time.',summaryOptions:{},});} -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:{},});} +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+'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:{},});} @@ -8432,7 +8459,7 @@ function collectRectsBasedSpeedIndexSamplesFromLoadExpectations(model,chromeHelp 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(){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);} +tr.metrics.MetricRegistry.register(rectsBasedSpeedIndexMetric);return{rectsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.v.d',function(){const ALERT_GROUPS={CPU_USAGE:'cpu_usage',LOADING_PAINT:'loading_paint',LOADING_INTERACTIVITY:'loading_interactivity',LOADING_LAYOUT:'loading_layout',};return{ALERT_GROUPS,};});'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 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;} @@ -8473,7 +8500,7 @@ return{firstMeaningfulPaintSamples,firstMeaningfulPaintCpuTimeSamples,firstCpuId 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 totalBlockingTimeHistogram=histograms.createHistogram('totalBlockingTime',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Total Blocking Time',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 navigationStartHistogram=histograms.createHistogram('navigationStart',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'navigationStart',summaryOptions:SUMMARY_OPTIONS,});tr.metrics.sh.rectsBasedSpeedIndexMetric(histograms,model);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.navigationStartSamples,navigationStartHistogram,histograms);} +function loadingMetric(histograms,model){const firstPaintHistogram=histograms.createHistogram('timeToFirstPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstContentfulPaintHistogram=histograms.createHistogram('timeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstContentfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});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,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstMeaningfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const timeToInteractiveHistogram=histograms.createHistogram('timeToInteractive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to Interactive',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});const totalBlockingTimeHistogram=histograms.createHistogram('totalBlockingTime',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Total Blocking Time',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});const timeToFirstCpuIdleHistogram=histograms.createHistogram('timeToFirstCpuIdle',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to First CPU Idle',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});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,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const layoutShiftHistogram=histograms.createHistogram('mainFrameCumulativeLayoutShift',unitlessNumber_smallerIsBetter,[],{binBoundaries:LAYOUT_SHIFT_SCORE_BOUNDARIES,description:'Main Frame Document Cumulative Layout Shift Score',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_LAYOUT],});const navigationStartHistogram=histograms.createHistogram('navigationStart',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'navigationStart',summaryOptions:SUMMARY_OPTIONS,});tr.metrics.sh.rectsBasedSpeedIndexMetric(histograms,model);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.navigationStartSamples,navigationStartHistogram,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.totalBlockingTimeSamples,totalBlockingTimeHistogram,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;} @@ -8488,7 +8515,7 @@ let allProcessCpuTime=0;for(const pid in model.processes){const process=model.pr let processCpuTime=0;for(const tid in process.threads){const thread=process.threads[tid];processCpuTime+=thread.getCpuTimeForRange(rangeOfInterest);} 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);} +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.setAlertGrouping([tr.v.d.ALERT_GROUPS.CPU_USAGE]);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',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];} @@ -8924,13 +8951,16 @@ function collectSpeedIndexSamplesFromLoadExpectations(model,chromeHelper){const const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addSpeedIndexScreenshotsBasedSample(speedIndexScreenshotsBasedSamples,expectation.navigationStart,expectation.duration,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);} +tr.metrics.MetricRegistry.register(screenshotsBasedSpeedIndexMetric);return{screenshotsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function weblayerStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('weblayer_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebLayer startup wall time';const loadWallHist=new tr.v.Histogram('weblayer_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebLayer blank URL load wall time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebLayerStartupInterval'){startupWallHist.addSample(slice.duration);} +if(slice.title==='WebLayerBlankUrlLoadInterval'){loadWallHist.addSample(slice.duration);}} +histograms.addHistogram(startupWallHist);histograms.addHistogram(loadWallHist);} +tr.metrics.MetricRegistry.register(weblayerStartupMetric);return{weblayerStartupMetric,};});'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 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);}}}} +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-1){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}});} 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;} @@ -8948,20 +8978,17 @@ 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 getIsHistogramBinsLinear_(histogramName){return histogramName.startsWith('Graphics.Smoothness.Throughput')||histogramName.startsWith('Memory.Memory.GPU.PeakMemoryUsage');} 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);} if(name.startsWith('Memory.Memory.GPU.PeakMemoryUsage')){return tr.v.HistogramBinBoundaries.createLinear(0,1e6,100);} 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);} +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,name);}else{throw new Error('There should be at most one snapshot of UMA '+`histogram for ${name} in each process.`);}}} +for(const[name,values]of histogramValues){const histogram=new tr.v.Histogram(name,getHistogramUnit_(name),getHistogramBoundaries_(name));const isLinear=getIsHistogramBinsLinear_(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(isLinear&&Math.abs(shift)>0.5){throw new Error(`Samples sum is wrong for ${name}.`);} +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);} @@ -8981,7 +9008,52 @@ histograms.addHistogram(cpuTotalOptimizeCode);histograms.addHistogram(wallTotalO function computeDeoptimizeCodeMetrics(histograms,model){const cpuTotalDeoptimizeCode=new tr.v.Histogram('v8_deoptimize_code_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalDeoptimizeCode.description='cpu total time spent in code deoptimization';const wallTotalDeoptimizeCode=new tr.v.Histogram('v8_deoptimize_code_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalDeoptimizeCode.description='wall total time spent in code deoptimization';for(const e of model.findTopmostSlicesNamed('V8.DeoptimizeCode')){cpuTotalDeoptimizeCode.addSample(e.cpuDuration);wallTotalDeoptimizeCode.addSample(e.duration);} histograms.addHistogram(cpuTotalDeoptimizeCode);histograms.addHistogram(wallTotalDeoptimizeCode);} function executionMetric(histograms,model){computeExecuteMetrics(histograms,model);computeParseLazyMetrics(histograms,model);computeCompileIgnitionMetrics(histograms,model);computeCompileFullCodeMetrics(histograms,model);computeRecompileMetrics(histograms,model);computeOptimizeCodeMetrics(histograms,model);computeDeoptimizeCodeMetrics(histograms,model);} -tr.metrics.MetricRegistry.register(executionMetric);return{executionMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const TARGET_FPS=60;const MS_PER_SECOND=1000;const WINDOW_SIZE_MS=MS_PER_SECOND/TARGET_FPS;function gcMetric(histograms,model,options){options=options||{};addDurationOfTopEvents(histograms,model);addTotalDurationOfTopEvents(histograms,model);if(options.include_sub_events){addDurationOfSubEvents(histograms,model);} +tr.metrics.MetricRegistry.register(executionMetric);return{executionMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const TARGET_FPS=60;const MS_PER_SECOND=1000;const WINDOW_SIZE_MS=MS_PER_SECOND/TARGET_FPS;const EPSILON=1e-6;const METRICS=['v8:gc:cycle:full','v8:gc:cycle:full:cpp','v8:gc:cycle:full:mark','v8:gc:cycle:full:mark:cpp','v8:gc:cycle:full:weak','v8:gc:cycle:full:weak:cpp','v8:gc:cycle:full:sweep','v8:gc:cycle:full:sweep:cpp','v8:gc:cycle:full:compact','v8:gc:cycle:full:compact:cpp','v8:gc:cycle:main_thread:full','v8:gc:cycle:main_thread:full:cpp','v8:gc:cycle:main_thread:full:mark','v8:gc:cycle:main_thread:full:mark:cpp','v8:gc:cycle:main_thread:full:weak','v8:gc:cycle:main_thread:full:weak:cpp','v8:gc:cycle:main_thread:full:sweep','v8:gc:cycle:main_thread:full:sweep:cpp','v8:gc:cycle:main_thread:full:compact','v8:gc:cycle:main_thread:full:compact:cpp','v8:gc:event:main_thread:full:atomic','v8:gc:event:main_thread:full:atomic:cpp','v8:gc:event:main_thread:full:atomic:mark','v8:gc:event:main_thread:full:atomic:mark:cpp','v8:gc:event:main_thread:full:atomic:weak','v8:gc:event:main_thread:full:atomic:weak:cpp','v8:gc:event:main_thread:full:atomic:sweep','v8:gc:event:main_thread:full:atomic:sweep:cpp','v8:gc:event:main_thread:full:atomic:compact','v8:gc:event:main_thread:full:atomic:compact:cpp','v8:gc:event:main_thread:full:incremental','v8:gc:event:main_thread:full:incremental:cpp','v8:gc:event:main_thread:full:incremental:mark','v8:gc:event:main_thread:full:incremental:mark:cpp','v8:gc:event:main_thread:full:incremental:sweep','v8:gc:event:main_thread:full:incremental:sweep:cpp','v8:gc:cycle:young','v8:gc:cycle:main_thread:young',];const V8_FULL_ATOMIC_EVENTS=['V8.GCCompactor','V8.GCFinalizeMC','V8.GCFinalizeMCReduceMemory',];const V8_FULL_MARK_EVENTS=['V8.GC_MC_BACKGROUND_MARKING','V8.GC_MC_MARK','V8.GCIncrementalMarking','V8.GCIncrementalMarkingFinalize','V8.GCIncrementalMarkingStart',];const V8_FULL_COMPACT_EVENTS=['V8.GC_MC_BACKGROUND_EVACUATE_COPY','V8.GC_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS','V8.GC_MC_EVACUATE',];const V8_FULL_SWEEP_EVENTS=['V8.GC_MC_BACKGROUND_SWEEPING','V8.GC_MC_SWEEP',];const V8_FULL_WEAK_EVENTS=['V8.GC_MC_CLEAR',];const V8_YOUNG_EVENTS=['V8.GC_SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL','V8.GCScavenger',];const CPP_GC_FULL_MARK_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.ConcurrentMarkingStep','BlinkGC.IncrementalMarkingStartMarking','BlinkGC.IncrementalMarkingStep','BlinkGC.MarkBailOutObjects','BlinkGC.MarkFlushEphemeronPairs','BlinkGC.MarkFlushV8References','BlinkGC.UnifiedMarkingStep','CppGC.AtomicMark','CppGC.IncrementalMark','CppGC.ConcurrentMark',];const CPP_GC_FULL_COMPACT_EVENTS=['BlinkGC.AtomicPauseSweepAndCompact','CppGC.AtomicCompact',];const CPP_GC_FULL_SWEEP_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.ConcurrentSweepingStep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation','CppGC.AtomicSweep','CppGC.IncrementalSweep','CppGC.ConcurrentSweep',];const CPP_GC_FULL_WEAK_EVENTS=['BlinkGC.MarkWeakProcessing','CppGC.AtomicWeak',];const RULES=[{events:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic',},{events:V8_FULL_MARK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:mark',},{events:CPP_GC_FULL_MARK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:mark:cpp',},{events:V8_FULL_MARK_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:mark',},{events:CPP_GC_FULL_MARK_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:mark:cpp',},{events:V8_FULL_COMPACT_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:compact',},{events:CPP_GC_FULL_COMPACT_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:compact:cpp',},{events:V8_FULL_SWEEP_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:sweep',},{events:CPP_GC_FULL_SWEEP_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:sweep:cpp',},{events:V8_FULL_WEAK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:weak',},{events:CPP_GC_FULL_WEAK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:weak:cpp',},{events:V8_FULL_SWEEP_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:sweep',},{events:CPP_GC_FULL_SWEEP_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:sweep:cpp',},{events:V8_YOUNG_EVENTS,contribute_to:'young:atomic',},];const Granularity={CYCLE:'cycle',EVENT:'event',};const ThreadType={MAIN:'main',BACKGROUND:'background',ALL_THREADS:'all_threads',};class Metric{constructor(name){const parts=name.split(':');this.granularity_=parts[2];assert(this.granularity_===Granularity.CYCLE||this.granularity_===Granularity.EVENT);this.thread_=ThreadType.ALL_THREADS;let phasesIndex=3;if(parts[3]==='main_thread'){this.thread_=ThreadType.MAIN;phasesIndex=4;} +if(parts[3]==='background_threads'){this.thread_=ThreadType.BACKGROUND;phasesIndex=4;} +this.phases_=parts.slice(phasesIndex);const maxValue=this.isPerCycleMetric()?10000:1000;const boundaries=tr.v.HistogramBinBoundaries.createExponential(0.1,maxValue,100);this.histogram=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,boundaries);this.histogram.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:false,sum:this.isPerCycleMetric(),});} +isPerCycleMetric(){return this.granularity_===Granularity.CYCLE;} +isMoreGeneralThanOrEqualTo(phases){const phasesSet=new Set(phases.split(':'));return this.phases_.every(phase=>phasesSet.has(phase));} +contributingEvents(rules,events){const eventsByName=groupBy(events,e=>e.title);function matches(rule,event){function isEnclosing(name){if(!eventsByName.has(name))return false;return eventsByName.get(name).some(e=>encloses(e,event));} +if(!rule.events.includes(event.title)){return false;} +if(rule.inside&&!rule.inside.some(isEnclosing)){return false;} +if(rule.outside&&rule.outside.some(isEnclosing)){return false;} +return true;} +const result=[];for(const event of events){const matching=rules.filter(r=>matches(r,event));if(matching.length===0){continue;} +assert(matching.length===1,`${event.userFriendlyName} matches more than one rule: `+ +JSON.stringify(matching));if(this.isMoreGeneralThanOrEqualTo(matching[0].contribute_to)){result.push(event);}} +return result;} +apply(rules,events,threadTypes){const filtered=this.contributingEvents(rules,events);const eventsByThread=groupBy(filtered,e=>e.parentContainer.tid);let flattened=[];for(const[tid,threadEvents]of eventsByThread){if(this.thread_===ThreadType.ALL_THREADS||this.thread_===threadTypes.get(tid)){flattened=flattened.concat(flatten(threadEvents));}} +if(this.isPerCycleMetric()){let sum=0;for(const event of flattened){sum+=event.cpuDuration;} +if(flattened.length>0){this.histogram.addSample(sum);}}else{for(const event of flattened){this.histogram.addSample(event.cpuDuration);}}}} +function assert(condition,message){if(!condition){throw new Error(message);}} +function groupBy(objects,keyCallback){const result=new Map();for(const object of objects){const group=keyCallback(object);if(result.has(group)){result.get(group).push(object);}else{result.set(group,[object]);}} +return result;} +function eventsMentionedIn(rules){let result=[];for(const rule of rules){result=result.concat(rule.events);if(rule.inside){result=result.concat(rule.inside);} +if(rule.outside){result=result.concat(rule.outside);}} +return result;} +function encloses(event1,event2){return(event1.start-EPSILON<=event2.start&&event2.end<=event1.end+EPSILON);} +function jsExecutionThreadsWithTypes(rendererHelper){const mainThreads=([rendererHelper.mainThread].concat(rendererHelper.dedicatedWorkerThreads).concat(rendererHelper.serviceWorkerThreads));const backgroundThreads=rendererHelper.foregroundWorkerThreads;const threadTypes=new Map();for(const thread of mainThreads){threadTypes.set(thread.tid,ThreadType.MAIN);} +for(const thread of backgroundThreads){threadTypes.set(thread.tid,ThreadType.BACKGROUND);} +return[mainThreads.concat(backgroundThreads),threadTypes];} +function flatten(events){function compareWithEpsilon(a,b){if(a.start<b.start-EPSILON)return-1;if(a.start>b.start+EPSILON)return 1;return b.end-a.end;} +events.sort(compareWithEpsilon);let last=events[0];const result=[last];for(const e of events){if(e.end>last.end+EPSILON){assert(e.start>=last.end-EPSILON,'Overlapping events: '+ +e.userFriendlyName+' '+ +last.userFriendlyName);result.push(e);last=e;}} +return result;} +function groupByEpoch(events){function isV8Event(event){return event.category&&event.category.includes('v8');} +function getEpoch(event){function checkEpochConsistency(epoch,event){if(epoch===null)return;assert(epoch===event.args.epoch,`${event.userFriendlyName} has epoch ${event.args.epoch} `+`which contradicts the epoch of nested events ${epoch}`);} +const result={v8:null,cpp:null};while(event){if('epoch'in event.args){if(isV8Event(event)){checkEpochConsistency(result.v8,event);result.v8=event.args.epoch;}else{checkEpochConsistency(result.cpp,event);result.cpp=event.args.epoch;}} +event=event.parentSlice;} +return result;} +const cppToV8=new Map();for(const event of events){const epoch=getEpoch(event);if(epoch.cpp!==null&&epoch.v8!==null){assert(!cppToV8.has(epoch.cpp)||cppToV8.get(epoch.cpp)===epoch.v8,`CppGC epoch ${epoch.cpp} corresponds to two v8 epochs `+`${cppToV8.get(epoch.cpp)} and ${epoch.v8}. `+`Detected at ${event.userFriendlyName}.`);cppToV8.set(epoch.cpp,epoch.v8);}} +const result=new Map();for(const event of events){const epoch=getEpoch(event);if(epoch.cpp===null&&epoch.v8===null){continue;} +assert(epoch.cpp===null||cppToV8.has(epoch.cpp),`CppGC epoch ${epoch.cpp} doesn't have the corresponding V8 epoch. `+`Detected at ${event.userFriendlyName}`);const key=epoch.v8===null?cppToV8.get(epoch.cpp):epoch.v8;if(result.has(key)){result.get(key).push(event);}else{result.set(key,[event]);}} +return result;} +function addGarbageCollectionMetrics(metricNames,histograms,model){const metrics=metricNames.map(name=>new Metric(name));const gcEventNames=new Set(eventsMentionedIn(RULES));const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;const[threads,threadTypes]=jsExecutionThreadsWithTypes(rendererHelper);const events=[];for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(gcEventNames.has(event.title)){events.push(event);}}} +for(const cycleEvents of groupByEpoch(events).values()){if(cycleEvents.some(tr.metrics.v8.utils.isForcedGarbageCollectionEvent)){continue;} +for(const metric of metrics){metric.apply(RULES,cycleEvents,threadTypes);}}} +for(const metric of metrics){histograms.addHistogram(metric.histogram);}} +function gcMetric(histograms,model,options){options=options||{};addDurationOfTopEvents(histograms,model);addTotalDurationOfTopEvents(histograms,model);if(options.include_sub_events){addDurationOfSubEvents(histograms,model);} addPercentageInV8ExecuteOfTopEvents(histograms,model);addTotalPercentageInV8Execute(histograms,model);addMarkCompactorMutatorUtilization(histograms,model);addTotalMarkCompactorTime(histograms,model);addTotalMarkCompactorMarkingTime(histograms,model);addScavengerSurvivedFromStackEvents(histograms,model);} tr.metrics.MetricRegistry.register(gcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const bytes_smallerIsBetter=tr.b.Unit.byName.sizeInBytes_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 createNumericForSubEventTime(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:false,percentile:[0.90]});return n;} @@ -9005,7 +9077,7 @@ function addTotalPercentageInV8Execute(histograms,model){tr.metrics.v8.utils.gro function addPercentageInV8Execute(histograms,model,name,events){let cpuDurationInV8Execute=0;let cpuDurationTotal=0;events.forEach(function(event){const v8Execute=tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isV8ExecuteEvent);if(v8Execute){cpuDurationInV8Execute+=event.cpuDuration;} cpuDurationTotal+=event.cpuDuration;});const percentage=createPercentage(name+'_percentage_in_v8_execute',cpuDurationInV8Execute,cpuDurationTotal,percentage_smallerIsBetter);histograms.addHistogram(percentage);} function addMarkCompactorMutatorUtilization(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=Object.values(chromeHelper.rendererHelpers);tr.metrics.v8.utils.addMutatorUtilization('v8-gc-mark-compactor-mmu',tr.metrics.v8.utils.isNotForcedMarkCompactorEvent,[100],rendererHelpers,histograms);} -return{gcMetric,WINDOW_SIZE_MS,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const COUNT_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1000000,50);const DURATION_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.1,10000,50);const SUMMARY_OPTIONS={std:false,count:false,sum:false,min:false,max:false,};function convertMicroToMilli_(time){return tr.b.convertUnit(time,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);} +return{gcMetric,WINDOW_SIZE_MS,addGarbageCollectionMetrics,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const COUNT_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1000000,50);const DURATION_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.1,10000,50);const SUMMARY_OPTIONS={std:false,count:false,sum:false,min:false,max:false,};function convertMicroToMilli_(time){return tr.b.convertUnit(time,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);} function addDurationHistogram(histogramName,time,histograms){const value=convertMicroToMilli_(time);histograms.createHistogram(`${histogramName}:duration`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,{value},{binBoundaries:DURATION_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});} function addCountHistogram(histogramName,value,histograms){histograms.createHistogram(`${histogramName}:count`,tr.b.Unit.byName.count_smallerIsBetter,{value},{binBoundaries:COUNT_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS});} function runtimeStatsTotalMetric(histograms,model){const v8Slices=tr.metrics.v8.utils.filterEvents(model,ev=>ev instanceof tr.e.v8.V8ThreadSlice);const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(v8Slices);let overallV8Time=runtimeGroupCollection.totalTime;let overallV8Count=runtimeGroupCollection.totalCount;let mainThreadTime=runtimeGroupCollection.totalTime;let mainThreadCount=runtimeGroupCollection.totalCount;let mainThreadV8Time=runtimeGroupCollection.totalTime;let mainThreadV8Count=runtimeGroupCollection.totalCount;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addDurationHistogram(runtimeGroup.name,runtimeGroup.time,histograms);if(runtimeGroup.name==='Blink C++'){overallV8Time-=runtimeGroup.time;mainThreadV8Time-=runtimeGroup.time;}else if(runtimeGroup.name.includes('Background')){mainThreadTime-=runtimeGroup.time;mainThreadV8Time-=runtimeGroup.time;} @@ -9015,12 +9087,16 @@ addDurationHistogram('V8-Only',overallV8Time,histograms);addCountHistogram('V8-O tr.metrics.MetricRegistry.register(runtimeStatsTotalMetric);return{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.v8',function(){function computeSyncInstantiationTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.SyncInstantiate'))return;const wasmSyncInstantiationTimeCPU=new tr.v.Histogram('v8:wasm:sync_instantiate:cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);wasmSyncInstantiationTimeCPU.description='cpu time spent instantiating a WebAssembly module';const wasmSyncInstantiationTimeWall=new tr.v.Histogram('v8:wasm:sync_instantiate:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);wasmSyncInstantiationTimeWall.description='wall time spent instantiating a WebAssembly module';for(const e of wasmEvents['wasm.SyncInstantiate']){wasmSyncInstantiationTimeCPU.addSample(e.cpuDuration);wasmSyncInstantiationTimeWall.addSample(e.duration);} histograms.addHistogram(wasmSyncInstantiationTimeCPU);histograms.addHistogram(wasmSyncInstantiationTimeWall);} +function computeSyncCompileTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.SyncCompile'))return;const wasmSyncCompileTimeCPU=new tr.v.Histogram('v8:wasm:sync_compile:cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);wasmSyncCompileTimeCPU.description='cpu time spent compiling a WebAssembly module synchronously';const wasmSyncCompileTimeWall=new tr.v.Histogram('v8:wasm:sync_compile:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);wasmSyncCompileTimeWall.description='wall time spent compiling a WebAssembly module synchronously';for(const e of wasmEvents['wasm.SyncCompile']){wasmSyncCompileTimeCPU.addSample(e.cpuDuration);wasmSyncCompileTimeWall.addSample(e.duration);} +histograms.addHistogram(wasmSyncCompileTimeCPU);histograms.addHistogram(wasmSyncCompileTimeWall);} function computeStreamingBaselineCompileTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.StartStreamingCompilation')||!wasmEvents.hasOwnProperty('wasm.BaselineFinished')){return;} -const histogram=new tr.v.Histogram('v8:wasm:streaming_baseline_compilation:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);const compilationStart=wasmEvents['wasm.StartStreamingCompilation'][0].start;const compilationEnd=wasmEvents['wasm.BaselineFinished'][0].end;histogram.addSample(compilationEnd-compilationStart);histograms.addHistogram(histogram);} +const histogram=new tr.v.Histogram('v8:wasm:streaming_baseline_compilation:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);for(const endEvent of wasmEvents['wasm.BaselineFinished']){const compilationEnd=endEvent.end;const startEvent=wasmEvents['wasm.StartStreamingCompilation'].find(e=>e.args.id===endEvent.args.id);if(!startEvent)continue;const compilationStart=startEvent.start;histogram.addSample(compilationEnd-compilationStart);} +histograms.addHistogram(histogram);} function computeCompilationTierupWallTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.BaselineFinished')||!wasmEvents.hasOwnProperty('wasm.TopTierFinished')){return;} -const histogram=new tr.v.Histogram('v8:wasm:compilation_tierup:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);const tierupStart=wasmEvents['wasm.BaselineFinished'][0].start;const tierupEnd=wasmEvents['wasm.TopTierFinished'][0].end;histogram.addSample(tierupEnd-tierupStart);histograms.addHistogram(histogram);} +const histogram=new tr.v.Histogram('v8:wasm:compilation_tierup:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);for(const endEvent of wasmEvents['wasm.TopTierFinished']){const tierupEnd=endEvent.end;const startEvent=wasmEvents['wasm.BaselineFinished'].find(e=>e.args.id===endEvent.args.id);if(!startEvent)continue;const tierupStart=startEvent.start;histogram.addSample(tierupEnd-tierupStart);} +histograms.addHistogram(histogram);} function collectWasmEvents(model){const wasmEvents=tr.metrics.v8.utils.filterAndOrderEvents(model,event=>event.title.startsWith('wasm.'),event=>event.title);return wasmEvents;} -function wasmMetric(histograms,model){const wasmEvents=collectWasmEvents(model);computeSyncInstantiationTimeMetric(histograms,wasmEvents);computeStreamingBaselineCompileTimeMetric(histograms,wasmEvents);computeCompilationTierupWallTimeMetric(histograms,wasmEvents);} +function wasmMetric(histograms,model){const wasmEvents=collectWasmEvents(model);computeSyncInstantiationTimeMetric(histograms,wasmEvents);computeSyncCompileTimeMetric(histograms,wasmEvents);computeStreamingBaselineCompileTimeMetric(histograms,wasmEvents);computeCompilationTierupWallTimeMetric(histograms,wasmEvents);} tr.metrics.MetricRegistry.register(wasmMetric);return{wasmMetric,};});'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();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));} @@ -9399,9 +9475,9 @@ const linkEl=tr.ui.b.createLink(link);if(link.href){linkEl.target='_blank';linkE 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-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;} -function createDiagnosticSpan(diagnostic,name,histogram){const tagName=findElementNameForDiagnostic(diagnostic);const span=document.createElement(tagName);if(span.build===undefined)throw new Error(tagName);span.build(diagnostic,name,histogram);return span;} +return typeInfo.metadata.elementName;} +function createDiagnosticSpan(diagnostic,name,histogram){const tagName=findElementNameForDiagnostic(diagnostic);const span=document.createElement(tagName);if(span instanceof HTMLUnknownElement){throw new Error('Element not registered: '+tagName);} +if(span.build===undefined)throw new Error(tagName);span.build(diagnostic,name,histogram);return span;} 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;} @@ -9730,7 +9806,8 @@ const rowsWithHeadings=[];for(const subGroup of this.group_.viewSubGroups){const for(let i=0;i<subGroupRows.length;i++){rowsWithHeadings.push({row:subGroupRows[i],heading:(i===0?subGroup.title:'')});}} this.setPrebuiltSubRows(this.group_,rowsWithHeadings);}};function stripSlice_(slice){if(slice.subSlices!==undefined&&slice.subSlices.length===1){const subSlice=slice.subSlices[0];if(tr.b.math.approximately(subSlice.start,slice.start,1)&&tr.b.math.approximately(subSlice.duration,slice.duration,1)){return subSlice;}} return slice;} -function makeLevelSubRows_(slices){const rows=[];const putSlice=(slice,level)=>{while(rows.length<=level){rows.push([]);} +function makeLevelSubRows_(slices){const rows=[];const putSlice=(slice,level)=>{if(slice.hidden){return;} +while(rows.length<=level){rows.push([]);} rows[level].push(slice);};const putSliceRecursively=(slice,level)=>{putSlice(slice,level);if(slice.subSlices!==undefined){for(const subSlice of slice.subSlices){putSliceRecursively(subSlice,level+1);}}};for(const slice of slices){putSliceRecursively(stripSlice_(slice),0);} return rows;} function groupAsyncSlicesIntoSubRows(slices,opt_skipSort){if(!opt_skipSort){slices.sort((x,y)=>x.start-y.start);} @@ -9873,9 +9950,9 @@ this.removeAttribute('expanded');unsupportedLabelEls.push(labelEl);}} for(const labelEl of unsupportedLabelEls){Polymer.dom(this.tabStrip_).appendChild(labelEl);} if(previouslyActivePanelType&&supportedPanelTypes.includes(previouslyActivePanelType)){this.activePanelType=previouslyActivePanelType;Polymer.dom(this).setAttribute('expanded',true);}else{if(this.activePanel){Polymer.dom(this.activePanelContainer_).removeChild(this.activePanel);} Polymer.dom(this).removeAttribute('expanded');}},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){if(range===undefined){throw new Error('Must not be undefined');} -this.rangeOfInterest_=range;if(this.activePanel){this.activePanel.rangeOfInterest=range;}}});'use strict';Polymer({is:'tr-ui-timeline-view-help-overlay',ready(){const mod=tr.isMac?'cmd ':'ctrl';const spans=Polymer.dom(this.root).querySelectorAll('span.mod');for(let i=0;i<spans.length;i++){Polymer.dom(spans[i]).textContent=mod;}}});'use strict';Polymer({is:'tr-ui-timeline-view-metadata-overlay',created(){this.metadata_=undefined;},ready(){this.$.table.tableColumns=[{title:'name',value:d=>d.name,},{title:'value',value:d=>{const gov=document.createElement('tr-ui-a-generic-object-view');gov.object=d.value;return gov;},}];},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.table.tableRows=this.metadata_;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-v-ui-preferred-display-unit',ready(){this.preferredTimeDisplayMode_=undefined;},attached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},detached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},get preferredTimeDisplayMode(){return this.preferredTimeDisplayMode_;},set preferredTimeDisplayMode(v){if(this.preferredTimeDisplayMode_===v)return;this.preferredTimeDisplayMode_=v;tr.b.Unit.didPreferredTimeDisplayUnitChange();}});'use strict';const POLYFILL_WARNING_MESSAGE='Trace Viewer is running with WebComponentsV0 polyfill, and some '+'features may be broken. As a workaround, you may try running chrome '+'with "--enable-blink-features=ShadowDOMV0,CustomElementsV0,HTMLImports" '+'flag. See crbug.com/1036492.';Polymer({is:'tr-ui-timeline-view',created(){this.trackViewContainer_=undefined;this.queuedModel_=undefined;this.builtPromise_=undefined;this.doneBuilding_=undefined;},attached(){this.async(function(){this.trackViewContainer_=Polymer.dom(this).querySelector('#track_view_container');if(!this.trackViewContainer_){throw new Error('missing trackviewContainer');} +this.rangeOfInterest_=range;if(this.activePanel){this.activePanel.rangeOfInterest=range;}}});'use strict';Polymer({is:'tr-ui-timeline-view-help-overlay',ready(){const mod=tr.isMac?'cmd ':'ctrl';const spans=Polymer.dom(this.root).querySelectorAll('span.mod');for(let i=0;i<spans.length;i++){Polymer.dom(spans[i]).textContent=mod;}}});'use strict';Polymer({is:'tr-ui-timeline-view-metadata-overlay',created(){this.metadata_=undefined;},ready(){this.$.table.tableColumns=[{title:'name',value:d=>d.name,},{title:'value',value:d=>{const gov=document.createElement('tr-ui-a-generic-object-view');gov.object=d.value;return gov;},}];},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.table.tableRows=this.metadata_;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-v-ui-preferred-display-unit',ready(){this.preferredTimeDisplayMode_=undefined;},attached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},detached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},get preferredTimeDisplayMode(){return this.preferredTimeDisplayMode_;},set preferredTimeDisplayMode(v){if(this.preferredTimeDisplayMode_===v)return;this.preferredTimeDisplayMode_=v;tr.b.Unit.didPreferredTimeDisplayUnitChange();}});'use strict';const POLYFILL_WARNING_MESSAGE='Trace Viewer is running with WebComponentsV0 polyfill, and some '+'features may be broken. See crbug.com/1036492.';Polymer({is:'tr-ui-timeline-view',created(){this.trackViewContainer_=undefined;this.queuedModel_=undefined;this.builtPromise_=undefined;this.doneBuilding_=undefined;},attached(){this.async(function(){this.trackViewContainer_=Polymer.dom(this).querySelector('#track_view_container');if(!this.trackViewContainer_){throw new Error('missing trackviewContainer');} if(this.queuedModel_)this.updateContents_();});},ready(){this.tabIndex=0;this.polyfillWarnedOnce_=false;this.titleEl_=this.$.title;this.leftControlsEl_=this.$.left_controls;this.rightControlsEl_=this.$.right_controls;this.collapsingControlsEl_=this.$.collapsing_controls;this.sidePanelContainer_=this.$.side_panel_container;this.brushingStateController_=new tr.c.BrushingStateController(this);this.findCtl_=this.$.view_find_control;this.findCtl_.controller=new tr.ui.FindController(this.brushingStateController_);this.scriptingCtl_=document.createElement('tr-ui-scripting-control');this.scriptingCtl_.controller=new tr.c.ScriptingController(this.brushingStateController_);this.sidePanelContainer_.brushingStateController=this.brushingStateController_;if(window.tr.metrics&&window.tr.metrics.sh&&window.tr.metrics.sh.SystemHealthMetric){this.railScoreSpan_=document.createElement('tr-metrics-ui-sh-system-health-span');Polymer.dom(this.rightControls).appendChild(this.railScoreSpan_);}else{this.railScoreSpan_=undefined;} -this.flowEventFilter_=this.$.flow_event_filter_dropdown;this.processFilter_=this.$.process_filter_dropdown;this.optionsDropdown_=this.$.view_options_dropdown;this.selectedFlowEvents_=new Set();this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.ui.b.createCheckBox(this,'highlightVSync','tr.ui.TimelineView.highlightVSync',false,'Highlight VSync');Polymer.dom(this.optionsDropdown_).appendChild(this.highlightVSyncCheckbox_);this.initMetadataButton_();this.initConsoleButton_();this.initHelpButton_();Polymer.dom(this.collapsingControls).appendChild(this.scriptingCtl_);this.dragEl_=this.$.drag_handle;this.analysisEl_=this.$.analysis;this.analysisEl_.brushingStateController=this.brushingStateController_;this.addEventListener('requestSelectionChange',function(e){const sc=this.brushingStateController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);this.bindKeyListeners_();this.dragEl_.target=this.analysisEl_;},get globalMode(){return this.hotkeyController.globalMode;},set globalMode(globalMode){globalMode=!!globalMode;this.brushingStateController_.historyEnabled=globalMode;this.hotkeyController.globalMode=globalMode;},get hotkeyController(){return this.$.hkc;},warnPolyfill(){if(this.polyfillWarnedOnce_)return;console.warn(POLYFILL_WARNING_MESSAGE);this.polyfillWarnedOnce_=true;if(!window.__hideTraceViewerPolyfillWarning){const polyfillWarningsEl=Polymer.dom(this.root).querySelector('#polyfill-warning');polyfillWarningsEl.addMessage(POLYFILL_WARNING_MESSAGE,[{buttonText:'Hide',onClick:()=>polyfillWarningsEl.clearMessages()}]);}},updateDocumentFavicon(){let hue;if(!this.model){hue='blue';}else{hue=this.model.faviconHue;} +this.flowEventFilter_=this.$.flow_event_filter_dropdown;this.processFilter_=this.$.process_filter_dropdown;this.optionsDropdown_=this.$.view_options_dropdown;this.selectedFlowEvents_=new Set();this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.ui.b.createCheckBox(this,'highlightVSync','tr.ui.TimelineView.highlightVSync',false,'Highlight VSync');Polymer.dom(this.optionsDropdown_).appendChild(this.highlightVSyncCheckbox_);this.initMetadataButton_();this.initConsoleButton_();this.initHelpButton_();Polymer.dom(this.collapsingControls).appendChild(this.scriptingCtl_);this.dragEl_=this.$.drag_handle;this.analysisEl_=this.$.analysis;this.analysisEl_.brushingStateController=this.brushingStateController_;this.addEventListener('requestSelectionChange',function(e){const sc=this.brushingStateController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);this.bindKeyListeners_();this.dragEl_.target=this.analysisEl_;},get globalMode(){return this.hotkeyController.globalMode;},set globalMode(globalMode){globalMode=!!globalMode;this.brushingStateController_.historyEnabled=globalMode;this.hotkeyController.globalMode=globalMode;},get hotkeyController(){return this.$.hkc;},warnPolyfill(){if(this.polyfillWarnedOnce_)return;console.warn(POLYFILL_WARNING_MESSAGE);this.polyfillWarnedOnce_=true;},updateDocumentFavicon(){let hue;if(!this.model){hue='blue';}else{hue=this.model.faviconHue;} let faviconData=tr.ui.b.FaviconsByHue[hue];if(faviconData===undefined){faviconData=tr.ui.b.FaviconsByHue.blue;} let link=Polymer.dom(document.head).querySelector('link[rel="shortcut icon"]');if(!link){link=document.createElement('link');link.rel='shortcut icon';Polymer.dom(document.head).appendChild(link);} link.href=faviconData;},get selectedFlowEvents(){return this.selectedFlowEvents_;},set selectedFlowEvents(selectedFlowEvents){this.selectedFlowEvents_=selectedFlowEvents;},get highlightVSync(){return this.highlightVSync_;},set highlightVSync(highlightVSync){this.highlightVSync_=highlightVSync;if(!this.trackView_)return;this.trackView_.viewport.highlightVSync=highlightVSync;},initHelpButton_(){const helpButtonEl=this.$.view_help_button;const dlg=new tr.ui.b.Overlay();dlg.title='Chrome Tracing Help';dlg.visible=false;dlg.appendChild(document.createElement('tr-ui-timeline-view-help-overlay'));function onClick(e){dlg.visible=!dlg.visible;e.stopPropagation();} @@ -9954,7 +10031,8 @@ if(metadata.name==='metadata'&&metadata.value&&metadata.value['trace-config']&&m if(config){return{excluded:config.excluded_categories||[],included:config.included_categories||[],};}}} 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 validateDiagnosticNames(histograms){for(const hist of histograms){for(const name of hist.diagnostics.keys()){if(name===tr.v.d.RESERVED_NAMES.ALERT_GROUPING){continue;} +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;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);if(model.canonicalUrl!==undefined){const info=tr.v.d.RESERVED_INFOS.TRACE_URLS;histograms.addSharedDiagnosticToAllHistograms(info.name,new info.type([model.canonicalUrl]));} diff --git a/catapult/systrace/systrace/tracing_agents/atrace_agent.py b/catapult/systrace/systrace/tracing_agents/atrace_agent.py index 95046850..05c4330d 100644 --- a/catapult/systrace/systrace/tracing_agents/atrace_agent.py +++ b/catapult/systrace/systrace/tracing_agents/atrace_agent.py @@ -104,7 +104,8 @@ def try_create_agent(config): 'Your device SDK version is %d.' % device_sdk_version) return None - return AtraceAgent(device_sdk_version, util.get_tracing_path()) + return AtraceAgent(device_sdk_version, + util.get_tracing_path(config.device_serial_number)) def _construct_extra_atrace_args(config, categories): """Construct extra arguments (-a, -k, categories) for atrace command. diff --git a/catapult/systrace/systrace/util.py b/catapult/systrace/systrace/util.py index 02981458..063f9ed9 100644 --- a/catapult/systrace/systrace/util.py +++ b/catapult/systrace/systrace/util.py @@ -52,7 +52,7 @@ def run_adb_shell(shell_args, device_serial): return (adb_output, adb_return_code) -def get_tracing_path(): +def get_tracing_path(device_serial=None): """Uses adb to attempt to determine tracing path. The newest kernel doesn't support mounting debugfs, so the Android master uses tracefs to replace it. @@ -62,12 +62,14 @@ def get_tracing_path(): /sys/kernel/debug/tracing if support can't be determined. """ mount_info_args = ['mount'] - parser = OptionParserIgnoreErrors() - parser.add_option('-e', '--serial', dest='device_serial', type='string') - options, _ = parser.parse_args() - adb_output, adb_return_code = run_adb_shell(mount_info_args, - options.device_serial) + if device_serial is None: + parser = OptionParserIgnoreErrors() + parser.add_option('-e', '--serial', dest='device_serial', type='string') + options, _ = parser.parse_args() + device_serial = options.device_serial + + adb_output, adb_return_code = run_adb_shell(mount_info_args, device_serial) if adb_return_code == 0 and 'debugfs' not in adb_output: return '/sys/kernel/tracing' return '/sys/kernel/debug/tracing' |