summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/catapult/tracing
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/catapult/tracing')
-rw-r--r--chromium/third_party/catapult/tracing/DIR_METADATA4
-rw-r--r--chromium/third_party/catapult/tracing/OWNERS4
-rw-r--r--chromium/third_party/catapult/tracing/PRESUBMIT.py17
-rw-r--r--chromium/third_party/catapult/tracing/bin/PRESUBMIT.py5
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/add_reserved_diagnostics10
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/compare_samples1
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/histograms2csv4
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/histograms2html3
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/html2trace3
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/memory_infra_remote_dump20
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/merge_histograms2
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/proto2json3
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_metric14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_py_tests1
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/snapdragon2trace1
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/trace2html3
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/validate_all_diagnostics24
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/validate_all_metrics12
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/why_imported5
-rw-r--r--chromium/third_party/catapult/tracing/docs/perfetto.md19
-rw-r--r--chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py14
-rw-r--r--chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py10
-rwxr-xr-xchromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py7
-rwxr-xr-xchromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line50
-rw-r--r--chromium/third_party/catapult/tracing/trace_viewer.gni16
-rw-r--r--chromium/third_party/catapult/tracing/tracing/BUILD.gn7
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html4
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html5
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html26
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/largest_contentful_paint.html5
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html23
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/msm_parser.html170
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/msm_parser_test.html106
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html91
-rwxr-xr-xchromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py106
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py13
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html13
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/import.html29
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/import_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html4
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html20
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/__init__.py1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html7
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html256
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html117
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/blink/resource_metric.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/blink/resource_metric_test.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/core_web_vitals_metric.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/core_web_vitals_metric_test.html174
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/count_sum_metric.html81
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/count_sum_metric_test.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/custom_metric.html155
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/custom_metric_test.html273
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/discover.py3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/OWNERS2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html195
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric_test.html138
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html38
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html8
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_segment_filter.html112
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html11
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html26
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html10
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html10
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html123
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html149
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html24
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/persecond_metric_test.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/weblayer_startup_metric.html54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/weblayer_startup_metric_test.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/uma_metric.html88
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/uma_metric_test.html68
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/OWNERS3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html791
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html717
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric.html74
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric_test.html133
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/thread.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/failure.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py14
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/function_handle.py3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py4
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_traces.py3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/mre_result.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py4
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py4
-rw-r--r--chromium/third_party/catapult/tracing/tracing/proto/histogram_proto.py22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/proto/histogram_proto_unittest.py10
-rw-r--r--chromium/third_party/catapult/tracing/tracing/tests.html2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py33
-rw-r--r--chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py5
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html19
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html4
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/base.html2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html9
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html10
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html12
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/utils.html12
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html28
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html27
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html9
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/alert_groups.html35
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py14
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py8
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py15
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html17
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py4
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py25
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram.h1
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram.html24
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram.py24
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_serializer_unittest.py98
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_set.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_test.html57
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py5
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/running_statistics.cc3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html11
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html5
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html95
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html15
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html24
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/check_common.py8
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py7
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html6
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/html2trace.py22
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/merge_traces.py23
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py8
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py33
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py44
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/snapdragon2trace.py6
-rwxr-xr-xchromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/trace2html.py10
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py17
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/update_gni.py2
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py7
-rw-r--r--chromium/third_party/catapult/tracing/tracing_examples/trace_viewer_embedder.html4
-rw-r--r--chromium/third_party/catapult/tracing/tracing_project.py7
197 files changed, 5470 insertions, 928 deletions
diff --git a/chromium/third_party/catapult/tracing/DIR_METADATA b/chromium/third_party/catapult/tracing/DIR_METADATA
new file mode 100644
index 00000000000..592fce2a9d8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/DIR_METADATA
@@ -0,0 +1,4 @@
+monorail {
+ component: "Speed>Tracing"
+}
+team_email: "tracing@chromium.org"
diff --git a/chromium/third_party/catapult/tracing/OWNERS b/chromium/third_party/catapult/tracing/OWNERS
index a2cfbf26769..d4c36899e10 100644
--- a/chromium/third_party/catapult/tracing/OWNERS
+++ b/chromium/third_party/catapult/tracing/OWNERS
@@ -1,13 +1,9 @@
-oysteine@chromium.org # Prefers python reviews.
dproy@chromium.org # Prefers javascript reviews.
khokhlov@google.com
-dberris@chromium.org
# For changes related to system_health/loading_metric.html and its tests.
kouhei@chromium.org
-# TEAM: tracing@chromium.org
-# COMPONENT: Speed>Tracing
# These folks have made huge contributions to the project, but are no longer
# actively reviewing patches.
diff --git a/chromium/third_party/catapult/tracing/PRESUBMIT.py b/chromium/third_party/catapult/tracing/PRESUBMIT.py
index 90442392078..676ca4d8ed6 100644
--- a/chromium/third_party/catapult/tracing/PRESUBMIT.py
+++ b/chromium/third_party/catapult/tracing/PRESUBMIT.py
@@ -2,6 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+
+USE_PYTHON3 = True
+
+
import sys
def _RunArgs(args, input_api):
@@ -16,7 +20,7 @@ def _CheckRegisteredMetrics(input_api, output_api):
results = []
tracing_dir = input_api.PresubmitLocalPath()
out, return_code = _RunArgs(
- [input_api.python_executable,
+ [sys.executable,
input_api.os_path.join(tracing_dir, 'bin', 'validate_all_metrics')],
input_api)
if return_code:
@@ -30,7 +34,7 @@ def _CheckRegisteredDiagnostics(input_api, output_api):
results = []
tracing_dir = input_api.PresubmitLocalPath()
out, return_code = _RunArgs(
- [input_api.python_executable,
+ [sys.executable,
input_api.os_path.join(tracing_dir, 'bin', 'validate_all_diagnostics')],
input_api)
if return_code:
@@ -61,7 +65,8 @@ def _CheckHistogramProtoIsGated(input_api, output_api):
for f in input_api.AffectedSourceFiles(source_file_filter):
contents = input_api.ReadFile(f)
if ('histogram_pb2' in contents and
- not f.LocalPath().endswith('histogram_proto.py')):
+ not f.LocalPath().endswith('histogram_proto.py') and
+ not f.LocalPath().endswith('PRESUBMIT.py')):
files.append(f)
results = []
@@ -109,7 +114,7 @@ def _CheckChange(input_api, output_api):
original_sys_path = sys.path
try:
sys.path += [input_api.PresubmitLocalPath()]
- from tracing_build import check_gni
+ from tracing_build import check_gni # pylint: disable=import-outside-toplevel
error = check_gni.GniCheck()
if error:
results.append(output_api.PresubmitError(error))
@@ -120,7 +125,7 @@ def _CheckChange(input_api, output_api):
files_to_skip = input_api.DEFAULT_FILES_TO_SKIP + (".*_pb2.py$",)
results += input_api.RunTests(input_api.canned_checks.GetPylint(
input_api, output_api, extra_paths_list=_GetPathsToPrepend(input_api),
- pylintrc='../pylintrc', files_to_skip=files_to_skip))
+ pylintrc='../pylintrc', files_to_skip=files_to_skip, version='2.7'))
results += _CheckRegisteredMetrics(input_api, output_api)
results += _CheckRegisteredDiagnostics(input_api, output_api)
@@ -132,7 +137,7 @@ def _CheckChange(input_api, output_api):
def _GetPathsToPrepend(input_api):
- import tracing_project
+ import tracing_project # pylint: disable=import-outside-toplevel
project_dir = input_api.PresubmitLocalPath()
catapult_dir = input_api.os_path.join(project_dir, '..')
return [
diff --git a/chromium/third_party/catapult/tracing/bin/PRESUBMIT.py b/chromium/third_party/catapult/tracing/bin/PRESUBMIT.py
index 799215d729d..084bf71ec06 100644
--- a/chromium/third_party/catapult/tracing/bin/PRESUBMIT.py
+++ b/chromium/third_party/catapult/tracing/bin/PRESUBMIT.py
@@ -1,6 +1,11 @@
# Copyright 2015 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.
+
+
+USE_PYTHON3 = True
+
+
import os
def CheckChange(input_api, output_api):
diff --git a/chromium/third_party/catapult/tracing/bin/add_reserved_diagnostics b/chromium/third_party/catapult/tracing/bin/add_reserved_diagnostics
index 988862ed4f7..10c6b352778 100755
--- a/chromium/third_party/catapult/tracing/bin/add_reserved_diagnostics
+++ b/chromium/third_party/catapult/tracing/bin/add_reserved_diagnostics
@@ -3,10 +3,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from __future__ import print_function
import argparse
import json
import sys
import os
+import six
tracing_path = os.path.abspath(os.path.join(
os.path.dirname(os.path.realpath(__file__)), '..'))
@@ -69,7 +71,7 @@ def main():
args = parser.parse_args()
names_to_values = {}
- for name, value in vars(args).iteritems():
+ for name, value in six.iteritems(vars(args)):
if name == LOG_URLS_K and value is not None:
v_value = vars(args)[LOG_URLS_V]
names_to_values[reserved_infos.LOG_URLS.name] = [value, v_value]
@@ -94,16 +96,16 @@ def main():
if args.stdout:
assert len(json_batches) == 1, len(json_batches)
- print json_batches[0]
+ print(json_batches[0])
else:
path = args.output_path or args.input_path
if len(json_batches) == 1:
- with open(path, 'w') as f:
+ with open(path, 'wb') as f:
f.write(json_batches[0])
else:
base, ext = os.path.splitext(path)
for i, hs in enumerate(json_batches):
- with open('%s.%04d%s' % (base, i, ext), 'w') as f:
+ with open('%s.%04d%s' % (base, i, ext), 'wb') as f:
f.write(hs)
return 0
diff --git a/chromium/third_party/catapult/tracing/bin/compare_samples b/chromium/third_party/catapult/tracing/bin/compare_samples
index 0d67a997837..b39a4f053ce 100755
--- a/chromium/third_party/catapult/tracing/bin/compare_samples
+++ b/chromium/third_party/catapult/tracing/bin/compare_samples
@@ -3,6 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from __future__ import print_function
import argparse
import os
import sys
diff --git a/chromium/third_party/catapult/tracing/bin/histograms2csv b/chromium/third_party/catapult/tracing/bin/histograms2csv
index c36246ec3d2..84c10a8a5da 100755
--- a/chromium/third_party/catapult/tracing/bin/histograms2csv
+++ b/chromium/third_party/catapult/tracing/bin/histograms2csv
@@ -4,8 +4,6 @@
# found in the LICENSE file.
import argparse
-import codecs
-import json
import sys
import os
@@ -33,7 +31,7 @@ def main():
if result.returncode != 0:
sys.stderr.write(result.stdout)
else:
- file(args.csv_path, 'w').write(result.stdout)
+ open(args.csv_path, 'w').write(result.stdout)
return result.returncode
if __name__ == '__main__':
diff --git a/chromium/third_party/catapult/tracing/bin/histograms2html b/chromium/third_party/catapult/tracing/bin/histograms2html
index 454c98d154f..7e73628f064 100755
--- a/chromium/third_party/catapult/tracing/bin/histograms2html
+++ b/chromium/third_party/catapult/tracing/bin/histograms2html
@@ -8,6 +8,7 @@ import codecs
import json
import sys
import os
+import six
tracing_path = os.path.abspath(os.path.join(
os.path.dirname(os.path.realpath(__file__)), '..'))
@@ -42,7 +43,7 @@ def main():
histograms.extend(json.load(open(json_path, 'r')))
for json_path in args.mapresults:
- for filename, results in json.load(open(json_path, 'r')).iteritems():
+ for filename, results in six.iteritems(json.load(open(json_path, 'r'))):
for histogram in results['pairs']['histograms']:
histograms.append(histogram)
diff --git a/chromium/third_party/catapult/tracing/bin/html2trace b/chromium/third_party/catapult/tracing/bin/html2trace
index 82161fb1cfd..85ccff80316 100755
--- a/chromium/third_party/catapult/tracing/bin/html2trace
+++ b/chromium/third_party/catapult/tracing/bin/html2trace
@@ -3,6 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from __future__ import print_function
import argparse
import codecs
import sys
@@ -46,7 +47,7 @@ def main():
html_file, args.trace_path, gzipped_output)
if not args.quiet:
- print '\n'.join(saved_paths)
+ print('\n'.join(saved_paths))
if __name__ == '__main__':
diff --git a/chromium/third_party/catapult/tracing/bin/memory_infra_remote_dump b/chromium/third_party/catapult/tracing/bin/memory_infra_remote_dump
index 3125e9fe10d..4f821d68529 100755
--- a/chromium/third_party/catapult/tracing/bin/memory_infra_remote_dump
+++ b/chromium/third_party/catapult/tracing/bin/memory_infra_remote_dump
@@ -31,6 +31,7 @@ $ ./third_party/catapult/tracing/bin/memory_infra_remote_dump --port=1234
/var/folders/18/gl6q632j20nc_tw5g9l03dhc007g45/T/trace_20s191.json: 835 KB
"""
+from __future__ import print_function
import argparse
import json
import os
@@ -38,11 +39,12 @@ import requests
import sys
import tempfile
import time
+from six.moves import input
try:
import websocket
except ImportError:
- print 'Please run: pip install --user websocket-client'
+ print('Please run: pip install --user websocket-client')
sys.exit(1)
@@ -50,7 +52,7 @@ class TracingDevtoolsClient(object):
def __init__(self, host, port):
r = requests.get('http://%s:%s/json/version' % (host, port))
url = r.json()['webSocketDebuggerUrl']
- print 'Connecting to ' + url
+ print('Connecting to ' + url)
self.ws = websocket.create_connection(url)
self.cmd = 0
@@ -66,10 +68,10 @@ class TracingDevtoolsClient(object):
return json.loads(self.ws.recv())
def req_memory_dump(self):
- print 'Requesting memory dump...',
+ print('Requesting memory dump...', end=' ')
resp = self.send('Tracing.requestMemoryDump')
assert resp['success'] == True
- print ' ...done'
+ print(' ...done')
def dump(self, trace_fd):
trace_config = {
@@ -77,7 +79,7 @@ class TracingDevtoolsClient(object):
'includedCategories': ['disabled-by-default-memory-infra'],
'memoryDumpConfig': {'triggers': []}
}
- print 'Starting trace with trace_config', trace_config
+ print('Starting trace with trace_config', trace_config)
params = {'traceConfig': trace_config, 'transferMode': 'ReturnAsStream'}
self.send('Tracing.start', params)
self.req_memory_dump()
@@ -85,8 +87,8 @@ class TracingDevtoolsClient(object):
if sys.stdin.isatty():
while True:
try:
- print '[Press enter to trigger a new dump, q to finish the trace]'
- cmd = raw_input()
+ print('[Press enter to trigger a new dump, q to finish the trace]')
+ cmd = input()
except KeyboardInterrupt:
break
if cmd == 'q':
@@ -96,7 +98,7 @@ class TracingDevtoolsClient(object):
self.send('Tracing.end')
# Wait for trace completion
- print 'Flushing trace'
+ print('Flushing trace')
resp = self.recv()
assert resp['method'] == 'Tracing.tracingComplete'
stream_handle = resp['params']['stream']
@@ -128,4 +130,4 @@ if __name__ == '__main__':
cli = TracingDevtoolsClient(args.host, args.port)
cli.dump(trace_fd)
- print '\n%s: %d KB' % (trace_fd.name, os.stat(trace_fd.name).st_size / 1000)
+ print('\n%s: %d KB' % (trace_fd.name, os.stat(trace_fd.name).st_size / 1000))
diff --git a/chromium/third_party/catapult/tracing/bin/merge_histograms b/chromium/third_party/catapult/tracing/bin/merge_histograms
index ebf65d8615c..403715590ed 100755
--- a/chromium/third_party/catapult/tracing/bin/merge_histograms
+++ b/chromium/third_party/catapult/tracing/bin/merge_histograms
@@ -25,7 +25,7 @@ def Main(argv):
args = parser.parse_args(argv[1:])
merged = merge_histograms.MergeHistograms(args.input, args.groupby)
- json.dump(merged, file(args.output, 'w'))
+ json.dump(merged, open(args.output, 'w'))
return 0
if __name__ == '__main__':
diff --git a/chromium/third_party/catapult/tracing/bin/proto2json b/chromium/third_party/catapult/tracing/bin/proto2json
index b81c012de9a..792d75e333d 100755
--- a/chromium/third_party/catapult/tracing/bin/proto2json
+++ b/chromium/third_party/catapult/tracing/bin/proto2json
@@ -3,6 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from __future__ import print_function
import argparse
import os
import json
@@ -24,7 +25,7 @@ def main():
with open(args.proto_path, "rb") as f:
hs.ImportProto(f.read())
- print(json.dumps(hs.AsDicts(), indent=4))
+ print((json.dumps(hs.AsDicts(), indent=4)))
if __name__ == '__main__':
sys.exit(main())
diff --git a/chromium/third_party/catapult/tracing/bin/run_metric b/chromium/third_party/catapult/tracing/bin/run_metric
index 968f1ae42ef..07e7aca15e6 100755
--- a/chromium/third_party/catapult/tracing/bin/run_metric
+++ b/chromium/third_party/catapult/tracing/bin/run_metric
@@ -3,11 +3,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from __future__ import print_function
import argparse
import codecs
import json
import os
import sys
+import six
sys.path.insert(1, os.path.join(os.path.dirname(__file__), '..'))
from tracing_build import vulcanize_histograms_viewer
@@ -54,8 +56,8 @@ def Main(argv):
failures = []
histograms = []
- for trace_url, mre_result in metric_runner.RunMetricOnTraces(
- traces, args.metrics).iteritems():
+ for trace_url, mre_result in six.iteritems(metric_runner.RunMetricOnTraces(
+ traces, args.metrics)):
failures.extend(mre_result.failures)
histograms.extend(mre_result.pairs.get('histograms', []))
@@ -68,22 +70,22 @@ def Main(argv):
histograms = hset.AsDicts()
if failures:
- print 'Running metric failed:'
+ print('Running metric failed:')
for failure in failures:
- print failure.stack
+ print(failure.stack)
output_file = args.filename + '.html'
open(output_file, 'a').close() # Create file if it doesn't exist.
with codecs.open(output_file, mode='r+', encoding='utf-8') as output_stream:
vulcanize_histograms_viewer.VulcanizeAndRenderHistogramsViewer(
histograms, output_stream, args.reset)
- print 'HTML result created in file://' + os.path.abspath(output_file)
+ print('HTML result created in file://' + os.path.abspath(output_file))
if args.also_output_json:
output_file = args.filename + '.json'
with open(output_file, 'w') as f:
json.dump(histograms, f, indent=2, sort_keys=True, separators=(',', ': '))
- print 'JSON result created in file://' + os.path.abspath(output_file)
+ print('JSON result created in file://' + os.path.abspath(output_file))
if __name__ == '__main__':
diff --git a/chromium/third_party/catapult/tracing/bin/run_py_tests b/chromium/third_party/catapult/tracing/bin/run_py_tests
index e81cb180b79..46796ed30ea 100755
--- a/chromium/third_party/catapult/tracing/bin/run_py_tests
+++ b/chromium/third_party/catapult/tracing/bin/run_py_tests
@@ -4,7 +4,6 @@
# found in the LICENSE file.
import os
-import platform
import sys
_CATAPULT_PATH = os.path.abspath(
diff --git a/chromium/third_party/catapult/tracing/bin/snapdragon2trace b/chromium/third_party/catapult/tracing/bin/snapdragon2trace
index fee277b5fc5..cf952ac6085 100755
--- a/chromium/third_party/catapult/tracing/bin/snapdragon2trace
+++ b/chromium/third_party/catapult/tracing/bin/snapdragon2trace
@@ -26,7 +26,6 @@ file.
"""
import argparse
-import codecs
import sys
import os
diff --git a/chromium/third_party/catapult/tracing/bin/trace2html b/chromium/third_party/catapult/tracing/bin/trace2html
index e1e56702268..803c7860851 100755
--- a/chromium/third_party/catapult/tracing/bin/trace2html
+++ b/chromium/third_party/catapult/tracing/bin/trace2html
@@ -1,8 +1,9 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python
# Copyright (c) 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 __future__ import absolute_import
import sys
import os
diff --git a/chromium/third_party/catapult/tracing/bin/validate_all_diagnostics b/chromium/third_party/catapult/tracing/bin/validate_all_diagnostics
index f8bd5badaf0..7548cc31080 100755
--- a/chromium/third_party/catapult/tracing/bin/validate_all_diagnostics
+++ b/chromium/third_party/catapult/tracing/bin/validate_all_diagnostics
@@ -3,10 +3,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import argparse
import json
import os
-import string
import sys
sys.path.insert(
@@ -58,16 +56,16 @@ def CheckPythonDiagnostics():
return_code = 0
if unregistered_diagnostics:
- print ('These diagnostics are unregistered: %s. Please add them to '
- 'tracing/tracing/value/diagnostics/all_diagnostics.py.' %
- ', '.join(unregistered_diagnostics))
+ print('These diagnostics are unregistered: %s. Please add them to '
+ 'tracing/tracing/value/diagnostics/all_diagnostics.py.' %
+ ', '.join(unregistered_diagnostics))
return_code = 1
for name in all_diagnostics.GetDiagnosticTypenames():
diagnostic = all_diagnostics.GetDiagnosticClassForName(name)
if name != diagnostic.__name__:
- print 'This diagnostic refers to the wrong class: %s: %s' % (
- name, diagnostic.__name__)
+ print('This diagnostic refers to the wrong class: %s: %s' % (
+ name, diagnostic.__name__))
return_code = 1
return return_code
@@ -86,10 +84,10 @@ def CheckJSDiagnostics():
unregistered_diagnostics = (all_possible_diagnostics -
all_registered_diagnostics)
if unregistered_diagnostics:
- print ('These diagnostics are unregistered: %s. Please import their modules in '
- 'tracing/tracing/value/diagnostics/all_diagnostics.html and '
- 'ensure that they call Diagnostic.register().' %
- ', '.join(unregistered_diagnostics))
+ print('These diagnostics are unregistered: %s. Please import their modules in '
+ 'tracing/tracing/value/diagnostics/all_diagnostics.html and '
+ 'ensure that they call Diagnostic.register().' %
+ ', '.join(unregistered_diagnostics))
return 1
lowercased_diagnostics = []
@@ -97,8 +95,8 @@ def CheckJSDiagnostics():
if str.islower(m[0]):
lowercased_diagnostics.append(m)
if lowercased_diagnostics:
- print ('These diagnostics must be renamed to start with a upper-case: %s' %
- lowercased_diagnostics)
+ print('These diagnostics must be renamed to start with a upper-case: %s' %
+ lowercased_diagnostics)
return 1
return 0
diff --git a/chromium/third_party/catapult/tracing/bin/validate_all_metrics b/chromium/third_party/catapult/tracing/bin/validate_all_metrics
index b4b26307bc1..b38cac3ef6c 100755
--- a/chromium/third_party/catapult/tracing/bin/validate_all_metrics
+++ b/chromium/third_party/catapult/tracing/bin/validate_all_metrics
@@ -3,10 +3,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import argparse
-import json
+from __future__ import print_function
import os
-import string
import sys
sys.path.insert(
@@ -25,16 +23,16 @@ def Main():
all_possible_metrics = set(discover.DiscoverMetrics(all_modules))
unregistered_metrics = all_possible_metrics - all_registered_metrics
if unregistered_metrics:
- print ('These metrics are unregistered: %s. Please import their modules in '
- 'tracing/tracing/metrics/all_metrics.html' %
- ', '.join(unregistered_metrics))
+ print('These metrics are unregistered: %s. Please import their modules in '
+ 'tracing/tracing/metrics/all_metrics.html' %
+ ', '.join(unregistered_metrics))
return 1
uppercased_metrics = []
for m in all_possible_metrics:
if str.isupper(m[0]):
uppercased_metrics.append(m)
if uppercased_metrics:
- print ('These metrics must be renamed to start with a lower-case: %s' %
+ print('These metrics must be renamed to start with a lower-case: %s' %
uppercased_metrics)
return 1
return 0
diff --git a/chromium/third_party/catapult/tracing/bin/why_imported b/chromium/third_party/catapult/tracing/bin/why_imported
index 9b5a59a6f49..04a134681f7 100755
--- a/chromium/third_party/catapult/tracing/bin/why_imported
+++ b/chromium/third_party/catapult/tracing/bin/why_imported
@@ -15,6 +15,7 @@ This can then be converted to a graphical representation with the dot tool:
$ dot -Grankdir=LR -Tpng ~/analysis_view.dot -o ~/analysis_view.png
"""
+from __future__ import print_function
import os
import sys
import argparse
@@ -35,8 +36,8 @@ def Main():
load_sequence = vulcanizer.CalcLoadSequenceForModuleNames(names)
else:
parser.error('No config specified.')
- print vulcanizer.GetDominatorGraphForModulesNamed(
- args.module_names, load_sequence)
+ print(vulcanizer.GetDominatorGraphForModulesNamed(
+ args.module_names, load_sequence))
if __name__ == '__main__':
diff --git a/chromium/third_party/catapult/tracing/docs/perfetto.md b/chromium/third_party/catapult/tracing/docs/perfetto.md
new file mode 100644
index 00000000000..1ec78be2d27
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/docs/perfetto.md
@@ -0,0 +1,19 @@
+**July 2022 update**: chrome://tracing is deprecated, and by default will
+redirect to https://ui.perfetto.dev. At the moment, it's still possible to use
+the old UI, but there's no guarantee that it will continue to function;
+please file [feature requests](https://perfetto.dev/docs/#bugs) for any
+blockers that prevent you from migrating from chrome://tracing to Perfetto.
+
+[Perfetto](https://perfetto.dev) is an evolution of chrome://tracing. Try it
+out!
+
+Perfetto offers various advantages, including:
+
+* Support for larger trace sizes and more responsive trace navigation
+* Interactive SQL queries to analyze the trace model
+* Android system trace recording via WebUSB
+
+So far, the Perfetto UI has been optimized for use cases on Android. If your
+Chromium use case could be supported in better ways, or if you're missing a
+loved feature from the catapult viewer, please leave us
+[feedback](https://perfetto.dev/docs/#bugs).
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py
index b4d94ae225b..2060f251606 100644
--- a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py
@@ -2,14 +2,24 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+
+USE_PYTHON3 = True
+
+
def CommonChecks(input_api, output_api):
output = []
- output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+ output.extend(input_api.RunTests(input_api.canned_checks.GetPylint(
+ input_api,
+ output_api,
+ version='2.7')))
output.extend(input_api.canned_checks.RunUnitTestsInDirectory(
input_api,
output_api,
input_api.PresubmitLocalPath(),
- whitelist=[r'^.+_unittest\.py$']))
+ files_to_check=[r'^.+_unittest\.py$'],
+ run_on_python2=False,
+ run_on_python3=True,
+ skip_shebang_check=True))
return output
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py
index 9deec868368..4db186721fa 100644
--- a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py
@@ -26,7 +26,7 @@ except ImportError:
ADDR2LINE_RECYCLE_LIMIT = 4000
-class ELFSymbolizer(object):
+class ELFSymbolizer:
"""An uber-fast (multiprocessing, pipelined and asynchronous) ELF symbolizer.
This class is a frontend for addr2line (part of GNU binutils), designed to
@@ -201,7 +201,7 @@ class ELFSymbolizer(object):
(time.time() - start_time))
- class Addr2Line(object):
+ class Addr2Line:
"""A python wrapper around an addr2line instance.
The communication with the addr2line process looks as follows:
@@ -397,7 +397,7 @@ class ELFSymbolizer(object):
if self._symbolizer.inlines:
cmd += ['--inlines']
self._proc = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE,
- stdin=subprocess.PIPE, stderr=sys.stderr, close_fds=True)
+ stdin=subprocess.PIPE, stderr=sys.stderr, close_fds=True, text=True)
# Start the poller thread, which simply moves atomically the lines read
# from the addr2line's stdout to the |_out_queue|.
@@ -441,7 +441,7 @@ class ELFSymbolizer(object):
process_pipe.close()
# Every addr2line processes will die at some point, please die silently.
- except (IOError, OSError):
+ except (IOError, OSError, ValueError):
pass
@property
@@ -450,7 +450,7 @@ class ELFSymbolizer(object):
return self._request_queue[0][2] if self._request_queue else 0
-class ELFSymbolInfo(object):
+class ELFSymbolInfo:
"""The result of the symbolization passed as first arg. of each callback."""
def __init__(self, name, source_path, source_line, was_ambiguous=False,
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py
index d7978aba0f8..130f0139a16 100755
--- a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py
@@ -10,7 +10,6 @@ import sys
import unittest
sys.path.insert(0, os.path.dirname(__file__))
-# pylint: disable=relative-import
import elf_symbolizer
import mock_addr2line
@@ -58,7 +57,7 @@ class ELFSymbolizerTest(unittest.TestCase):
inlines=True,
max_concurrent_jobs=4)
- for addr in xrange(1000):
+ for addr in range(1000):
exp_inline = False
exp_unknown = False
@@ -128,7 +127,7 @@ class ELFSymbolizerTest(unittest.TestCase):
max_concurrent_jobs=max_concurrent_jobs,
addr2line_timeout=0.5)
- for addr in xrange(num_symbols):
+ for addr in range(num_symbols):
exp_name = 'mock_sym_for_addr_%d' % addr
exp_source_path = 'mock_src/mock_lib1.so.c'
exp_source_line = addr
@@ -138,7 +137,7 @@ class ELFSymbolizerTest(unittest.TestCase):
symbolizer.Join()
# Check that all the expected callbacks have been received.
- for addr in xrange(num_symbols):
+ for addr in range(num_symbols):
self.assertIn(addr, self._resolved_addresses)
self._resolved_addresses.remove(addr)
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line
index 5544359ad60..7ae89a08934 100755
--- a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# 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.
@@ -9,21 +9,21 @@ Outputs mock symbol information, with each symbol being a function of the
original address (so it is easy to double-check consistency in unittests).
"""
-import optparse
+import argparse
import os
import posixpath
import sys
import time
-def main(argv):
- parser = optparse.OptionParser()
- parser.add_option('-e', '--exe', dest='exe') # Path of the debug-library.so.
+def main(args=None):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-e', '--exe') # Path of the debug-library.so.
# Silently swallow the other unnecessary arguments.
- parser.add_option('-C', '--demangle', action='store_true')
- parser.add_option('-f', '--functions', action='store_true')
- parser.add_option('-i', '--inlines', action='store_true')
- options, _ = parser.parse_args(argv[1:])
+ parser.add_argument('-C', '--demangle', action='store_true')
+ parser.add_argument('-f', '--functions', action='store_true')
+ parser.add_argument('-i', '--inlines', action='store_true')
+ options = parser.parse_args()
lib_file_name = posixpath.basename(options.exe)
processed_sym_count = 0
crash_every = int(os.environ.get('MOCK_A2L_CRASH_EVERY', 0))
@@ -36,8 +36,8 @@ def main(argv):
# An empty line should generate '??,??:0' (is used as marker for inlines).
if line == '\n':
- print '??'
- print '??:0'
+ print('??')
+ print('??:0')
sys.stdout.flush()
continue
@@ -50,31 +50,31 @@ def main(argv):
# Addresses < 1M will return good mock symbol information.
if addr < 1024 * 1024:
- print 'mock_sym_for_addr_%d' % addr
- print 'mock_src/%s.c:%d' % (lib_file_name, addr)
+ print('mock_sym_for_addr_%d' % addr)
+ print('mock_src/%s.c:%d' % (lib_file_name, addr))
# Addresses 1M <= x < 2M will return symbols with a name but a missing path.
elif addr < 2 * 1024 * 1024:
- print 'mock_sym_for_addr_%d' % addr
- print '??:0'
+ print('mock_sym_for_addr_%d' % addr)
+ print('??:0')
# Addresses 2M <= x < 3M will return unknown symbol information.
elif addr < 3 * 1024 * 1024:
- print '??'
- print '??'
+ print('??')
+ print('??')
# Addresses 3M <= x < 4M will return inlines.
elif addr < 4 * 1024 * 1024:
- print 'mock_sym_for_addr_%d_inner' % addr
- print 'mock_src/%s.c:%d' % (lib_file_name, addr)
- print 'mock_sym_for_addr_%d_middle' % addr
- print 'mock_src/%s.c:%d' % (lib_file_name, addr)
- print 'mock_sym_for_addr_%d_outer' % addr
- print 'mock_src/%s.c:%d' % (lib_file_name, addr)
+ print('mock_sym_for_addr_%d_inner' % addr)
+ print('mock_src/%s.c:%d' % (lib_file_name, addr))
+ print('mock_sym_for_addr_%d_middle' % addr)
+ print('mock_src/%s.c:%d' % (lib_file_name, addr))
+ print('mock_sym_for_addr_%d_outer' % addr)
+ print('mock_src/%s.c:%d' % (lib_file_name, addr))
else:
- print 'mock_sym_for_addr_%d' % addr
- print 'mock_src/%s.c:%d' % (lib_file_name, addr)
+ print('mock_sym_for_addr_%d' % addr)
+ print('mock_src/%s.c:%d' % (lib_file_name, addr))
sys.stdout.flush()
diff --git a/chromium/third_party/catapult/tracing/trace_viewer.gni b/chromium/third_party/catapult/tracing/trace_viewer.gni
index 18d64554a28..d286545782a 100644
--- a/chromium/third_party/catapult/tracing/trace_viewer.gni
+++ b/chromium/third_party/catapult/tracing/trace_viewer.gni
@@ -134,6 +134,7 @@ tracing_js_html_files = [
"tracing/extras/importer/linux_perf/kfunc_parser.html",
"tracing/extras/importer/linux_perf/mali_parser.html",
"tracing/extras/importer/linux_perf/memreclaim_parser.html",
+ "tracing/extras/importer/linux_perf/msm_parser.html",
"tracing/extras/importer/linux_perf/parser.html",
"tracing/extras/importer/linux_perf/power_parser.html",
"tracing/extras/importer/linux_perf/regulator_parser.html",
@@ -197,14 +198,18 @@ tracing_js_html_files = [
"tracing/metrics/android_systrace_metric.html",
"tracing/metrics/blink/gc_metric.html",
"tracing/metrics/blink/leak_detection_metric.html",
+ "tracing/metrics/blink/resource_metric.html",
"tracing/metrics/console_error_metric.html",
+ "tracing/metrics/core_web_vitals_metric.html",
+ "tracing/metrics/count_sum_metric.html",
"tracing/metrics/cpu_process_metric.html",
+ "tracing/metrics/custom_metric.html",
"tracing/metrics/media_metric.html",
- "tracing/metrics/memory_ablation_metric.html",
"tracing/metrics/metric_map_function.html",
"tracing/metrics/metric_registry.html",
+ "tracing/metrics/partition_alloc/pcscan_metric.html",
"tracing/metrics/rendering/cpu_utilization.html",
- "tracing/metrics/rendering/frame_time.html",
+ "tracing/metrics/rendering/frame_segment_filter.html",
"tracing/metrics/rendering/image_decode_time.html",
"tracing/metrics/rendering/pixels.html",
"tracing/metrics/rendering/queueing_duration.html",
@@ -231,6 +236,7 @@ tracing_js_html_files = [
"tracing/metrics/system_health/responsiveness_metric.html",
"tracing/metrics/system_health/screenshots_based_speed_index_metric.html",
"tracing/metrics/system_health/utils.html",
+ "tracing/metrics/system_health/weblayer_startup_metric.html",
"tracing/metrics/system_health/webview_startup_metric.html",
"tracing/metrics/tabs_metric.html",
"tracing/metrics/tracing_metric.html",
@@ -556,6 +562,7 @@ tracing_js_html_files = [
"tracing/ui/tracks/x_axis_track.html",
"tracing/ui/view_specific_brushing_state.html",
"tracing/value/csv_builder.html",
+ "tracing/value/diagnostics/alert_groups.html",
"tracing/value/diagnostics/all_diagnostics.html",
"tracing/value/diagnostics/breakdown.html",
"tracing/value/diagnostics/collected_related_event_set.html",
@@ -684,9 +691,8 @@ py_vulcanize_files = [
"../common/py_vulcanize/third_party/rjsmin/rjsmin.py",
"../common/py_vulcanize/third_party/rjsmin/setup.py",
]
-other_python_files = [
- "tracing_project.py",
-]
+other_python_files = [ "tracing_project.py" ]
+
# python files needed for deterministic builds. See https://crbug.com/1025132.
# This list is manually generated and may become out of date. Please fix it if
# it does so.
diff --git a/chromium/third_party/catapult/tracing/tracing/BUILD.gn b/chromium/third_party/catapult/tracing/tracing/BUILD.gn
index 816fa752e0b..0df405e5cf7 100644
--- a/chromium/third_party/catapult/tracing/tracing/BUILD.gn
+++ b/chromium/third_party/catapult/tracing/tracing/BUILD.gn
@@ -11,7 +11,7 @@ config("common_config") {
}
source_set("histogram") {
- configs += [ ":common_config" ]
+ public_configs = [ ":common_config" ]
sources = [
"value/histogram.cc",
"value/histogram.h",
@@ -25,7 +25,7 @@ source_set("histogram") {
}
source_set("reserved_infos") {
- configs += [ ":common_config" ]
+ public_configs = [ ":common_config" ]
sources = [
"value/diagnostics/reserved_infos.cc",
"value/diagnostics/reserved_infos.h",
@@ -33,7 +33,6 @@ source_set("reserved_infos") {
}
test("histogram_unittests") {
- configs += [ ":common_config" ]
sources = [
"value/histogram_unittest.cc",
"value/running_statistics_unittest.cc",
@@ -46,7 +45,7 @@ test("histogram_unittests") {
deps = [
":histogram",
"proto:histogram_proto",
- "//testing/gtest:gtest_main",
"//testing/gtest:gtest",
+ "//testing/gtest:gtest_main",
]
}
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html
index 1642cd7ec2e..1387d0206c8 100644
--- a/chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html
@@ -503,8 +503,7 @@ tr.exportTo('tr.b.unittest', function() {
},
didAllTestsPass() {
- // A test counts as failing if it failed or it was skipped.
- return this.numTestsThatFailed_ + this.numSkippedTests_ === 0;
+ return this.numTestsThatFailed_ === 0;
},
notifyTestResultToDevServer_(result, extraMsg) {
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html
index 6c14bd5afbf..0a092a0a79a 100644
--- a/chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html
@@ -212,11 +212,11 @@ tr.exportTo('tr.b.unittest', function() {
this.oldGlobalOnError_ = undefined;
},
- constructAndRegisterTestSuite(suiteConstructor) {
+ constructAndRegisterTestSuite(suiteConstructor, opt_options) {
const name = this.currentModuleLoader_.getCurrentlyExecutingModuleName();
const testSuite = new tr.b.unittest.TestSuite(
- name, suiteConstructor);
+ name, suiteConstructor, opt_options);
this.testSuites.push(testSuite);
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html
index 237403fbf05..f0e607273b4 100644
--- a/chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html
@@ -19,7 +19,7 @@ tr.exportTo('tr.b.unittest', function() {
const TestTypes = tr.b.unittest.TestTypes;
- function TestSuite(name, suiteConstructor) {
+ function TestSuite(name, suiteConstructor, opt_suiteOptions) {
this.guid = tr.b.GUID.allocateSimple();
this.name_ = name;
this.tests_ = [];
@@ -36,6 +36,17 @@ tr.exportTo('tr.b.unittest', function() {
}
}.bind(this);
+ global.skipTest = function(testCaseOrName, opt_testFn, opt_options) {
+ if (testCaseOrName instanceof TestCase) {
+ testCaseOrName.options.skipped = true;
+ test(testCaseOrName);
+ } else {
+ const options = Object.assign({}, opt_options || {});
+ options.skipped = true;
+ test(testCaseOrName, opt_testFn, options);
+ }
+ }.bind(this);
+
global.test = function(testCaseOrName, opt_testFn, opt_options) {
if (testCaseOrName instanceof TestCase) {
if (opt_testFn !== undefined) {
@@ -44,6 +55,9 @@ tr.exportTo('tr.b.unittest', function() {
if (opt_options !== undefined) {
throw new Error('opt_options cannot be given when giving a TestCase');
}
+ if (opt_suiteOptions && opt_suiteOptions.skipped) {
+ testCaseOrName.options.skipped = true;
+ }
this.addTest(testCaseOrName);
return;
}
@@ -51,6 +65,9 @@ tr.exportTo('tr.b.unittest', function() {
let testName = testCaseOrName;
const testFn = opt_testFn;
const options = opt_options || {};
+ if (opt_suiteOptions && opt_suiteOptions.skipped) {
+ options.skipped = true;
+ }
if (testFn === undefined) {
throw new Error('Must provide opt_testFn');
}
@@ -100,6 +117,8 @@ tr.exportTo('tr.b.unittest', function() {
} finally {
global.test = undefined;
global.timedPerfTest = undefined;
+ global.flakyTest = undefined;
+ global.skipTest = undefined;
}
}
@@ -127,16 +146,22 @@ tr.exportTo('tr.b.unittest', function() {
}
};
- function testSuite(suiteConstructor) {
+ function testSuite(suiteConstructor, opt_suiteOptions) {
if (!global._currentSuiteLoader) {
throw new Error('testSuites can only be defined during suite loading');
}
- global._currentSuiteLoader.constructAndRegisterTestSuite(suiteConstructor);
+ global._currentSuiteLoader.constructAndRegisterTestSuite(
+ suiteConstructor, opt_suiteOptions);
+ }
+
+ function skippedTestSuite(suiteConstructor) {
+ testSuite(suiteConstructor, {skipped: true});
}
return {
TestSuite,
testSuite,
+ skippedTestSuite,
};
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html
index a010398a1cc..15a2e921d49 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html
@@ -54,11 +54,12 @@ tr.exportTo('tr.e.audits', function() {
for (const slice of asyncSlices) {
if (slice.title === 'PipelineReporter' &&
slice.args.chrome_frame_reporter &&
- slice.args.chrome_frame_reporter.state === 'STATE_DROPPED') {
+ slice.args.chrome_frame_reporter.state === 'STATE_DROPPED' &&
+ slice.args.chrome_frame_reporter.affects_smoothness) {
const alertSlices = [slice].concat(slice.subSlices);
alerts.push(new Alert(
new EventInfo(
- 'Dropped Frame',
+ 'Dropped Frame affecting smoothness',
'Frame was dropped (i.e. not produced/presented).'),
slice.start,
alertSlices));
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html
index 8b41fa056ad..bbc0750b6b9 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html
@@ -150,6 +150,30 @@ tr.b.unittest.testSuite(function() {
}
});
+ const missedFrameSliceNotAffectingSmoothness = newAsyncSliceEx({
+ title: 'PipelineReporter',
+ start: 200,
+ duration: 15,
+ args: {
+ chrome_frame_reporter: {
+ affects_smoothness: false,
+ state: 'STATE_DROPPED'
+ }
+ }
+ });
+
+ const missedFrameSliceAffectingSmoothness = newAsyncSliceEx({
+ title: 'PipelineReporter',
+ start: 200,
+ duration: 15,
+ args: {
+ chrome_frame_reporter: {
+ affects_smoothness: true,
+ state: 'STATE_DROPPED'
+ }
+ }
+ });
+
const missedFrameSlice = newAsyncSliceEx({
title: 'PipelineReporter',
start: 200,
@@ -161,6 +185,8 @@ tr.b.unittest.testSuite(function() {
m.compositorThread.asyncSliceGroup.push(noArgsFrameSlice);
m.compositorThread.asyncSliceGroup.push(submittedFrameSlice);
+ m.compositorThread.asyncSliceGroup.push(missedFrameSliceNotAffectingSmoothness);
+ m.compositorThread.asyncSliceGroup.push(missedFrameSliceAffectingSmoothness);
m.compositorThread.asyncSliceGroup.push(missedFrameSlice);
}, tr.e.audits.ChromeAuditor);
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html
index 69128010fa9..dc8483985a7 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html
@@ -34,6 +34,9 @@ tr.exportTo('tr.e.chrome', function() {
model.rasterWorker1 = model.rendererProcess.getOrCreateThread(5);
model.rasterWorker1.name = 'CompositorTileWorker1';
+ model.foregroundWorker1 = model.rendererProcess.getOrCreateThread(6);
+ model.foregroundWorker1.name = 'ThreadPoolForegroundWorker1';
+
customizeModelCallback(model);
});
};
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html
index 6c046e34b18..f4f5671b022 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html
@@ -82,6 +82,9 @@ tr.exportTo('tr.e.chrome', function() {
'HTMLDocumentParser::processParsedChunkFromBackgroundParser',
'HTMLDocumentParser::processTokenizedChunkFromBackgroundParser',
'ParseHTML',
+ 'HTMLDocumentParser::DeferredPumpTokenizerIfPossible',
+ 'HTMLDocumentParser::PumpTokenizer',
+ 'HTMLDocumentParser::appendBytes',
],
raster: [
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html
index 5251a7d2edc..4c346d1e2ba 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html
@@ -42,7 +42,7 @@ tr.b.unittest.testSuite(function() {
}), 'style');
assert.strictEqual(ufcFromEvent({
guid: tr.b.GUID.allocateSimple(),
- title: 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser',
+ title: 'HTMLDocumentParser::DeferredPumpTokenizerIfPossible',
category: 'cat'
}), 'parseHTML');
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html
index edae6767dfb..fc781613d4f 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html
@@ -44,6 +44,7 @@ tr.b.unittest.testSuite(function() {
function addTestFrame(rendererProcess) {
rendererProcess.objects.addSnapshot(
'ptr', 'loading', 'FrameLoader', 300, {
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/largest_contentful_paint.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/largest_contentful_paint.html
index c61cca1047d..725106ed66e 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/chrome/largest_contentful_paint.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/largest_contentful_paint.html
@@ -89,9 +89,8 @@ tr.exportTo('tr.e.chrome', function() {
findCandidates() {
const finalLcpEvents = this.findFinalLcpEventOfEachNavigation(
this.allBrowserEvents);
- const finalCandidates = finalLcpEvents
- .filter(finalLcpEvent =>
- !LcpInvalidateEvent.isLcpInvalidateEvent(finalLcpEvent));
+ const finalCandidates = finalLcpEvents.filter(finalLcpEvent =>
+ !(finalLcpEvent instanceof LcpInvalidateEvent));
return finalCandidates;
}
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html
index 8fd2fcbf870..80079c7bb7a 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html
@@ -14,7 +14,6 @@ found in the LICENSE file.
tr.exportTo('tr.e.importer.fuchsia', function() {
const IMPORT_PRIORITY = 0;
- const IDLE_THREAD_THRESHOLD = 6444000000;
// Zircon thread state constants from:
// https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_get_info.md
@@ -64,19 +63,12 @@ tr.exportTo('tr.e.importer.fuchsia', function() {
finalizeImport() {
}
- isIdleThread(prio, tid) {
- if (prio === undefined) {
- // If the "prio" field is not available (if we were, for example,
- // using an old trace), then fall back to the legacy heuristic of
- // assuming that large numbered threads are idle ones.
- return tid > IDLE_THREAD_THRESHOLD;
- }
- // A thread is idle iff its priority is set to 0.
- return prio === 0;
+ isIdleThread(pid, prio) {
+ return pid === 0 && prio === 0;
}
- recordThreadState_(tid, timestamp, state, prio) {
- if (this.isIdleThread(prio, tid)) {
+ recordThreadState_(pid, tid, timestamp, state, prio) {
+ if (this.isIdleThread(pid, prio)) {
return;
}
const states =
@@ -104,6 +96,7 @@ tr.exportTo('tr.e.importer.fuchsia', function() {
// },
processContextSwitchEvent_(event) {
let tid = event.in.tid;
+ let pid = event.in.pid;
let threadName = tid.toString();
let procName = '';
const prio = event.in.prio;
@@ -119,7 +112,7 @@ tr.exportTo('tr.e.importer.fuchsia', function() {
const name = procName + threadName;
- if (this.isIdleThread(prio, tid)) {
+ if (this.isIdleThread(pid, prio)) {
tid = undefined; // Fake kernel idle task
}
@@ -128,7 +121,7 @@ tr.exportTo('tr.e.importer.fuchsia', function() {
cpu.switchActiveThread(timestamp, {}, tid, name, tid);
const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
- this.recordThreadState_(tid, timestamp, SCHEDULING_STATE.RUNNING, prio);
+ this.recordThreadState_(pid, tid, timestamp, SCHEDULING_STATE.RUNNING, prio);
let outState = SCHEDULING_STATE.UNKNOWN;
@@ -153,7 +146,7 @@ tr.exportTo('tr.e.importer.fuchsia', function() {
outState = SCHEDULING_STATE.TASK_DEAD;
break;
}
- this.recordThreadState_(event.out.tid, timestamp, outState,
+ this.recordThreadState_(event.out.pid, event.out.tid, timestamp, outState,
event.out.prio);
}
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html
index 048869e22d0..6e5e9c9ac67 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html
@@ -25,6 +25,7 @@ found in the LICENSE file.
<link rel="import" href="/tracing/extras/importer/linux_perf/kfunc_parser.html">
<link rel="import" href="/tracing/extras/importer/linux_perf/mali_parser.html">
<link rel="import" href="/tracing/extras/importer/linux_perf/memreclaim_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/msm_parser.html">
<link rel="import" href="/tracing/extras/importer/linux_perf/power_parser.html">
<link rel="import" href="/tracing/extras/importer/linux_perf/regulator_parser.html">
<link rel="import" href="/tracing/extras/importer/linux_perf/rss_parser.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/msm_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/msm_parser.html
new file mode 100644
index 00000000000..65b06999ddc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/msm_parser.html
@@ -0,0 +1,170 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses drm/msm driver events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux drm/msm trace events.
+ * @constructor
+ */
+ 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; // # of in-flight submits
+ }
+
+ MSMParser.prototype = {
+ __proto__: Parser.prototype,
+
+ // msm_gpu_freq_change: new_freq=180
+ 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;
+ },
+
+ // msm_gpu_submit_flush: id=348500 pid=29590 ring=0:348502 ticks=130364028
+ 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;
+ },
+
+ // msm_gpu_submit_retired: id=348500 pid=29590 ring=0:348501 elapsed=3405520 ns mhz=179 start=130055449 end=130120835 // @suppress longLineCheck
+ gpuSubmitRetired(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /id=(\d+) pid=(\d+) ring=(\d+):(\d+) elapsed=(\d+) ns mhz=(\d+) start=(\d+) end=(\d+)/. // @suppress longLineCheck
+ exec(eventBase.details);
+ if (!event) return false;
+ const id = parseInt(event[1]);
+
+ // If we didn't see the start event (msm_gpu_submit_flush) then just
+ // skip this event:
+ 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]);
+
+ // Ticks are in units of 19.2Mhz alwayson counter, we can derive
+ // the time queued and running from this. The submit_flush trace
+ // captures both the CPU timestamp and the 19.2Mhz counter as read
+ // from the CPU. The submit_retired timestamp includes the value
+ // of the 19.2Mhz counter as read from the GPU before and after
+ // executing the submit.
+ //
+ // The trace timestamps (CPU based) are in ms.
+
+ function ticks2ms(ticks) {
+ return ticks / 19200;
+ }
+
+ const queuedDuration = ticks2ms(submit.startTicks - submit.flushTicks);
+ const runningDuration = ticks2ms(submit.endTicks - submit.startTicks);
+
+ // for debug:
+ submit.queuedDuration = queuedDuration;
+ submit.runningDuration = runningDuration;
+
+ // AsyncSlice's to show when the submit is queued, and begins to run:
+ 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);
+
+ // We don't want the 'async' container slice visible, it just exists to
+ // group the 'queued' and 'running' subslices:
+ async.hidden = true;
+
+ async.subSlices.push(queued);
+ async.subSlices.push(running);
+ gpuThread.thread.asyncSliceGroup.push(async);
+
+ // And the synchronous ThreadSlice shows the time the submit is running
+ // on the gpu:
+ 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,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/msm_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/msm_parser_test.html
new file mode 100644
index 00000000000..fde592ac1af
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/msm_parser_test.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('msmImport', function() {
+ const lines = [
+ ' UnityGfxDeviceW-20803 (20764) [007] .... 2569.637650: msm_gpu_submit_flush: id=164270 pid=20803 ring=0:164271 ticks=5854915894', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.638074: msm_gpu_freq_change: new_freq=180', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [007] .... 2569.638521: msm_gpu_submit_flush: id=164271 pid=20803 ring=0:164272 ticks=5854932654', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.650267: msm_gpu_submit_retired: id=164270 pid=20803 ring=0:164271 elapsed=11198437 ns mhz=179 start=5854916032 end=5855131042', // @suppress longLineCheck
+ ' kworker/u16:1-21183 (21183) [003] .... 2569.650297: msm_gpu_freq_change: new_freq=800', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.652039: msm_gpu_submit_retired: id=164271 pid=20803 ring=0:164272 elapsed=1594895 ns mhz=216 start=5855131119 end=5855161741', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [007] .... 2569.654153: msm_gpu_submit_flush: id=164272 pid=20803 ring=0:164273 ticks=5855232953', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [007] .... 2569.654563: msm_gpu_submit_flush: id=164273 pid=20803 ring=0:164274 ticks=5855240817', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.657140: msm_gpu_submit_retired: id=164272 pid=20803 ring=0:164273 elapsed=2771979 ns mhz=799 start=5855233005 end=5855286227', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.659900: msm_gpu_submit_retired: id=164273 pid=20803 ring=0:164274 elapsed=549166 ns mhz=800 start=5855286249 end=5855296793', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.663715: msm_gpu_freq_change: new_freq=267', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [007] .... 2569.670766: msm_gpu_submit_flush: id=164274 pid=20803 ring=0:164275 ticks=5855552051', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [007] .... 2569.671356: msm_gpu_submit_flush: id=164275 pid=20803 ring=0:164276 ticks=5855563392', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.676930: msm_gpu_freq_change: new_freq=180', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.679942: msm_gpu_submit_retired: id=164274 pid=20803 ring=0:164275 elapsed=8682343 ns mhz=241 start=5855552151 end=5855718852', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.682724: msm_gpu_submit_retired: id=164275 pid=20803 ring=0:164276 elapsed=1663906 ns mhz=179 start=5855718929 end=5855750876', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.688592: msm_gpu_submit_flush: id=164276 pid=20803 ring=0:164277 ticks=5855894498', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.689192: msm_gpu_submit_flush: id=164277 pid=20803 ring=0:164278 ticks=5855906029', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.693595: msm_gpu_freq_change: new_freq=180', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.699896: msm_gpu_submit_retired: id=164276 pid=20803 ring=0:164277 elapsed=11185572 ns mhz=179 start=5855894608 end=5856109371', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.701729: msm_gpu_submit_retired: id=164277 pid=20803 ring=0:164278 elapsed=1686666 ns mhz=180 start=5856109447 end=5856141831', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.704179: msm_gpu_freq_change: new_freq=180', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.704660: msm_gpu_submit_flush: id=164278 pid=20803 ring=0:164279 ticks=5856203141', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.705313: msm_gpu_submit_flush: id=164279 pid=20803 ring=0:164280 ticks=5856215696', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.715973: msm_gpu_freq_change: new_freq=800', // @suppress longLineCheck
+ ' kworker/u16:1-21183 (21183) [003] .... 2569.715991: msm_gpu_submit_retired: id=164278 pid=20803 ring=0:164279 elapsed=11180989 ns mhz=179 start=5856203256 end=5856417931', // @suppress longLineCheck
+ ' kworker/u16:1-21183 (21183) [003] .... 2569.716802: msm_gpu_submit_retired: id=164279 pid=20803 ring=0:164280 elapsed=876718 ns mhz=669 start=5856418010 end=5856434843', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.721188: msm_gpu_submit_flush: id=164280 pid=20803 ring=0:164281 ticks=5856520661', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.721710: msm_gpu_submit_flush: id=164281 pid=20803 ring=0:164282 ticks=5856530679', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.725951: msm_gpu_submit_retired: id=164280 pid=20803 ring=0:164281 elapsed=2776406 ns mhz=799 start=5856520717 end=5856574024', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.726539: msm_gpu_submit_retired: id=164281 pid=20803 ring=0:164282 elapsed=546458 ns mhz=800 start=5856574047 end=5856584539', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.727104: msm_gpu_freq_change: new_freq=355', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.738225: msm_gpu_freq_change: new_freq=180', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.742288: msm_gpu_submit_flush: id=164282 pid=20803 ring=0:164283 ticks=5856925966', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.742994: msm_gpu_submit_flush: id=164283 pid=20803 ring=0:164284 ticks=5856939530', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.749148: msm_gpu_freq_change: new_freq=180', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.753702: msm_gpu_submit_retired: id=164282 pid=20803 ring=0:164283 elapsed=11166041 ns mhz=179 start=5856926090 end=5857140478', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.754644: msm_gpu_submit_flush: id=164284 pid=20803 ring=0:164285 ticks=5857163320', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.755242: msm_gpu_submit_retired: id=164283 pid=20803 ring=0:164284 elapsed=1697864 ns mhz=179 start=5857140557 end=5857173156', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.755419: msm_gpu_submit_flush: id=164285 pid=20803 ring=0:164286 ticks=5857178216', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.760258: msm_gpu_freq_change: new_freq=800', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.762807: msm_gpu_submit_retired: id=164284 pid=20803 ring=0:164285 elapsed=6796979 ns mhz=329 start=5857173223 end=5857303725', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.763401: msm_gpu_submit_retired: id=164285 pid=20803 ring=0:164286 elapsed=550937 ns mhz=799 start=5857303747 end=5857314325', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.770442: msm_gpu_submit_flush: id=164286 pid=20803 ring=0:164287 ticks=5857466816', // @suppress longLineCheck
+ ' UnityGfxDeviceW-20803 (20764) [006] .... 2569.771292: msm_gpu_submit_flush: id=164287 pid=20803 ring=0:164288 ticks=5857483141', // @suppress longLineCheck
+ ' kworker/u16:5-416 ( 416) [001] .... 2569.773496: msm_gpu_submit_retired: id=164286 pid=20803 ring=0:164287 elapsed=2780833 ns mhz=799 start=5857466871 end=5857520263', // @suppress longLineCheck
+ ' kworker/u16:1-21183 (21183) [003] .... 2569.774162: msm_gpu_freq_change: new_freq=430', // @suppress longLineCheck
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ let gpuThread = undefined;
+ m.getAllThreads().forEach(function(t) {
+ switch (t.name) {
+ case 'GPU':
+ gpuThread = t;
+ break;
+ default:
+ assert.fail(t, undefined, 'Unexpected thread named ' + t.name);
+ }
+ });
+ assert.isDefined(gpuThread);
+
+ assert.strictEqual(gpuThread.sliceGroup.length, 17);
+
+ function ticks2ms(ticks) {
+ return ticks / 19200;
+ }
+
+ const queuedDuration = ticks2ms(
+ 5854916032 - /* start= from retire trace */
+ 5854915894); /* ticks= from flush trace */
+ const runningDuration = ticks2ms(
+ 5855131042 - /* end= from retire trace */
+ 5854916032); /* start= from retire trace */
+
+ assert.closeTo(
+ (2569.637650 * 1000.0) + queuedDuration,
+ gpuThread.sliceGroup.slices[0].start,
+ 1e-5);
+ assert.closeTo(
+ runningDuration,
+ gpuThread.sliceGroup.slices[0].duration,
+ 1e-5);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html
index 54f4dcbaa15..8aa9d5b35ae 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html
@@ -772,7 +772,7 @@ tr.exportTo('tr.e.importer', function() {
// in the main thread, in order to get the correct thread object,
// we should use pid and tid from main thread.
if (data.startTime !== undefined) {
- this.profileInfo_.set(event.id, {
+ this.profileInfo_.set(`${event.pid} ${event.id}`, {
startTime: data.startTime,
pid: event.pid,
tid: event.tid
@@ -791,7 +791,8 @@ tr.exportTo('tr.e.importer', function() {
throw new Error('samples and timeDeltas array should have same length');
}
- const profileTree = this.getOrCreateProfileTree_(sampleType, event.id);
+ const profileTree = this.getOrCreateProfileTree_(sampleType,
+ `${event.pid} ${event.id}`);
const nodes = data[sampleType].nodes;
const samples = data[sampleType].samples;
if (nodes !== undefined) {
@@ -2853,6 +2854,7 @@ tr.exportTo('tr.e.importer', function() {
// In Chromium under //services/resource_coordinator/public see
// mojom/memory_instrumentation/memory_instrumentation.mojom and
// cpp/memory_instrumentation/tracing_observer.cc
+ if (rawVmRegions === null) return;
const vmRegions = new Array(rawVmRegions.length);
for (let i = 0; i < rawVmRegions.length; i++) {
const rawVmRegion = rawVmRegions[i];
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html
index 7953ba7c488..133345b9134 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html
@@ -6627,6 +6627,97 @@ tr.b.unittest.testSuite(function() {
checkParsedAndStreamInput(events, checkModel, false);
});
+ test('importV8SamplesInStreamingFormat_id_collision', function() {
+ function checkModel(m) {
+ const samples = m.samples;
+ assert.strictEqual(m.samples.length, 4);
+ assert.strictEqual(Object.keys(m.processes).length, 2);
+ assert.deepEqual(samples.map(sample => sample.start.toFixed(3)), [
+ '0.011',
+ '0.012',
+ '0.013',
+ '0.016'
+ ]);
+ assert.deepEqual(samples.map(sample => sample.thread.getProcess().pid), [
+ 1,
+ 1,
+ 2,
+ 2
+ ]);
+ assert.deepEqual(samples[0].userFriendlyStack, [
+ 'b url: b.js:1:2 Deoptimized reason: a reason',
+ 'a url: a.js:1:2'
+ ]);
+ assert.deepEqual(samples[1].userFriendlyStack, [
+ 'a url: a.js:1:2'
+ ]);
+ assert.deepEqual(samples[2].userFriendlyStack, [
+ 'd url: d.js:2:3 Deoptimized reason: another reason',
+ ]);
+ assert.deepEqual(samples[3].userFriendlyStack, [
+ 'c url: c.js:2:3',
+ ]);
+ }
+
+ const events = {
+ 'traceEvents': [
+ {'pid': 1, 'tid': 2, 'ts': 3, 'ph': 'P',
+ 'cat': 'disabled-by-default-v8.cpu_profiler',
+ 'name': 'Profile',
+ 'args': {'data': {'startTime': 10}},
+ 'id': 123
+ },
+ {'pid': 2, 'tid': 2, 'ts': 3, 'ph': 'P',
+ 'cat': 'disabled-by-default-v8.cpu_profiler',
+ 'name': 'Profile',
+ 'args': {'data': {'startTime': 10}},
+ 'id': 123
+ },
+ {'pid': 1, 'tid': 3, 'ts': 4, 'ph': 'P',
+ 'cat': 'disabled-by-default-v8.cpu_profiler',
+ 'name': 'Profile',
+ 'args': {
+ 'data': {
+ 'timeDeltas': [1, 1],
+ 'cpuProfile': {
+ 'nodes': [
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': '(root)', 'scriptId': 0}, 'id': 1},
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': 'a', 'url': 'a.js', 'scriptId': 1, 'lineNumber': 1, 'columnNumber': 2}, 'id': 2, 'parent': 1},
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': 'b', 'url': 'b.js', 'scriptId': 2, 'lineNumber': 1, 'columnNumber': 2}, 'deoptReason': 'a reason', 'id': 3, 'parent': 2}
+ ],
+ 'samples': [3, 2]
+ }
+ }
+ },
+ 'id': 123
+ },
+ {'pid': 2, 'tid': 3, 'ts': 4, 'ph': 'P',
+ 'cat': 'disabled-by-default-v8.cpu_profiler',
+ 'name': 'Profile',
+ 'args': {
+ 'data': {
+ 'timeDeltas': [3, 3],
+ 'cpuProfile': {
+ 'nodes': [
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': 'c', 'url': 'c.js', 'scriptId': 3, 'lineNumber': 2, 'columnNumber': 3}, 'id': 4, 'parent': 2},
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': 'd', 'url': 'd.js', 'scriptId': 4, 'lineNumber': 2, 'columnNumber': 3}, 'deoptReason': 'another reason', 'id': 5, 'parent': 3}
+ ],
+ 'samples': [5, 4]
+ }
+ }
+ },
+ 'id': 123
+ }
+ ]
+ };
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
test('scopedIdForEvent_defaultScopeAsyncEvent', function() {
const event = {pid: 1, ph: 'b', id: '0x1000'};
const id = tr.e.importer.TraceEventImporter.scopedIdForEvent_(event);
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py
index b15882a4ce6..cb5c4170b14 100755
--- a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py
@@ -284,7 +284,6 @@ class NodeWrapper(object):
'modified' flag.
"""
- pass
class MemoryMap(NodeWrapper):
@@ -341,7 +340,7 @@ class MemoryMap(NodeWrapper):
def file_offset(self, value):
self._file_offset = value
- def __cmp__(self, other):
+ def compare(self, other): # pylint: disable=invalid-name
if isinstance(other, type(self)):
other_start_address = other._start_address
elif isinstance(other, six.integer_types):
@@ -350,10 +349,31 @@ class MemoryMap(NodeWrapper):
raise Exception('Cannot compare with %s' % type(other))
if self._start_address < other_start_address:
return -1
- elif self._start_address > other_start_address:
+ if self._start_address > other_start_address:
return 1
- else:
- return 0
+ return 0
+
+ if six.PY2:
+ def __cmp__(self, other):
+ return self.compare(other)
+ else:
+ def __eq__(self, other):
+ return self.compare(other) == 0
+
+ def __ne__(self, other):
+ return self.compare(other) != 0
+
+ def __lt__(self, other):
+ return self.compare(other) < 0
+
+ def __le__(self, other):
+ return self.compare(other) <= 0
+
+ def __gt__(self, other):
+ return self.compare(other) > 0
+
+ def __ge__(self, other):
+ return self.compare(other) >= 0
def __repr__(self):
return 'Region(0x{:X} - 0x{:X}, {})'.format(
@@ -369,7 +389,8 @@ class MemoryMap(NodeWrapper):
file_offset)
# Keep track of code-identifier when present.
if 'ts' in region_node and 'sz' in region_node:
- region._code_id = '%08X%X' % (int(region_node['ts'], 16), region.size)
+ region._code_id = '%08X%X' % (int(str(region_node['ts']), 16),
+ region.size)
regions.append(region)
regions.sort()
@@ -433,7 +454,7 @@ class MemoryMap(NodeWrapper):
region_index = bisect.bisect_right(self._regions, address) - 1
if region_index >= 0:
region = self._regions[region_index]
- if address >= region.start_address and address < region.end_address:
+ if region.start_address <= address < region.end_address:
return region
return None
@@ -948,6 +969,7 @@ class Trace(NodeWrapper):
self._version = None
self._is_chromium = True
self._is_64bit = False
+ self._os_arch = None
self._is_win = False
self._is_mac = False
self._is_linux = False
@@ -983,6 +1005,7 @@ class Trace(NodeWrapper):
self._is_64bit = (
re.search('x86_64', metadata['os-arch'], re.IGNORECASE) and
not re.search('WOW64', metadata['user-agent'], re.IGNORECASE))
+ self._os_arch = metadata['os-arch']
# Android traces produced via 'chrome://inspect/?tracing#devices' are
# just list of events.
@@ -1093,6 +1116,10 @@ class Trace(NodeWrapper):
return self._os
@property
+ def os_arch(self):
+ return self._os_arch
+
+ @property
def is_chromium(self):
return self._is_chromium
@@ -1151,12 +1178,11 @@ class Trace(NodeWrapper):
if self._heap_dump_version is None:
self._heap_dump_version = version
return version
- elif self._heap_dump_version != version:
+ if self._heap_dump_version != version:
raise Exception(
("Inconsistent trace file: first saw '{}' heap dump version, "
"then '{}'.").format(self._heap_dump_version, version))
- else:
- return version
+ return version
class SymbolizableFile(object):
@@ -1218,12 +1244,13 @@ def ResolveSymbolizableFiles(processes, trace_from_win, frame_as_object_type):
continue
ResolveSymbolizableFilesByNodes(
symfile_by_path, process.memory_map,
- process.stack_frame_map.frame_by_id.values(), trace_from_win)
+ list(process.stack_frame_map.frame_by_id.values()), trace_from_win)
if frame_as_object_type:
- ResolveSymbolizableFilesByNodes(symfile_by_path, process.memory_map,
- process.type_name_map.type_by_id.values(),
- trace_from_win)
+ ResolveSymbolizableFilesByNodes(
+ symfile_by_path, process.memory_map,
+ list(process.type_name_map.type_by_id.values()),
+ trace_from_win)
return list(symfile_by_path.values())
@@ -1277,7 +1304,8 @@ class BreakpadSymbolsModule(object):
class Symbolizer(object):
"""Encapsulates platform-specific symbolization logic."""
- def __init__(self, addr2line_executable):
+ def __init__(self, addr2line_executable, os_arch):
+ self._os_arch = os_arch
self.is_mac = sys.platform == 'darwin'
self.is_win = sys.platform == 'win32'
if self.is_mac:
@@ -1331,10 +1359,11 @@ class Symbolizer(object):
for address in symfile.frames_by_address.keys():
address_file.write('{:x} '.format(address + load_address))
- cmd = [self.symbolizer_path, '-arch', 'x86_64', '-l',
+ architecture = 'arm64e' if self._os_arch == 'arm64' else 'x86_64'
+ cmd = [self.symbolizer_path, '-arch', architecture, '-l',
'0x%x' % load_address, '-o', symfile.symbolizable_path,
'-f', address_file_path]
- output_array = subprocess.check_output(cmd).split('\n')
+ output_array = six.ensure_str(subprocess.check_output(cmd)).split('\n')
for i, frames in enumerate(symfile.frames_by_address.values()):
symbolized_name = self._matcher.Match(output_array[i])
@@ -1364,8 +1393,9 @@ class Symbolizer(object):
stderr=None)
addrs = ["%x" % relative_pc for relative_pc in
symfile.frames_by_address.keys()]
- (stdout_data, _) = proc.communicate('\n'.join(addrs))
+ (stdout_data, _) = proc.communicate(six.ensure_binary('\n'.join(addrs)))
# On windows, lines may contain '\r' character: e.g. "RtlUserThreadStart\r".
+ stdout_data = six.ensure_str(stdout_data)
stdout_data.replace('\r', '')
stdout_data = stdout_data.split('\n')
@@ -1438,11 +1468,11 @@ class Symbolizer(object):
if self.is_win:
extension = os.path.splitext(file_path)[1].lower()
return extension in ['.dll', '.exe']
- else:
- result = subprocess.check_output(['file', '-0', file_path])
- type_string = result[result.find('\0') + 1:]
- return bool(re.match(r'.*(ELF|Mach-O) (32|64)-bit\b.*',
- type_string, re.DOTALL))
+ result = six.ensure_str(
+ subprocess.check_output(['file', '-0', file_path]))
+ type_string = result[result.find('\0') + 1:]
+ return bool(re.match(r'.*(ELF|Mach-O) (32|64)-bit\b.*',
+ type_string, re.DOTALL))
def SymbolizeFiles(symfiles, symbolizer):
@@ -1654,9 +1684,11 @@ def FetchAndExtractBreakpadSymbols(symbol_base_directory,
def OpenTraceFile(file_path, mode):
if file_path.endswith('.gz'):
- return gzip.open(file_path, mode + 'b')
- else:
- return open(file_path, mode + 't')
+ if six.PY2:
+ return gzip.open(file_path, mode + 'b')
+ return gzip.open( # pylint: disable=unexpected-keyword-arg
+ file_path, mode + 't', encoding='utf-8', newline='')
+ return open(file_path, mode + 't')
def FetchAndExtractSymbolsMac(symbol_base_directory, version,
@@ -1710,6 +1742,7 @@ def FetchAndExtractSymbolsWin(symbol_base_directory, version, is64bit,
target = open(os.path.join(destination, filename), 'wb')
with source, target:
shutil.copyfileobj(source, target)
+ return True
folder = "win64" if is64bit else "win"
# Clang build (M61+)
@@ -1726,16 +1759,19 @@ def FetchAndExtractSymbolsWin(symbol_base_directory, version, is64bit,
return True
os.makedirs(symbol_sub_dir)
- DownloadAndExtractZipFile(
+ if not DownloadAndExtractZipFile(
os.path.join(symbol_base_directory,
"chrome-" + folder + "-" + version + "-syms.zip"),
gcs_folder + "chrome-win32-syms.zip",
- symbol_sub_dir)
- DownloadAndExtractZipFile(
+ symbol_sub_dir):
+ return False
+
+ if not DownloadAndExtractZipFile(
os.path.join(symbol_base_directory,
"chrome-" + folder + "-" + version + ".zip"),
gcs_folder + "chrome-" + folder + folder_suffix + ".zip",
- symbol_sub_dir)
+ symbol_sub_dir):
+ return False
return True
@@ -1807,11 +1843,6 @@ def main(args):
if options.frame_as_object_type and not options.is_cast:
sys.exit("Frame-as-object-type is only supported for cast.")
- symbolizer = Symbolizer(options.addr2line_executable)
- if (symbolizer.symbolizer_path is None and
- not options.use_breakpad_symbols):
- sys.exit("Can't symbolize - no %s in PATH." % symbolizer.binary)
-
trace_file_path = options.file
print('Reading trace file...')
@@ -1819,6 +1850,11 @@ def main(args):
trace = Trace(json.load(trace_file), options.frame_as_object_type)
print('Trace loaded for %s/%s' % (trace.os, trace.version))
+ symbolizer = Symbolizer(options.addr2line_executable, trace.os_arch)
+ if (symbolizer.symbolizer_path is None and
+ not options.use_breakpad_symbols):
+ sys.exit("Can't symbolize - no %s in PATH." % symbolizer.binary)
+
trace.is_chromium = options.is_local_build
trace.is_cast = options.is_cast
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py
index ff05cc6ba86..344a2437aeb 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py
@@ -7,6 +7,7 @@ from __future__ import division
from __future__ import print_function
import re
import subprocess
+import six
from six.moves import range # pylint: disable=redefined-builtin
@@ -16,7 +17,7 @@ def ReadMachOTextLoadAddress(file_name):
"""
regex = re.compile(r".* vmaddr 0x([\dabcdef]*)")
cmd = ["otool", "-l", file_name]
- output = subprocess.check_output(cmd).split('\n')
+ output = six.ensure_str(subprocess.check_output(cmd)).split('\n')
for i in range(len(output) - 3):
# It's possible to use a regex here instead, but these conditionals are much
# clearer.
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py
index f0058abda51..6e812583c79 100644
--- a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py
@@ -3,6 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import os
import sys
import unittest
@@ -14,12 +15,16 @@ class AtosRegexTest(unittest.TestCase):
if sys.platform != "darwin":
return
file_name = "/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit"
- result = symbolize_trace_macho_reader.ReadMachOTextLoadAddress(file_name)
- self.assertNotEqual(None, result)
+ # TODO(crbug.com/1275181)
+ if os.path.exists(file_name):
+ result = symbolize_trace_macho_reader.ReadMachOTextLoadAddress(file_name)
+ self.assertNotEqual(None, result)
file_name = "/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa"
- result = symbolize_trace_macho_reader.ReadMachOTextLoadAddress(file_name)
- self.assertNotEqual(None, result)
+ # TODO(crbug.com/1275181)
+ if os.path.exists(file_name):
+ result = symbolize_trace_macho_reader.ReadMachOTextLoadAddress(file_name)
+ self.assertNotEqual(None, result)
if __name__ == '__main__':
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html b/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html
index b4db84afe45..5d83362b0f4 100644
--- a/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html
+++ b/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html
@@ -317,24 +317,29 @@ tr.exportTo('tr.importer', function() {
for (let index = 0; index < navStartEvents.length; index++) {
const currNavigation = navStartEvents[index];
let url;
- let isLoadingMainFrame = false;
+ let isOutermostMainFrame = false;
if (currNavigation.args.data) {
url = currNavigation.args.data.documentLoaderURL;
- isLoadingMainFrame = currNavigation.args.data.isLoadingMainFrame;
+ // If isOutermostMainFrame is available, use it, if not use
+ // isLoadingMainFrame.
+ isOutermostMainFrame =
+ (currNavigation.args.data.isOutermostMainFrame !== undefined) ?
+ currNavigation.args.data.isOutermostMainFrame :
+ currNavigation.args.data.isLoadingMainFrame;
} else {
// TODO(#4358): Delete old path of obtaining URL.
const snapshot = findFrameLoaderSnapshotAt(
rendererHelper, frameIdRef, currNavigation.start);
if (snapshot) {
url = snapshot.args.documentLoaderURL;
- isLoadingMainFrame = snapshot.args.isLoadingMainFrame;
+ isOutermostMainFrame = snapshot.args.isLoadingMainFrame;
}
}
// Filter navigationStartEvents that do not correspond to a loading main
// frame, or has a URL that we do not care about.
- if (!isLoadingMainFrame) continue;
+ if (!isOutermostMainFrame) continue;
if (url === undefined || IGNORE_URLS.includes(url)) continue;
if (prevNavigation.navigationEvent !== undefined) {
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/import.html b/chromium/third_party/catapult/tracing/tracing/importer/import.html
index 8893120c2c5..00892071d69 100644
--- a/chromium/third_party/catapult/tracing/tracing/importer/import.html
+++ b/chromium/third_party/catapult/tracing/tracing/importer/import.html
@@ -235,11 +235,23 @@ tr.exportTo('tr.importer', function() {
// Create auditors
let auditors = [];
addImportStage('Adding arbitrary data to model...', () => {
- auditors = this.importOptions_.auditorConstructors.map(
- auditorConstructor => new auditorConstructor(this.model_));
+ for (const auditorConstructor of
+ this.importOptions_.auditorConstructors) {
+ try {
+ auditors.push(new auditorConstructor(this.model_));
+ } catch (e) {
+ console.error('Failed to construct an auditor:');
+ console.error(e);
+ }
+ }
auditors.forEach((auditor) => {
- auditor.runAnnotate();
- auditor.installUserFriendlyCategoryDriverIfNeeded();
+ try {
+ auditor.runAnnotate();
+ auditor.installUserFriendlyCategoryDriverIfNeeded();
+ } catch (e) {
+ console.error('Failed to run an auditor:');
+ console.error(e);
+ }
});
});
@@ -275,8 +287,13 @@ tr.exportTo('tr.importer', function() {
// Build the UserModel.
addImportStage('Building UserModel...', () => {
- const userModelBuilder = new tr.importer.UserModelBuilder(this.model_);
- userModelBuilder.buildUserModel();
+ try {
+ const userModelBuilder = new tr.importer.UserModelBuilder(this.model_);
+ userModelBuilder.buildUserModel();
+ } catch (e) {
+ console.error('Failed to build user model');
+ console.error(e);
+ }
});
// Sort Expectations.
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/import_test.html b/chromium/third_party/catapult/tracing/tracing/importer/import_test.html
index 77787402719..55d5eb797fe 100644
--- a/chromium/third_party/catapult/tracing/tracing/importer/import_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/importer/import_test.html
@@ -213,7 +213,8 @@ tr.b.unittest.testSuite(function() {
p.memoryDumps[2].mostRecentVmRegions);
});
- test('setsModelStatsTraceImportDurationMs', function() {
+// TODO(crbug.com/1315423): Fix and re-enable test to pass on all trybots.
+ skipTest('setsModelStatsTraceImportDurationMs', function() {
const traceEvents = [
{ts: 1000, pid: 1, tid: 3, ph: 'B', cat: 'c', name: 'taskB', args: {
my_object: {id_ref: '0x1000'}
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html b/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html
index 3deaac7d934..4efb9c079af 100644
--- a/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html
+++ b/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html
@@ -83,8 +83,8 @@ tr.exportTo('tr.importer', function() {
if (this.type !== ProtoExpectation.IGNORED_TYPE && !this.isValid) {
model.importWarning({
type: 'ProtoExpectation',
- message: 'Please file a bug with this trace. ' + this.debug(),
- showToUser: true
+ message: this.debug(),
+ showToUser: false
});
return undefined;
}
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html b/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html
index e4eeaa972fd..f26b7a19241 100644
--- a/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html
@@ -278,8 +278,9 @@ tr.b.unittest.testSuite(function() {
const verifier = new UserExpectationVerifier();
verifier.customizeModelCallback = function(model) {
model.rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader',
- 25, {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
- documentLoaderURL: 'http://example.com'});
+ 25, { isOutermostMainFrame: true, isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
cat: 'blink.user_timing',
@@ -321,8 +322,9 @@ tr.b.unittest.testSuite(function() {
verifier.customizeModelCallback = function(model) {
ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
model.rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader',
- 15, {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
- documentLoaderURL: 'http://example.com'});
+ 15, { isOutermostMainFrame: true, isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
ChromeTestUtils.addFrameEvent(model, {start: 20, end: 40});
model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
cat: 'blink.user_timing',
@@ -1111,8 +1113,9 @@ tr.b.unittest.testSuite(function() {
const verifier = new UserExpectationVerifier();
verifier.customizeModelCallback = function(model) {
model.rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader',
- 25, {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
- documentLoaderURL: 'http://example.com'});
+ 25, { isOutermostMainFrame: true, isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
cat: 'blink.user_timing',
title: 'navigationStart',
@@ -1207,8 +1210,9 @@ tr.b.unittest.testSuite(function() {
verifier.customizeModelCallback = function(model) {
ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
model.rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader',
- 25, {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
- documentLoaderURL: 'http://example.com'});
+ 25, { isOutermostMainFrame: true, isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
ChromeTestUtils.addFrameEvent(model, {start: 10, end: 20});
model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
cat: 'blink.user_timing',
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/__init__.py b/chromium/third_party/catapult/tracing/tracing/metrics/__init__.py
index cffcee63c42..c115b7fe69d 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/__init__.py
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/__init__.py
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from __future__ import absolute_import
import os
import sys
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html b/chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html
index 694f443fab7..6ed6dd188fd 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html
@@ -9,10 +9,14 @@ found in the LICENSE file.
<link rel="import" href="/tracing/metrics/android_systrace_metric.html">
<link rel="import" href="/tracing/metrics/blink/gc_metric.html">
<link rel="import" href="/tracing/metrics/blink/leak_detection_metric.html">
+<link rel="import" href="/tracing/metrics/blink/resource_metric.html">
<link rel="import" href="/tracing/metrics/console_error_metric.html">
+<link rel="import" href="/tracing/metrics/core_web_vitals_metric.html">
+<link rel="import" href="/tracing/metrics/count_sum_metric.html">
<link rel="import" href="/tracing/metrics/cpu_process_metric.html">
+<link rel="import" href="/tracing/metrics/custom_metric.html">
<link rel="import" href="/tracing/metrics/media_metric.html">
-<link rel="import" href="/tracing/metrics/memory_ablation_metric.html">
+<link rel="import" href="/tracing/metrics/partition_alloc/pcscan_metric.html">
<link rel="import" href="/tracing/metrics/rendering/rendering_metric.html">
<link rel="import" href="/tracing/metrics/reported_by_page_metric.html">
<link rel="import" href="/tracing/metrics/sample_exception_metric.html">
@@ -32,6 +36,7 @@ found in the LICENSE file.
<link rel="import" href="/tracing/metrics/system_health/rects_based_speed_index_metric.html">
<link rel="import" href="/tracing/metrics/system_health/responsiveness_metric.html">
<link rel="import" href="/tracing/metrics/system_health/screenshots_based_speed_index_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/weblayer_startup_metric.html">
<link rel="import" href="/tracing/metrics/system_health/webview_startup_metric.html">
<link rel="import" href="/tracing/metrics/tabs_metric.html">
<link rel="import" href="/tracing/metrics/tracing_metric.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html
index 702cdbf5fea..390b02df412 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html
@@ -5,55 +5,113 @@ Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
<link rel="import" href="/tracing/metrics/metric_registry.html">
<link rel="import" href="/tracing/value/histogram.html">
<script>
'use strict';
-// The |androidStartupMetric| produces metrics that start counting at the
-// earliest moment the Chrome code on Android is executed.
-// A few histograms are produced with the names as described below:
+// The |androidStartupMetric| produces metrics that (unless noted otherwise)
+// start counting at the earliest moment the Chrome code on Android is
+// executed. A few histograms are produced with the names as described below:
//
-// 1. messageloop_start_time - time till the message loop of the browser main
-// starts processing posted tasts (after having loaded the Profile)
-// 2. experimental_content_start_time - time when the renderer enters the main
-// entrypoint.
-// 3. experimental_navigation_start_time - This roughly corresponds to the time
-// the initial navigation network request is sent.
-// 4. navigation_commit_time - This is when the renderer has received the first
-// part of the response from the network and started loading the page.
-// 5. first_contentful_paint_time - time to the first contentful paint of the
-// page loaded at startup
+// * messageloop_start_time - Time till the message loop of the browser main
+// starts processing posted tasks (after having loaded the Profile)
+//
+// * experimental_navigation_start_time - This roughly corresponds to the time
+// the initial navigation network request is sent on the UI thread
+//
+// * experimental_network_request_start_time - Time until the first network
+// request starts in the netlog. The actual bytes will be sent to the network
+// slightly later: after disk cache responds. This metric can be used even for
+// netowrk loads that are served from the disk cache. Currently relies on
+// NetworkService running in the browser process.
+//
+// * navigation_commit_time - This is when the renderer has received the first
+// part of the response from the network after all redirects and started
+// loading the page. Recorded when the confirmation is received on the browser
+// UI thread.
+//
+// * first_contentful_paint_time - Time to the first 'contentful' paint of the
+// page loaded at startup
+//
+// * process_create_to_app_start_time - Time from process creation until the
+// application starts. The end time of this event will be the same as the
+// start time of messageloop_start_time.
//
// The metric also supports multiple browser restarts, in this case multiple
// samples would be added to the histograms above.
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';
+ const REQUEST_ALIVE = 'REQUEST_ALIVE';
+
+ function isGetRequest(event) {
+ if (event.args &&
+ event.args.params &&
+ event.args.params.method == 'GET') {
+ return true;
+ }
+ return false;
+ }
+
+ function findRequestEventAfterNavigation(networkEvents, range) {
+ let requestStart = range.max;
+ let requestEvent = null;
+ for (const event of networkEvents) {
+ if (isGetRequest(event)) {
+ for (const subSlice of event.subSlices) {
+ if (subSlice.title === REQUEST_ALIVE &&
+ range.min <= subSlice.start && subSlice.start < requestStart) {
+ requestStart = subSlice.start;
+ requestEvent = subSlice;
+ }
+ }
+ }
+ }
+ return requestEvent;
+ }
+
function androidStartupMetric(histograms, model) {
// Walk the browser slices, extract timestamps for the browser start,
// message loop start.
let messageLoopStartEvents = [];
- let navigationEvents = [];
+ let applicationStartEvents = [];
+ let navigationPairs = [];
+
+ function organizeBrowserEventByTitle(event, process) {
+ if (event.title === MESSAGE_LOOP_EVENT_NAME) {
+ messageLoopStartEvents.push(event);
+ } else if (event.title === APPLICATION_START_EVENT_NAME) {
+ applicationStartEvents.push(event);
+ } else if (event.title === NAVIGATION_EVENT_NAME) {
+ const networkEvents =
+ tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(process,
+ event.range);
+ const requestEvent = findRequestEventAfterNavigation(
+ networkEvents, event.range);
+ navigationPairs.push({
+ 'nav': event,
+ 'req': requestEvent,
+ });
+ }
+ }
+
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);
- }
+ organizeBrowserEventByTitle(ev, helper.process);
}
}
// Walk the renderer slices and extract the 'first contentful paint'
// histogram samples.
- let contentStartEvents = [];
let firstContentfulPaintEvents = [];
const rendererHelpers = chromeHelper.rendererHelpers;
const pids = Object.keys(rendererHelpers);
@@ -65,38 +123,28 @@ tr.exportTo('tr.metrics.sh', function() {
// There are usually several 'First Contentful Paint' events recorded
// for each page load. Take only the first one per renderer.
break;
- } else if (ev.title === CONTENT_START_EVENT_NAME) {
- contentStartEvents.push(ev);
}
}
}
// Fallback to scanning all processes if important events are not found.
let totalBrowserStarts = messageLoopStartEvents.length;
- let totalContentStartEvents = contentStartEvents.length;
let totalFcpEvents = firstContentfulPaintEvents.length;
- let totalNavigations = navigationEvents.length;
- if (totalFcpEvents !== totalBrowserStarts ||
- totalNavigations !== totalBrowserStarts ||
- totalContentStartEvents !== totalBrowserStarts ||
+ if (totalBrowserStarts !== totalFcpEvents ||
+ totalBrowserStarts !== navigationPairs.length ||
+ totalBrowserStarts !== applicationStartEvents.length ||
totalBrowserStarts === 0) {
- messageLoopStartEvents = [];
- contentStartEvents = [];
- navigationEvents = [];
- firstContentfulPaintEvents = [];
+ messageLoopStartEvents.length = 0;
+ navigationPairs.length = 0;
+ firstContentfulPaintEvents.length = 0;
+ applicationStartEvents.length = 0;
// Sometimes either the browser process or the renderer process does not
// have the proper name attached. This often happens when both chrome
// trace and systrace are merged. Other multi-process trickery, like
// Perfetto, may also cause this.
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);
- }
+ organizeBrowserEventByTitle(ev, proc);
}
for (const ev of proc.getDescendantEvents()) {
if (ev.title === FIRST_CONTENTFUL_PAINT_EVENT_NAME) {
@@ -106,25 +154,65 @@ tr.exportTo('tr.metrics.sh', function() {
}
}
totalBrowserStarts = messageLoopStartEvents.length;
- totalContentStartEvents = contentStartEvents.length;
- totalNavigations = navigationEvents.length;
totalFcpEvents = firstContentfulPaintEvents.length;
}
- // Sometimes a number of early trace events are not recorded because tracing
- // takes time to start. This leads to having more FCP events than
- // messageloop_start events. As a workaround ignore the FCP events for which
- // there are no browser starts. Navigation and content start events are
- // recorded on a best effort basis if they are found in the trace; their
- // absence doesn't cause FCP events to be dropped.
+ // Sort the events by start time.
function orderEvents(event1, event2) {
return event1.start - event2.start;
}
messageLoopStartEvents.sort(orderEvents);
- contentStartEvents.sort(orderEvents);
- navigationEvents.sort(orderEvents);
+ applicationStartEvents.sort(orderEvents);
firstContentfulPaintEvents.sort(orderEvents);
+ function orderPairs(pair1, pair2) {
+ return pair1['nav'].start - pair2['nav'].start;
+ }
+ navigationPairs.sort(orderPairs);
+
+ // Remove spurious navigation events. Only one 'Navigation StartToCommit'
+ // event should remain for each browser session. When multiple events are
+ // encountered for a browsing session, remove all except the first one. The
+ // first navigation event looked more realistic for the story
+ // maps_pwa:with_http_cache (http://crbug.com/1307774).
+ let filteredNavigationPairs = [];
+ let filteredRequestsFollowingNavigation = [];
+ let navigation_index = 0;
+ let messageloop_index = 0;
+ do {
+ // Set |browserStart| as the upper limit for the set of navigations to
+ // select from.
+ let browserStart = Number.POSITIVE_INFINITY;
+ if (messageloop_index < messageLoopStartEvents.length) {
+ browserStart = messageLoopStartEvents[messageloop_index].start;
+ }
+ // From navigation events preceding |browserStart| take the first one,
+ // skip others.
+ let navigationFound = false;
+ for (; navigation_index < navigationPairs.length; navigation_index++) {
+ // Each request event has to be at the same index as its corresponding
+ // navigation event. Take either both of them or none.
+ const navPair = navigationPairs[navigation_index];
+ const navEvent = navPair['nav'];
+ const requestEvent = navPair['req'];
+ if (navEvent.start >= browserStart) {
+ break;
+ }
+ if (!navigationFound) {
+ if (messageloop_index === 0) {
+ throw new Error('Found a navigation event before browser start');
+ }
+ filteredNavigationPairs.push(navPair);
+ navigationFound = true;
+ }
+ }
+ // Run the last iteration with |browserStart| as positive infinity.
+ } while (messageloop_index++ <= messageLoopStartEvents.length);
+ navigationPairs = filteredNavigationPairs;
+
+ // Verify the number of FCP events to avoid pairing them to browser starts
+ // incorrectly. Absence of navigation events does not cause FCP events to be
+ // dropped.
if (totalFcpEvents < totalBrowserStarts) {
throw new Error('Found fewer FCP events (' + totalFcpEvents +
') than browser starts (' + totalBrowserStarts + ')');
@@ -135,47 +223,44 @@ tr.exportTo('tr.metrics.sh', function() {
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 requestStartHistogram = histograms.createHistogram(
+ 'experimental_network_request_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, []);
- // The earliest browser start is skipped because it is affected by the state
- // of the system coming from the time before the benchmark started. Removing
- // these influencing factors allows reducing measurement noise.
- // Note: Two early starts are ignored below, the reasons for spurious
- // slowdowns of the 2nd run are not known yet, see http://crbug.com/891797.
- let contentIndex = 0;
+ const applicationStartHistogram = histograms.createHistogram(
+ 'process_create_to_app_start_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, []);
+ // The earliest 2 browser starts are skipped to reduce measurement noise.
+ // See http://crbug.com/891797.
let navIndex = 0;
let fcpIndex = 0;
for (let loopStartIndex = 0; loopStartIndex < totalBrowserStarts;) {
- const startEvent = messageLoopStartEvents[loopStartIndex];
+ const loopStartEvent = messageLoopStartEvents[loopStartIndex];
+ // There should be a corresponding application start event for each
+ // message loop start event.
+ const applicationStartEvent = applicationStartEvents[loopStartIndex];
if (fcpIndex === totalFcpEvents) {
break;
}
// Skip all events that appear before the next browser start.
- 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) {
+ const navPair = navIndex < navigationPairs.length ?
+ navigationPairs[navIndex] : null;
+ const navEvent = navPair ? navPair['nav'] : null;
+ if (navEvent && navEvent.start < loopStartEvent.start) {
navIndex++;
continue;
}
const fcpEvent = firstContentfulPaintEvents[fcpIndex];
- if (fcpEvent.start < startEvent.start) {
+ if (fcpEvent.start < loopStartEvent.start) {
fcpIndex++;
continue;
}
@@ -190,25 +275,30 @@ tr.exportTo('tr.metrics.sh', function() {
}
// Record the histograms.
- 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])});
- }
+ messageLoopStartHistogram.addSample(loopStartEvent.duration,
+ {events: new tr.v.d.RelatedEventSet([loopStartEvent])});
if (navEvent) {
navigationStartHistogram.addSample(
- navEvent.start - startEvent.start,
- {events: new tr.v.d.RelatedEventSet([startEvent, navEvent])});
+ navEvent.start - loopStartEvent.start,
+ {events: new tr.v.d.RelatedEventSet([loopStartEvent, navEvent])});
navigationCommitHistogram.addSample(
- navEvent.end - startEvent.start,
- {events: new tr.v.d.RelatedEventSet([startEvent, navEvent])});
+ navEvent.end - loopStartEvent.start,
+ {events: new tr.v.d.RelatedEventSet([loopStartEvent, navEvent])});
+ const requestEvent = navPair['req'];
+ if (!requestEvent) {
+ throw new Error('No network request after navigation');
+ }
+ requestStartHistogram.addSample(
+ requestEvent.start - loopStartEvent.start,
+ {events: new tr.v.d.RelatedEventSet([navEvent, requestEvent])});
}
firstContentfulPaintHistogram.addSample(
- fcpEvent.end - startEvent.start,
- {events: new tr.v.d.RelatedEventSet([startEvent, fcpEvent])});
+ 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])});
+ }
}
}
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html
index af1dca98488..076cbfef83f 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html
@@ -32,6 +32,34 @@ tr.b.unittest.testSuite(function() {
return rendererMainThread;
}
+ function addNetworkEvents(startTime, durationTime, process) {
+ const slice = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'netlog',
+ title: 'http://bbc.co.uk',
+ start: startTime,
+ args: { params: { method: 'GET' } },
+ duration: durationTime});
+ slice.args.params['method'] = 'GET';
+ const subSlice = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'netlog',
+ title: 'REQUEST_ALIVE',
+ start: startTime,
+ duration: durationTime});
+ slice.subSlices.push(subSlice);
+ const netThread = process.getOrCreateThread(tr.b.GUID.allocateSimple());
+ netThread.name = 'NetLog';
+ netThread.asyncSliceGroup.push(slice);
+ }
+
+ function addNavigationEvent(threadForAdding, startTime, durationTime) {
+ threadForAdding.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'navigation',
+ title: 'Navigation StartToCommit',
+ start: startTime,
+ duration: durationTime}));
+ }
+
// Adds a browser and renderer to the process, with a few key events necessary
// to calculate the |androidStartupMetric|. An |offset| can be added to all
// events and the length of a few events can be extended by
@@ -43,22 +71,20 @@ tr.b.unittest.testSuite(function() {
browserMainThread.asyncSliceGroup.push(
tr.c.TestUtils.newAsyncSliceEx({
cat: 'startup',
+ title: 'Startup.LoadTime.ProcessCreateToApplicationStart',
+ start: (offset + 5000),
+ duration: (incrementForMetrics + 100)}));
+ browserMainThread.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'startup',
title: 'Startup.BrowserMessageLoopStartTime',
start: (offset + 6800.125),
duration: (incrementForMetrics + 1700.0625)}));
- browserMainThread.asyncSliceGroup.push(
- tr.c.TestUtils.newAsyncSliceEx({
- cat: 'navigation',
- title: 'Navigation StartToCommit',
- start: (offset + 9000.5 + incrementForMetrics),
- duration: (incrementForMetrics + 2000.5)}));
+ const navigationStart = offset + 9000.5 + incrementForMetrics;
+ addNavigationEvent(browserMainThread, navigationStart,
+ incrementForMetrics + 2000.5);
const rendererMainThread = createRendererThread(model);
rendererMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
- cat: 'startup',
- title: 'content::Start',
- start: (offset + 9500.125 + incrementForMetrics),
- duration: 10000.0}));
- rendererMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
cat: 'loading,rail,devtools.timeline',
title: 'firstContentfulPaint',
start: (offset + 8400.125 + incrementForMetrics),
@@ -73,6 +99,11 @@ tr.b.unittest.testSuite(function() {
start: (offset + 8400.125 + incrementForMetrics + 0.125),
duration: 0.0,
args: {frame: '0x0'}}));
+
+ // The metrics rely on having network access in netlog soon after the
+ // navigation starts.
+ addNetworkEvents(navigationStart + 110, 2, browserMainThread.parent);
+ return browserMainThread;
}
// Adds early messageloop and FCP events. The metric should ignore these very
@@ -83,6 +114,12 @@ tr.b.unittest.testSuite(function() {
browserMainThread.asyncSliceGroup.push(
tr.c.TestUtils.newAsyncSliceEx({
cat: 'startup',
+ title: 'Startup.LoadTime.ProcessCreateToApplicationStart',
+ start: offset,
+ duration: 1.0}));
+ browserMainThread.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'startup',
title: 'Startup.BrowserMessageLoopStartTime',
start: (offset + 1.0),
duration: 10.0}));
@@ -123,9 +160,11 @@ tr.b.unittest.testSuite(function() {
verifyHistogram(histograms, 'messageloop_start_time', 1, 1700.0625);
verifyHistogram(histograms, 'experimental_navigation_start_time', 1,
2200.375);
+ verifyHistogram(histograms, 'experimental_network_request_start_time', 1,
+ 2200.375 + 110);
verifyHistogram(histograms, 'navigation_commit_time', 1, 4200.875);
- verifyHistogram(histograms, 'experimental_content_start_time', 1, 2700);
verifyHistogram(histograms, 'first_contentful_paint_time', 1, 1600);
+ verifyHistogram(histograms, 'process_create_to_app_start_time', 1, 100);
});
// Emulates loss of the initial message loop start event. Checks that this
@@ -150,18 +189,10 @@ tr.b.unittest.testSuite(function() {
title: 'Startup.BrowserMessageLoopStartTime',
start: (20.0 + 1.0),
duration: 10.0}));
- browserMainThread.asyncSliceGroup.push(
- tr.c.TestUtils.newAsyncSliceEx({
- cat: 'navigation',
- title: 'Navigation StartToCommit',
- start: (20.0 + 11.0),
- duration: 10.0}));
+ const navigationStartTime = 20.0 + 11.0;
+ addNavigationEvent(browserMainThread, navigationStartTime, 10.0);
+ addNetworkEvents(navigationStartTime + 2, 2, browserMainThread.parent);
const rendererMainThread = createRendererThread(model);
- rendererMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
- cat: 'startup',
- title: 'content::Start',
- start: (20.0 + 1.75),
- duration: 10.0}));
rendererMainThread.sliceGroup.pushSlice(
tr.c.TestUtils.newSliceEx({
cat: 'loading,rail,devtools.timeline',
@@ -178,8 +209,9 @@ tr.b.unittest.testSuite(function() {
verifyHistogram(histograms, 'messageloop_start_time', 1, 1700.0625);
verifyHistogram(histograms, 'experimental_navigation_start_time', 1,
2200.375);
+ verifyHistogram(histograms, 'experimental_network_request_start_time', 1,
+ 2200.375 + 110);
verifyHistogram(histograms, 'navigation_commit_time', 1, 4200.875);
- verifyHistogram(histograms, 'experimental_content_start_time', 1, 2700);
verifyHistogram(histograms, 'first_contentful_paint_time', 1, 1600);
});
@@ -212,10 +244,12 @@ tr.b.unittest.testSuite(function() {
verifyHistogram(histograms, 'messageloop_start_time', 1, 10);
verifyHistogram(histograms, 'experimental_navigation_start_time', 0,
undefined);
- verifyHistogram(histograms, 'navigation_commit_time', 0, undefined);
- verifyHistogram(histograms, 'experimental_content_start_time', 0,
+ verifyHistogram(histograms, 'experimental_network_request_start_time', 0,
undefined);
+ verifyHistogram(histograms, 'navigation_commit_time', 0, undefined);
verifyHistogram(histograms, 'first_contentful_paint_time', 1, 2);
+ verifyHistogram(histograms, 'process_create_to_app_start_time', 0,
+ undefined);
});
// Checks the metrics after adding an offset to events in the model, and
@@ -226,9 +260,11 @@ tr.b.unittest.testSuite(function() {
verifyHistogram(histograms, 'messageloop_start_time', 1, 1707.0625);
verifyHistogram(histograms, 'experimental_navigation_start_time', 1,
2207.375);
+ verifyHistogram(histograms, 'experimental_network_request_start_time', 1,
+ 2207.375 + 110);
verifyHistogram(histograms, 'navigation_commit_time', 1, 4214.875);
- verifyHistogram(histograms, 'experimental_content_start_time', 1, 2707);
verifyHistogram(histograms, 'first_contentful_paint_time', 1, 1607);
+ verifyHistogram(histograms, 'process_create_to_app_start_time', 1, 107);
});
test('androidStartupMetric_twoSessions', function() {
@@ -249,12 +285,35 @@ tr.b.unittest.testSuite(function() {
2, 1700.0625, 1700.0625 + delta);
verifyHistogramRange(histograms, 'experimental_navigation_start_time',
2, 2200.375, 2200.375 + delta);
+ verifyHistogramRange(histograms, 'experimental_network_request_start_time',
+ 2, 2200.375 + 110, 2200.375 + delta + 110);
verifyHistogramRange(histograms, 'navigation_commit_time',
2, 4200.875, 4200.875 + delta * 2);
- verifyHistogramRange(histograms, 'experimental_content_start_time',
- 2, 2700, 2700 + delta);
verifyHistogramRange(histograms, 'first_contentful_paint_time',
2, 1600, 1600 + delta);
+ verifyHistogramRange(histograms, 'process_create_to_app_start_time', 2, 100,
+ 100 + delta);
+ });
+
+ test('androidStartupMetric_extraNavigations', function() {
+ const histograms = new tr.v.HistogramSet();
+ function makeTestModelWithExtraNavigations() {
+ return tr.c.TestUtils.newModel(function(model) {
+ const mainThread = fillModelWithOneBrowserSession(model, 0.0, 0.0);
+ addEarlyEventsToBeIgnored(model, 0.0);
+ addEarlyEventsToBeIgnored(model, 20.0);
+ // The first commit time is hardcoded to match how it is added in
+ // fillModelWithOneBrowserSession().
+ const veryFirstCommitTime = 9000.5 + 2000.5;
+ addNavigationEvent(mainThread, veryFirstCommitTime + 20.0, 5.0);
+ });
+ }
+ tr.metrics.sh.androidStartupMetric(histograms, makeTestModelWithExtraNavigations());
+ verifyHistogram(histograms, 'messageloop_start_time', 1, 1700.0625);
+ verifyHistogram(histograms, 'experimental_navigation_start_time', 1,
+ 2200.375);
+ verifyHistogram(histograms, 'experimental_network_request_start_time', 1,
+ 2200.375 + 110);
});
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html
index 0c20030edc1..fba89459e00 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html
@@ -6,6 +6,7 @@ found in the LICENSE file.
-->
<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
<link rel="import" href="/tracing/metrics/blink/gc_metric.html">
<link rel="import" href="/tracing/metrics/v8/utils.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/blink/resource_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/blink/resource_metric.html
new file mode 100644
index 00000000000..bb186a74e9d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/blink/resource_metric.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright 2021 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+
+<script>
+'use strict';
+
+/**
+ * This metric is used for for blink network metrics
+ * - blinkRequestResourceCount: the count of requested resources
+ */
+tr.exportTo('tr.metrics', function() {
+ function blinkResourceMetric(histograms, model, opt_options) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!chromeHelper) {
+ // Chrome isn't present.
+ return;
+ }
+ const CATEGORY = 'blink.resource';
+ const NAME = 'ResourceFetcher::requestResource';
+ let count = 0;
+ // Collect trace events.
+ for (const helper of Object.values(chromeHelper.rendererHelpers)) {
+ if (helper.isChromeTracingUI) continue;
+ const events = tr.e.chrome.EventFinderUtils.getMainThreadEvents(
+ helper, NAME, CATEGORY);
+ for (const event of events) {
+ count++;
+ }
+ }
+ // Generate histograms.
+ histograms.createHistogram(
+ 'blinkRequestResourceCount', tr.b.Unit.byName.count, count);
+ }
+
+ tr.metrics.MetricRegistry.register(blinkResourceMetric, {
+ supportsRangeOfInterest: false,
+ });
+
+ return {
+ blinkResourceMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/blink/resource_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/blink/resource_metric_test.html
new file mode 100644
index 00000000000..c11530c46fe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/blink/resource_metric_test.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright 2021 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/metrics/blink/resource_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('blinkRequestResourceCount_general', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ const mainFrame = { id: '0xdeadbeef', is_main: true };
+ const emitEvent = (time, cat, title, url, duration) => {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat,
+ title,
+ start: time,
+ duration,
+ args: {url},
+ }));
+ };
+ emitEvent(1000, 'blink.resource', 'ResourceFetcher::requestResource', 'A.js', 0.1);
+ emitEvent(2001, 'blink.resource', 'ignore', 'A.js', 0.1);
+ emitEvent(2002, 'ignore', 'ignore', 'A.js', 0.1);
+ emitEvent(3200, 'blink.resource', 'ResourceFetcher::requestResource', 'b.js', 0.1);
+ emitEvent(4201, 'ignore', 'ResourceFetcher::requestResource', 'b.js', 0.1);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.blinkResourceMetric(histograms, model);
+ const histogram = histograms.getHistogramNamed('blinkRequestResourceCount');
+ assert.strictEqual(histogram.sampleValues.length, 1);
+ assert.strictEqual(histogram.running.count, 1);
+ assert.strictEqual(histogram.running.mean, 2);
+ });
+});
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py b/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py
index 2a766b2477c..c5a9817c522 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py
@@ -91,7 +91,7 @@ class CompareSamplesUnittest(unittest.TestCase):
prev_bucket += width
for value in values:
for bucket in buckets:
- if value >= bucket['low'] and value < bucket['high']:
+ if bucket['low'] <= value < bucket['high']:
bucket['count'] += 1
break
charts = {
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/core_web_vitals_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/core_web_vitals_metric.html
new file mode 100644
index 00000000000..34382936e44
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/core_web_vitals_metric.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright 2022 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.
+-->
+
+<!--
+These metrics are designed to read off Core Web Vitals metrics (and their
+important diagnostic metrics like First Contentful Paint) from the trace events
+generated by the UkmPageLoadMetricsObserver, doing as little post-processing as
+possible. These should therefore automatically stay updated as the definitions
+in chromium C++ code evolve. See http://go/cwv-ukm-lab-metrics for more details.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/diagnostics/alert_groups.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ const CWV_HISTOGRAM_NAMES = {
+ FCP_HISTOGRAM_NAME: 'cwv:first_contentful_paint',
+ LCP_HISTOGRAM_NAME: 'cwv:largest_contentful_paint',
+ CLS_HISTOGRAM_NAME: 'cwv:cumulative_layout_shift',
+ };
+
+ function coreWebVitalsMetric(histograms, model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (chromeHelper === undefined) return;
+
+ const firstContentfulPaintHistogram =
+ histograms.createHistogram(CWV_HISTOGRAM_NAMES.FCP_HISTOGRAM_NAME,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], {
+ alertGrouping: [tr.v.d.ALERT_GROUPS.LOADING_PAINT],
+ });
+ const largestContentfulPaintHistogram =
+ histograms.createHistogram(CWV_HISTOGRAM_NAMES.LCP_HISTOGRAM_NAME,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], {
+ alertGrouping: [tr.v.d.ALERT_GROUPS.LOADING_PAINT],
+ });
+ const cumulativeLayoutShiftHistogram =
+ histograms.createHistogram(CWV_HISTOGRAM_NAMES.CLS_HISTOGRAM_NAME,
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter, [], {
+ alertGrouping: [tr.v.d.ALERT_GROUPS.LOADING_LAYOUT],
+ });
+
+ for (const browserHelper of Object.values(chromeHelper.browserHelpers)) {
+ const mainThread = browserHelper.mainThread;
+ const latestTimingBySourceId = new Map();
+
+ for (const event of mainThread.sliceGroup.childEvents()) {
+ if (event.category === 'loading' &&
+ event.title === 'UkmPageLoadTimingUpdate') {
+ const timingUpdate = event.args['ukm_page_load_timing_update'];
+ const sourceId = timingUpdate['ukm_source_id'];
+ latestTimingBySourceId.set(sourceId, timingUpdate);
+ }
+ }
+
+ for (const timingUpdate of latestTimingBySourceId.values()) {
+ const timingUpdateDiagnostic = {
+ 'page_load_timing': new tr.v.d.GenericSet([timingUpdate]),
+ };
+
+ // Note: This might always be a perfect round number because as of
+ // 2022/09/13, FCP values are clamped to 1ms resolution when sent to the
+ // browser process to prevent timing attacks.
+ const firstContentfulPaint =
+ timingUpdate['first_contentful_paint_ms'];
+
+ // Do not add any core web vitals metrics if page did not reach FCP.
+ if (firstContentfulPaint === undefined) continue;
+
+ firstContentfulPaintHistogram.addSample(
+ firstContentfulPaint, timingUpdateDiagnostic);
+
+ // Note: this could be undefined if somehow the browser determined the
+ // LCP data is invalid. They should be exactly the same cases where we
+ // also do not report data to UKM.
+ largestContentfulPaintHistogram.addSample(
+ timingUpdate['latest_largest_contentful_paint_ms'],
+ timingUpdateDiagnostic);
+
+ // Note: There is no need to specially handle the case when there are no
+ // layout shifts on the page. The latest_cumulative_layout_shift value
+ // should be reported as 0 in the trace event by the browser in that
+ // case, not undefined. Not that CLS can still be undefined if data
+ // is invalidated for some reason, e.g. see
+ // https://crsrc.org/c/components/page_load_metrics/browser/layout_shift_normalization.cc;l=25;drc=8d399817282e3c12ed54eb23ec42a5e418298ec6
+ cumulativeLayoutShiftHistogram.addSample(
+ timingUpdate['latest_cumulative_layout_shift'],
+ timingUpdateDiagnostic);
+ }
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(coreWebVitalsMetric);
+
+ return {
+ coreWebVitalsMetric,
+ CWV_HISTOGRAM_NAMES,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/core_web_vitals_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/core_web_vitals_metric_test.html
new file mode 100644
index 00000000000..25354674ae1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/core_web_vitals_metric_test.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<!--
+Copyright 2022 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/metrics/core_web_vitals_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const {
+ FCP_HISTOGRAM_NAME,
+ LCP_HISTOGRAM_NAME,
+ CLS_HISTOGRAM_NAME,
+ } = tr.metrics.CWV_HISTOGRAM_NAMES;
+
+ const timingUpdateEvent = (args) => {
+ return tr.c.TestUtils.newSliceEx({
+ title: 'UkmPageLoadTimingUpdate',
+ cat: 'loading',
+ start: args.ts,
+ duration: 0,
+ args: {
+ ukm_page_load_timing_update: {
+ ukm_source_id: args.sourceId,
+ first_contentful_paint_ms: args.fcp,
+ latest_largest_contentful_paint_ms: args.lcp,
+ latest_cumulative_layout_shift: args.cls,
+ },
+ },
+ });
+ };
+
+ test('histogramsAreAlwaysCreatedButCanBeEmpty', () => {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel((model) => {
+ console.log(model);
+ model.browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {title: 'SomeRandomEvent', start: 2, duration: 0}));
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.coreWebVitalsMetric(histograms, model);
+
+ assert.strictEqual(
+ 0, histograms.getHistogramNamed(FCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 0, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 0, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).numValues);
+ });
+
+ test('metricIsReportedFromLatestEvent', () => {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel((model) => {
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 42, ts: 11, fcp: 123, lcp: 300, cls: 2}));
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 42, ts: 12, fcp: 124, lcp: 301, cls: 3}));
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.coreWebVitalsMetric(histograms, model);
+
+ assert.strictEqual(
+ 1, histograms.getHistogramNamed(FCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 124, histograms.getHistogramNamed(FCP_HISTOGRAM_NAME).max);
+ assert.strictEqual(
+ 1, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 301, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).max);
+ assert.strictEqual(
+ 1, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 3, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).max);
+ });
+
+ test('noMetricIsReportedIfFCPIsNotReached', () => {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel((model) => {
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 42, ts: 11, lcp: 300, cls: 2})); // FCP missing.
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.coreWebVitalsMetric(histograms, model);
+
+ assert.strictEqual(
+ 0, histograms.getHistogramNamed(FCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 0, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 0, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).numValues);
+ });
+
+ test('multipleNavigations', () => {
+ const modelClsMissing =
+ tr.e.chrome.ChromeTestUtils.newChromeModel((model) => {
+ // First navigation.
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 42, ts: 11, fcp: 123, lcp: 300, cls: 2}));
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 42, ts: 11, fcp: 123, lcp: 301, cls: 3}));
+
+ // Second navigation.
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 43, ts: 11, fcp: 223, lcp: 400, cls: 12}));
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 43, ts: 11, fcp: 223, lcp: 401, cls: 13}));
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.coreWebVitalsMetric(histograms, modelClsMissing);
+
+ assert.strictEqual(
+ 2, histograms.getHistogramNamed(FCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 123, histograms.getHistogramNamed(FCP_HISTOGRAM_NAME).min);
+ assert.strictEqual(
+ 223, histograms.getHistogramNamed(FCP_HISTOGRAM_NAME).max);
+ assert.strictEqual(
+ 2, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 301, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).min);
+ assert.strictEqual(
+ 401, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).max);
+ assert.strictEqual(
+ 2, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 3, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).min);
+ assert.strictEqual(
+ 13, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).max);
+ });
+
+ test('metricIsNotReportedIfMissingInLatestButPresentInEarlierEvent', () => {
+ // Metric can become missing in later update events if it's invalidated /
+ // tainted somehow in the browser. We do not report the metric when that
+ // happens (as opposed to reporting the last valid value of the metric.)
+
+ const modelClsMissing =
+ tr.e.chrome.ChromeTestUtils.newChromeModel((model) => {
+ // First navigation.
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 42, ts: 11, fcp: 123, lcp: 300, cls: 2}));
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 42, ts: 11, fcp: 123, lcp: 301})); // CLS missing.
+
+ // Second navigation.
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 43, ts: 11, fcp: 123, lcp: 300, cls: 2}));
+ model.browserMain.sliceGroup.pushSlice(timingUpdateEvent(
+ {sourceId: 43, ts: 11, fcp: 123, cls: 3})); // LCP missing.
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.coreWebVitalsMetric(histograms, modelClsMissing);
+
+ assert.strictEqual(
+ 2, histograms.getHistogramNamed(FCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 1, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 301, histograms.getHistogramNamed(LCP_HISTOGRAM_NAME).max);
+ assert.strictEqual(
+ 1, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).numValues);
+ assert.strictEqual(
+ 3, histograms.getHistogramNamed(CLS_HISTOGRAM_NAME).max);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/count_sum_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/count_sum_metric.html
new file mode 100644
index 00000000000..35148fcce85
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/count_sum_metric.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!--
+Copyright 2021 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+
+<script>
+'use strict';
+
+/**
+ * This metric is used for custom benchmarks which need to record counts
+ * or sums of events ocurring in the renderer threads of traces. This is useful
+ * for one-off cluster telemetry analysis.
+ * For trace events with category "benchmark", and name "count_sum" and a
+ * "counter" field with the name of the counter, it records one or two metrics:
+ * - [counter]_count: the count of trace events with the same counter field.
+ * - [counter]_sum: the sum of values of trace events with that field, if any
+ * have a value field.
+ */
+tr.exportTo('tr.metrics', function() {
+ function countSumMetric(histograms, model, opt_options) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!chromeHelper) {
+ // Chrome isn't present.
+ return;
+ }
+
+ const CATEGORY = 'benchmark';
+ const NAME = 'count_sum';
+ const counts = new Map();
+ const sums = new Map();
+ // Collect trace events.
+ for (const pid in chromeHelper.rendererHelpers) {
+ const helper = chromeHelper.rendererHelpers[pid];
+ if (helper.isChromeTracingUI) continue;
+
+ const events = tr.e.chrome.EventFinderUtils.getMainThreadEvents(
+ helper, NAME, CATEGORY);
+ for (const event of events) {
+ const c = event.args.counter;
+ if (!c) {
+ continue;
+ }
+ if (!counts.get(c)) {
+ counts.set(c, 0);
+ }
+ counts.set(c, counts.get(c) + 1);
+ if (event.args.value) {
+ if (!sums.get(c)) {
+ sums.set(c, 0);
+ }
+ sums.set(c, sums.get(c) + event.args.value);
+ }
+ }
+ }
+
+ // Generate histograms.
+ counts.forEach((value, key) => {
+ histograms.createHistogram(
+ 'count_' + key, tr.b.Unit.byName.count, value);
+ });
+ sums.forEach((value, key) => {
+ histograms.createHistogram(
+ 'sum_' + key, tr.b.Unit.byName.unitlessNumber, value);
+ });
+ }
+
+ tr.metrics.MetricRegistry.register(countSumMetric, {
+ supportsRangeOfInterest: false,
+ });
+
+ return {
+ countSumMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/count_sum_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/count_sum_metric_test.html
new file mode 100644
index 00000000000..a34fb9c7b84
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/count_sum_metric_test.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/metrics/count_sum_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('countSumMetric_general', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ const mainFrame = { id: '0xdeadbeef', is_main: true };
+ const subframe = { id: '0xdeadb33f', is_main: false };
+ const emitEvent = (time, cat, title, counter, value) => {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat,
+ title,
+ start: time,
+ duration: 0.0,
+ args: {counter, value}
+ }));
+ };
+ emitEvent(1000, 'benchmark', 'count_sum', 'A', 2.1);
+ emitEvent(3000, 'benchmark', 'count_sum', 'B', null);
+ emitEvent(2000, 'benchmark', 'count_sum', 'A', 19.4);
+ emitEvent(4000, 'benchmark', 'count_sum', 'B', null);
+ emitEvent(4000, 'benchmark', 'count_sum', 'B', null);
+ emitEvent(4000, 'donotcount', 'count_sum', 'C', null);
+ emitEvent(4000, 'benchmark', 'foo', 'D', null);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.countSumMetric(histograms, model);
+ const histAc = histograms.getHistogramNamed('count_A');
+ assert.strictEqual(histAc.sampleValues.length, 1);
+ assert.strictEqual(histAc.running.count, 1);
+ assert.strictEqual(histAc.running.mean, 2);
+ const histAs = histograms.getHistogramNamed('sum_A');
+ assert.strictEqual(histAs.sampleValues.length, 1);
+ assert.strictEqual(histAs.running.count, 1);
+ assert.strictEqual(histAs.running.mean, 21.5);
+ const histBc = histograms.getHistogramNamed('count_B');
+ assert.strictEqual(histBc.sampleValues.length, 1);
+ assert.strictEqual(histBc.running.count, 1);
+ assert.strictEqual(histBc.running.mean, 3);
+ assert.isUndefined(histograms.getHistogramNamed('sum_B'));
+ assert.isUndefined(histograms.getHistogramNamed('count_C'));
+ assert.isUndefined(histograms.getHistogramNamed('sum_C'));
+ assert.isUndefined(histograms.getHistogramNamed('count_D'));
+ assert.isUndefined(histograms.getHistogramNamed('sum_D'));
+ });
+});
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/custom_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/custom_metric.html
new file mode 100644
index 00000000000..63823b49cee
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/custom_metric.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+
+<script>
+'use strict';
+
+/**
+ * This metric is used for custom performance benchmark.
+ * It captures the following:
+ * - Metrics reported by telemetry in the format of
+ * performance.mark('custom_metric:manifest:[{"name":<METRIC_NAME1>},{"name":<METRIC_NAME2>}...]');
+ * - Duration between performance.mark('<METRIC_NAME>:metric_begin')
+ * and performance.mark('<METRIC_NAME>:metric_end') on the JS side.
+ * - performance.mark('<METRIC_NAME>:<METRIC_VALUE>:metric_value')
+ * on the JS side.
+ */
+tr.exportTo('tr.metrics', function() {
+ function customMetric(histograms, model, opt_options) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!chromeHelper) {
+ // Chrome isn't present.
+ return;
+ }
+
+ const metrics = getMetrics(chromeHelper);
+ const traces = new Map();
+ const benchmarkValues = new Map();
+ // Collect trace events.
+ for (const helper of chromeHelper.browserHelpers) {
+ helper.iterAllThreads(function(thread) {
+ for (const slice of thread.sliceGroup.slices.concat(
+ thread.asyncSliceGroup.slices)) {
+ if (!slice.error && metrics.has(slice.title)) {
+ if (!traces.has(slice.title)) {
+ traces.set(slice.title, []);
+ }
+ traces.get(slice.title).push(slice.duration);
+ }
+ }
+ });
+ }
+
+ // Collect performance.mark().
+ const METRIC_BEGIN = 'metric_begin';
+ const METRIC_END = 'metric_end';
+ const METRIC_VALUE = 'metric_value';
+ const marks = new Map();
+ for (const helper of Object.values(chromeHelper.rendererHelpers)) {
+ if (!helper.mainThread) continue;
+ for (const event of helper.mainThread.sliceGroup.childEvents()) {
+ if (!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 === METRIC_BEGIN) {
+ marks.set(name, event);
+ } else if (lastPart === METRIC_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 === METRIC_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);
+ }
+ }
+ }
+ }
+
+ // Generate histograms.
+ traces.forEach((value, key) => {
+ createMetricHistogram(histograms,
+ key,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ value,
+ metrics.get(key));
+ });
+ benchmarkValues.forEach((value, key) => {
+ createMetricHistogram(histograms,
+ key,
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter,
+ value,
+ metrics.get(key));
+ });
+ }
+
+ // Get metrics from performance.mark()
+ function getMetrics(chromeHelper) {
+ const CUSTOM_METRIC_MANIFEST_PREFIX = 'custom_metric:manifest:'
+ for (const helper of Object.values(chromeHelper.rendererHelpers)) {
+ if (!helper.mainThread) continue;
+ for (const event of helper.mainThread.sliceGroup.childEvents()) {
+ if (!event.category.includes('blink.user_timing')) continue;
+ const {title} = event;
+ if (title.startsWith(CUSTOM_METRIC_MANIFEST_PREFIX)) {
+ const result = JSON.parse(title.substring(CUSTOM_METRIC_MANIFEST_PREFIX.length));
+ return new Map(result.map(event => [event.name, event]));
+ }
+ }
+ }
+ return new Map();
+ }
+
+ // Create histogram with default unit and
+ // read unit and description from the metric manifest if available.
+ function createMetricHistogram(histograms, key, defaultUnit, value, metric) {
+ let unit = metric && metric.unit;
+ if (unit) {
+ unit = tr.b.Unit.fromJSON(unit);
+ }
+ const description = metric && metric.description;
+ const histogram = histograms.createHistogram(key,
+ unit || defaultUnit,
+ value);
+ if (description) {
+ histogram.description = description;
+ }
+ return histogram;
+ }
+
+ tr.metrics.MetricRegistry.register(customMetric, {
+ supportsRangeOfInterest: false,
+ });
+
+ return {
+ customMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/custom_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/custom_metric_test.html
new file mode 100644
index 00000000000..4a90395a6ef
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/custom_metric_test.html
@@ -0,0 +1,273 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/custom_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('customMetric_collectTrace', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserThread = setUpBrowserThread(model);
+ addTraces(browserThread);
+ addSingleTrace(setUpOtherBrowserThread(model));
+ addSingleTrace(setUpOtherRendererThread(model));
+ const rendererMainThread = setUpRendererMainThread(model);
+ setMetrics(rendererMainThread);
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.customMetric(histograms, model);
+ const hist1 = histograms.getHistogramNamed('metric1');
+ assert.strictEqual(hist1.numValues, 2);
+ assert.strictEqual(hist1.unit.asJSON(), 'ms_smallerIsBetter');
+ const hist2 = histograms.getHistogramNamed('metric2');
+ assert.strictEqual(hist2.numValues, 1);
+ assert.strictEqual(hist2.unit.asJSON(), 'ms_biggerIsBetter');
+ assert.strictEqual(hist2.description, 'This is metric2');
+ const hist3 = histograms.getHistogramNamed('metric3');
+ // metric3 is not collected because its name isn't reported.
+ assert.isUndefined(hist3);
+ const hist4 = histograms.getHistogramNamed('metric4');
+ assert.strictEqual(hist4.numValues, 2);
+ // metric5 is collected from both other browser thread and
+ // other renderer thread.
+ const hist5 = histograms.getHistogramNamed('metric5');
+ assert.strictEqual(hist5.numValues, 2);
+ });
+
+ test('customMetric_collectPerformanceMark', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const rendererMainThread = setUpRendererMainThread(model);
+ addPerformanceMark(rendererMainThread);
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.customMetric(histograms, model);
+ const hist1 = histograms.getHistogramNamed('metric1');
+ assert.strictEqual(hist1.numValues, 2);
+ assert.strictEqual(hist1.max, 5.0);
+ assert.strictEqual(hist1.min, 2.0);
+ assert.strictEqual(hist1.average, 3.5);
+ const hist2 = histograms.getHistogramNamed('metric2');
+ assert.strictEqual(hist2.numValues, 1);
+ assert.strictEqual(hist2.max, 18.0);
+ assert.strictEqual(hist2.min, 18.0);
+ assert.strictEqual(hist2.average, 18.0);
+ // metric3 is not collected because
+ // ":metric_begin" and ":metric_end" are missing.
+ assert.isUndefined(histograms.getHistogramNamed('metric3'));
+ // metric4 is not collected because
+ // ":metric_end" is missing.
+ assert.isUndefined(histograms.getHistogramNamed('metric4'));
+ // metric5 is not collected because
+ // ":metric_begin" is missing.
+ assert.isUndefined(histograms.getHistogramNamed('metric5'));
+ const hist3 = histograms.getHistogramNamed('metric6');
+ assert.strictEqual(hist3.numValues, 2);
+ assert.strictEqual(hist3.max, 51);
+ assert.strictEqual(hist3.min, 49);
+ assert.strictEqual(hist3.average, 50);
+ // metric7 is not collected because
+ // benmark value is invalid.
+ assert.isUndefined(histograms.getHistogramNamed('metric7'));
+ // metric8 is not collected because
+ // benchmark value is missing.
+ assert.isUndefined(histograms.getHistogramNamed('metric8'));
+ });
+
+ function setUpBrowserThread(model) {
+ const BROWSER_PROCESS_ID = 1234;
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const browserThread = browserProcess.getOrCreateThread(2);
+ browserThread.name = 'CrBrowserMain';
+ return browserThread;
+ }
+
+ function setUpRendererMainThread(model) {
+ const RENDERER_PROCESS_ID = 2345;
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(23);
+ mainThread.name = 'CrRendererMain';
+ return mainThread;
+ }
+
+ function setUpOtherBrowserThread(model) {
+ const BROWSER_PROCESS_ID = 1234;
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const thread = browserProcess.getOrCreateThread(3);
+ thread.name = 'Other';
+ return thread;
+ }
+
+ function setUpOtherRendererThread(model) {
+ const RENDERER_PROCESS_ID = 2345;
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const thread = rendererProcess.getOrCreateThread(4);
+ thread.name = 'Other';
+ return thread;
+ }
+
+ function addEvent(mainThread, event) {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: event.title,
+ start: event.start,
+ duration: 0.0,
+ }));
+ }
+
+ function addTraces(thread) {
+ [
+ {
+ cat: 'browser',
+ title: 'metric1',
+ start: 1,
+ duration: 1,
+ },
+ {
+ cat: 'browser',
+ title: 'metric1',
+ start: 2,
+ duration: 2,
+ },
+ {
+ cat: 'browser',
+ title: 'metric2',
+ start: 3,
+ duration: 3,
+ },
+ {
+ cat: 'browser',
+ title: 'metric3',
+ start: 4,
+ duration: 4,
+ }
+ ].forEach(slice => {
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(slice));
+ });
+
+ [
+ {
+ cat: 'browser',
+ title: 'metric4',
+ start: 1,
+ duration: 1,
+ },
+ {
+ cat: 'browser',
+ title: 'metric4',
+ start: 2,
+ duration: 2,
+ }
+ ].forEach(slice => {
+ thread.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(slice));
+ });
+ }
+
+ function addSingleTrace(thread) {
+ const slice = {
+ cat: 'browser',
+ title: 'metric5',
+ start: 1,
+ duration: 1,
+ };
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(slice));
+ }
+
+ function setMetrics(thread) {
+ const traceEvents = [
+ {
+ name: "metric1",
+ },
+ {
+ name: "metric2",
+ unit: "ms_biggerIsBetter",
+ description: "This is metric2"
+ },
+ {
+ name: "metric4",
+ },
+ {
+ name: "metric5",
+ },
+ ]
+ const report = `custom_metric:manifest:${JSON.stringify(traceEvents)}`;
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: report,
+ start: 0,
+ duration: 0,
+ }));
+ }
+
+ function addPerformanceMark(thread) {
+ [
+ {
+ title: 'metric1:metric_begin',
+ start: 10,
+ },
+ {
+ title: 'metric1:metric_end',
+ start: 15,
+ },
+ {
+ title: 'metric1:metric_begin',
+ start: 17,
+ },
+ {
+ title: 'metric1:metric_end',
+ start: 19,
+ },
+ {
+ title: 'metric2:metric_begin',
+ start: 2,
+ },
+ {
+ title: 'metric2:metric_end',
+ start: 20,
+ },
+ {
+ title: 'metric3',
+ start: 25,
+ },
+ {
+ title: 'metric4:metric_begin',
+ start: 5,
+ },
+ {
+ title: 'metric5:metric_end',
+ start: 10,
+ },
+ {
+ title: 'metric6:49:metric_value',
+ start: 10,
+ },
+ {
+ title: 'metric6:51:metric_value',
+ start: 20,
+ },
+ {
+ title: 'metric7:invalid value:metric_value',
+ start: 10,
+ },
+ {
+ title: 'metric8:metric_value',
+ start: 10,
+ }
+ ].forEach(slice => {
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: slice.title,
+ start: slice.start,
+ duration: 0,
+ }));
+ });
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/discover.py b/chromium/third_party/catapult/tracing/tracing/metrics/discover.py
index ef532c6d0df..75802db5d06 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/discover.py
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/discover.py
@@ -30,5 +30,4 @@ def DiscoverMetrics(modules_to_load):
if res.returncode != 0:
raise RuntimeError('Error running metrics_discover_cmdline: ' + res.stdout)
- else:
- return [str(m) for m in json.loads(res.stdout)]
+ return [str(m) for m in json.loads(res.stdout)]
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py b/chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py
index 10b81b547c8..978a9146d28 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py
@@ -11,7 +11,7 @@ class MetricsDiscoverUnittest(unittest.TestCase):
self.assertFalse(discover.DiscoverMetrics([]))
def testMetricsDiscoverNonEmpty(self):
- self.assertEquals(['sampleMetric'], discover.DiscoverMetrics(
+ self.assertEqual(['sampleMetric'], discover.DiscoverMetrics(
['/tracing/metrics/sample_metric.html']))
def testMetricsDiscoverMultipleMetrics(self):
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html
index 9ec388ec862..0b11d30142b 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html
@@ -71,6 +71,14 @@ tr.exportTo('tr.metrics', function() {
processData.calculateSeekTimes(mainThread);
processData.calculateBufferingTimes(mainThread);
+ // Roughness metrics are output from a thread pool worker, so we don't
+ // have a convenient name for the thread. Check all threads.
+ const allThreads =
+ rendererHelper.process.findAllThreadsMatching(function() {
+ return true;
+ });
+ processData.calculateVideoPlaybackQuality(allThreads);
+
processData.addMetricToHistograms(histograms);
}
}
@@ -160,6 +168,20 @@ tr.exportTo('tr.metrics', function() {
}
}
+ 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);
@@ -191,6 +213,8 @@ tr.exportTo('tr.metrics', function() {
this.seekError_ = false;
this.seekTimes_ = new Map();
this.currentSeek_ = undefined;
+ this.roughness_ = undefined;
+ this.freezing_ = undefined;
}
// API methods for retrieving metric values. Each method returns undefined
@@ -245,6 +269,16 @@ tr.exportTo('tr.metrics', function() {
return this.seekTimes_;
}
+ // Reports aggregate roughness.
+ get roughness() {
+ return this.roughness_;
+ }
+
+ // Reports aggregate freezing.
+ get freezing() {
+ return this.freezing_;
+ }
+
// API methods for processing data from trace events.
processVideoRenderTime(videoRenderTime) {
@@ -359,6 +393,20 @@ tr.exportTo('tr.metrics', function() {
}
}
+ processVideoRoughness(roughness) {
+ // Record the worst roughness.
+ if (this.roughness_ === undefined || this.roughness_ > roughness) {
+ this.roughness_ = roughness;
+ }
+ }
+
+ processVideoFreezing(freezing) {
+ // Record the worst 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,
@@ -384,6 +432,12 @@ tr.exportTo('tr.metrics', function() {
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);
}
// @private
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html b/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html
index 02f5dcf02b5..0cb63b11c8d 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html
@@ -147,6 +147,12 @@ tr.exportTo('tr.metrics', function() {
function validateDiagnosticNames(histograms) {
for (const hist of histograms) {
for (const name of hist.diagnostics.keys()) {
+ if (name === tr.v.d.RESERVED_NAMES.ALERT_GROUPING) {
+ // Metrics can set alert grouping when they create histogram. It's
+ // still a reserved diagnostic because that helps us enforce the right
+ // diagnostic shape.
+ continue;
+ }
if (tr.v.d.RESERVED_NAMES_SET.has(name)) {
throw new Error(
`Illegal diagnostic name "${name}" on Histogram "${hist.name}"`);
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/OWNERS b/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/OWNERS
new file mode 100644
index 00000000000..228f0c3184b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/OWNERS
@@ -0,0 +1,2 @@
+bikineev@chromium.org
+mlippautz@chromium.org
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html
new file mode 100644
index 00000000000..33743f757a5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric.html
@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_processes.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains implementations of PCScan metrics. PCScan
+ * is the algorithm that eliminates use-after-free bugs by verifying that there
+ * are no pointers in memory which point to explicitly freed objects before
+ * actually releasing their memory.
+ *
+ * pa:pcscan:<process_name>:<scanner|mutator>
+ * ========================
+ * The overall time spent on scanning the partition alloc heap for a specific
+ * process either in the scanner or mutator thread (process_name can be either 'browser_process' or 'renderer_processes').
+ *
+ * pa:pcscan:<process_name>:<scanner|mutator>:<phase>
+ * ========================
+ * Time spent on a certain PCScan phase ('clear', 'scan' or 'sweep').
+ */
+tr.exportTo('tr.metrics.pa', function() {
+ function pcscanMetric(histograms, model) {
+ function createTimeNumericForProcess(name, processName, context, desc) {
+ function createNumeric(name, desc) {
+ const n = new tr.v.Histogram(name,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ n.description = desc;
+ n.customizeSummaryOptions({
+ avg: true,
+ count: true,
+ max: true,
+ min: true,
+ std: true,
+ sum: true});
+ return n;
+ }
+ const scheme = ['pa', 'pcscan', processName, context];
+ if (name) scheme.push(name);
+ return createNumeric(scheme.join(':'), desc);
+ }
+
+ function createSizeNumericForProcess(name, processName, desc) {
+ function createNumeric(name, desc) {
+ const n = new tr.v.Histogram(name,
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter);
+ n.description = desc;
+ n.customizeSummaryOptions({
+ avg: true,
+ count: true,
+ max: true,
+ min: true,
+ std: true,
+ sum: true});
+ return n;
+ }
+ const scheme = ['pa', 'pcscan', processName, name];
+ return createNumeric(scheme.join(':'), desc);
+ }
+
+ function createPercentNumericForProcess(name, processName, desc) {
+ function createNumeric(name, desc) {
+ const n = new tr.v.Histogram(name,
+ tr.b.Unit.byName.normalizedPercentage_smallerIsBetter);
+ n.description = desc;
+ n.customizeSummaryOptions({
+ avg: true,
+ count: true,
+ max: true,
+ min: true,
+ std: true,
+ sum: true});
+ return n;
+ }
+ const scheme = ['pa', 'pcscan', processName, name];
+ return createNumeric(scheme.join(':'), desc);
+ }
+
+
+ function createHistsForProcess(processName) {
+ return {
+ scanner_scan: createTimeNumericForProcess('scan', processName, 'scanner',
+ 'Time for scanning heap for quarantine pointers on concurrent threads'),
+ scanner_sweep: createTimeNumericForProcess('sweep', processName, 'scanner',
+ 'Time for sweeping quarantine'),
+ scanner_clear: createTimeNumericForProcess('clear', processName, 'scanner',
+ 'Time for clearing quarantine entries'),
+ scanner_total: createTimeNumericForProcess('', processName, 'scanner',
+ 'Total time for PCScan execution on concurrent threads'),
+ mutator_scan_stack: createTimeNumericForProcess('scan_stack', processName, 'mutator',
+ 'Time for scanning stack for quarantine pointers on mutator threads'),
+ mutator_scan: createTimeNumericForProcess('scan', processName, 'mutator',
+ 'Time for scanning heap for quarantine pointers on mutator threads'),
+ mutator_clear: createTimeNumericForProcess('clear', processName, 'mutator',
+ 'Time for clearing heap quarantine entries on mutator threads'),
+ mutator_total: createTimeNumericForProcess('', processName, 'mutator',
+ 'Total time for PCScan execution on mutator threads (inside safepoints)'),
+ survived_quarantine_size: createSizeNumericForProcess(
+ 'survived_quarantine_size', processName,
+ 'Size in bytes of survived quarantined objects after each *Scan cycle'),
+ survived_quarantine_percent: createPercentNumericForProcess(
+ 'survived_quarantine_percent', processName,
+ 'Percent of survived quarantined objects after a *Scan cycle relative ' +
+ 'to the size of quarantined objects before the cycle'),
+ };
+ }
+
+ function addSliceSample(hists, slice) {
+ if (slice.category !== 'partition_alloc') return;
+ if (!(slice instanceof tr.model.ThreadSlice)) return;
+
+ if (slice.title === 'PCScan.Scanner.Scan') {
+ hists.scanner_scan.addSample(slice.duration);
+ } else if (slice.title === 'PCScan.Scanner.Sweep') {
+ hists.scanner_sweep.addSample(slice.duration);
+ } else if (slice.title === 'PCScan.Scanner.Clear') {
+ hists.scanner_clear.addSample(slice.duration);
+ } else if (slice.title === 'PCScan.Scanner') {
+ hists.scanner_total.addSample(slice.duration);
+ } else if (slice.title === 'PCScan.Mutator.ScanStack') {
+ hists.mutator_scan_stack.addSample(slice.duration);
+ } else if (slice.title === 'PCScan.Mutator.Scan') {
+ hists.mutator_scan.addSample(slice.duration);
+ } else if (slice.title === 'PCScan.Mutator.Clear') {
+ hists.mutator_clear.addSample(slice.duration);
+ } else if (slice.title === 'PCScan.Mutator') {
+ hists.mutator_total.addSample(slice.duration);
+ }
+ }
+
+ function addCounterSample(hists, counter) {
+ if (counter.category !== 'partition_alloc') return;
+ if (!(counter instanceof tr.model.Counter)) return;
+
+ for (const series of counter.series) {
+ for (const sample of series.samples) {
+ if (counter.name === 'PCScan.SurvivedQuarantineSize') {
+ hists.survived_quarantine_size.addSample(sample.value);
+ } else if (counter.name === 'PCScan.SurvivedQuarantinePercent') {
+ // Divide by 1000, since StatsCollector multiplies it by 1000.
+ hists.survived_quarantine_percent.addSample(sample.value / 1000);
+ }
+ }
+ }
+ }
+
+ function addHistsForProcess(processHists, processHelpers) {
+ for (const helper of Object.values(processHelpers)) {
+ const processName = tr.e.chrome.chrome_processes.
+ canonicalizeProcessName(helper.process.name);
+ if (!processHists.has(processName)) {
+ processHists.set(processName, createHistsForProcess(processName));
+ }
+ for (const slice of helper.process.getDescendantEvents()) {
+ addSliceSample(processHists.get(processName), slice);
+ }
+ for (const tid in helper.process.counters) {
+ addCounterSample(processHists.get(processName), helper.process.counters[tid]);
+ }
+ }
+ }
+
+ const helper =
+ model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+
+ const processHists = new Map();
+ addHistsForProcess(processHists, helper.browserHelpers);
+ addHistsForProcess(processHists, helper.rendererHelpers);
+
+ for (const hists of processHists.values()) {
+ for (const hist of Object.values(hists)) {
+ histograms.addHistogram(hist);
+ }
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(pcscanMetric);
+
+ return {
+ pcscanMetric,
+ };
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric_test.html
new file mode 100644
index 00000000000..ca43e546b56
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/partition_alloc/pcscan_metric_test.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_processes.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/metrics/partition_alloc/pcscan_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const CHROME_PROCESS_NAMES =
+ tr.e.chrome.chrome_processes.CHROME_PROCESS_NAMES;
+
+ function makeTestModelFor(processName) {
+ return tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const process = (processName === CHROME_PROCESS_NAMES.RENDERER ?
+ model.rendererProcess : model.browserProcess);
+ const thread = process.getOrCreateThread(2);
+ // Create slices.
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'partition_alloc',
+ title: 'PCScan.Scanner',
+ start: 200,
+ duration: 100,
+ cpuStart: 200,
+ cpuDuration: 100
+ }));
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'partition_alloc',
+ title: 'PCScan.Mutator',
+ start: 200,
+ duration: 50,
+ cpuStart: 200,
+ cpuDuration: 50
+ }));
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'partition_alloc',
+ title: 'PCScan.Scanner.Clear',
+ start: 200,
+ duration: 16,
+ cpuStart: 200,
+ cpuDuration: 16
+ }));
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'partition_alloc',
+ title: 'PCScan.Scanner.Scan',
+ start: 216,
+ duration: 32,
+ cpuStart: 216,
+ cpuDuration: 32
+ }));
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'partition_alloc',
+ title: 'PCScan.Mutator.Clear',
+ start: 210,
+ duration: 8,
+ cpuStart: 210,
+ cpuDuration: 8
+ }));
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'partition_alloc',
+ title: 'PCScan.Mutator.ScanStack',
+ start: 218,
+ duration: 14,
+ cpuStart: 218,
+ cpuDuration: 14
+ }));
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'partition_alloc',
+ title: 'PCScan.Mutator.Scan',
+ start: 232,
+ duration: 16,
+ cpuStart: 232,
+ cpuDuration: 16
+ }));
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'partition_alloc',
+ title: 'PCScan.Scanner.Sweep',
+ start: 248,
+ duration: 42,
+ cpuStart: 248,
+ cpuDuration: 42
+ }));
+ // Create counters.
+ const quarantineSizeCounter = process.getOrCreateCounter('partition_alloc', 'PCScan.SurvivedQuarantineSize');
+ const quarantineSizeSeries = new tr.model.CounterSeries('value', 0);
+ quarantineSizeSeries.addCounterSample(1, 200000);
+ quarantineSizeSeries.addCounterSample(3, 300000);
+ quarantineSizeCounter.addSeries(quarantineSizeSeries);
+ const quarantineRateCounter = process.getOrCreateCounter('partition_alloc', 'PCScan.SurvivedQuarantinePercent');
+ const quarantineRateSeries = new tr.model.CounterSeries('value', 0);
+ quarantineRateSeries.addCounterSample(1, 0.14 * 1000);
+ quarantineRateSeries.addCounterSample(3, 0.21 * 1000);
+ quarantineRateCounter.addSeries(quarantineRateSeries);
+ });
+ }
+
+ function testPCScanMetrics(processName) {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.pa.pcscanMetric(histograms, makeTestModelFor(processName));
+ assert.closeTo(100, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':scanner').average, 1e-2);
+ assert.closeTo(50, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':mutator').average, 1e-2);
+ assert.closeTo(16, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':scanner:clear').average, 1e-2);
+ assert.closeTo(32, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':scanner:scan').average, 1e-2);
+ assert.closeTo(8, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':mutator:clear').average, 1e-2);
+ assert.closeTo(14, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':mutator:scan_stack').average, 1e-2);
+ assert.closeTo(16, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':mutator:scan').average, 1e-2);
+ assert.closeTo(42, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':scanner:sweep').average, 1e-2);
+ assert.closeTo(250000, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':survived_quarantine_size').average, 1e-2);
+ assert.closeTo(0.175, histograms.getHistogramNamed(
+ 'pa:pcscan:' + processName + ':survived_quarantine_percent').average, 1e-2);
+ }
+
+ test('pcscanMetricForBrowser', function() {
+ testPCScanMetrics(CHROME_PROCESS_NAMES.BROWSER);
+ });
+
+ test('pcscanMetricForRenderer', function() {
+ testPCScanMetrics(CHROME_PROCESS_NAMES.RENDERER);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html
index 16e185c172e..e6d55984e27 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html
@@ -7,6 +7,9 @@ found in the LICENSE file.
<link rel="import" href="/tracing/base/math/statistics.html">
<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+
<link rel="import" href="/tracing/value/histogram.html">
<script>
@@ -15,7 +18,7 @@ found in the LICENSE file.
/**
* @fileoverview This file contains implementations of the following metrics.
*
- * The addCpuUtilizationHistograms method can generate the following sets of
+ * The addCpuSegmentCostHistograms method can generate the following sets of
* metrics, dependeing on the input values for segments, and segmentCostFunc.
*
* thread_{thread group}_cpu_time_per_frame
@@ -34,6 +37,13 @@ found in the LICENSE file.
* This set of metrics show the distribution of the number of task in each
* display compositor's frame of a thread group.
*
+ * The addCpuWallTimeHistogram method generates the metric:
+ * cpu_wall_time_ratio
+ * ==================
+ * segments: display compositor's frames
+ *
+ * This metric shows the ratio of cpu usage to wall time.
+ *
* Note: the CPU usage in all above-mentioned metrics, is approximated from
* top-level trace events in each thread; it does not come from the OS. So, the
* metric may be noisy and not be very meaningful for threads that do not have a
@@ -86,7 +96,7 @@ tr.exportTo('tr.metrics.rendering', function() {
if (isOther) yield 'other';
}
- function addCpuUtilizationHistograms(
+ function addCpuSegmentCostHistograms(
histograms, model, segments, segmentCostFunc, histogramNameFunc,
description) {
const categoryValues = new Map();
@@ -120,14 +130,26 @@ tr.exportTo('tr.metrics.rendering', function() {
}
}
- const SUMMARY_OPTIONS = {
- percentile: [0.90, 0.95],
- ci: [0.95],
- };
+ function addCpuWallTimeHistogram(histograms, model, segments) {
+ let totalWallTime = 0;
+ let totalCpuTime = 0;
+ for (const segment of segments) {
+ 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,
+ totalWallTime ? totalCpuTime / totalWallTime : NaN,
+ { description: 'Ratio of total cpu-time vs. wall-time.',
+ summaryOptions: {},
+ });
+ }
return {
- addCpuUtilizationHistograms,
- SUMMARY_OPTIONS,
+ addCpuSegmentCostHistograms,
+ addCpuWallTimeHistogram,
};
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html
index 9c3e0d21def..a5aab4912fc 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html
@@ -38,7 +38,7 @@ tr.b.unittest.testSuite(function() {
{ start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
});
const histograms = new tr.v.HistogramSet();
- tr.metrics.rendering.addCpuUtilizationHistograms(
+ tr.metrics.rendering.addCpuSegmentCostHistograms(
histograms, model, [new tr.model.um.Segment(0, 10)],
(thread, segment) => thread.getCpuTimeForRange(segment.boundsRange),
category => `thread_${category}_cpu_time_per_frame`, 'description');
@@ -95,7 +95,7 @@ tr.b.unittest.testSuite(function() {
{ start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
});
const histograms = new tr.v.HistogramSet();
- tr.metrics.rendering.addCpuUtilizationHistograms(
+ tr.metrics.rendering.addCpuSegmentCostHistograms(
histograms, model,
[new tr.model.um.Segment(0, 5), new tr.model.um.Segment(5, 5)],
(thread, segment) => thread.getCpuTimeForRange(segment.boundsRange),
@@ -134,7 +134,7 @@ tr.b.unittest.testSuite(function() {
{ start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
});
const histograms = new tr.v.HistogramSet();
- tr.metrics.rendering.addCpuUtilizationHistograms(
+ tr.metrics.rendering.addCpuSegmentCostHistograms(
histograms, model, [new tr.model.um.Segment(0, 10)],
(thread, segment) => thread.getCpuTimeForRange(segment.boundsRange),
category => `thread_${category}_cpu_time_per_frame`, 'description');
@@ -176,7 +176,7 @@ tr.b.unittest.testSuite(function() {
{ start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
});
const histograms = new tr.v.HistogramSet();
- tr.metrics.rendering.addCpuUtilizationHistograms(
+ tr.metrics.rendering.addCpuSegmentCostHistograms(
histograms, model, [new tr.model.um.Segment(0, 10)],
(thread, segment) =>
thread.getNumToplevelSlicesForRange(segment.boundsRange),
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_segment_filter.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_segment_filter.html
new file mode 100644
index 00000000000..9ebaa87d003
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_segment_filter.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<!--
+Copyright 2022 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/metrics/rendering/cpu_utilization.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/value/diagnostics/generic_set.html">
+<link rel="import" href="/tracing/value/diagnostics/related_event_set.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains helper methods to filter Segments to just
+ * those for the displaying of frames.
+ */
+tr.exportTo('tr.metrics.rendering', function() {
+ // Various tracing events.
+ const DISPLAY_EVENT = 'BenchmarkInstrumentation::DisplayRenderingStats';
+ const DRM_EVENT = 'DrmEventFlipComplete';
+ const SURFACE_FLINGER_EVENT = 'vsync_before';
+
+
+ // The least number of frames needed to report frame_times.
+ // Measurements done with very few frames tend to be unstable.
+ // See crbug.com/954984 for example.
+ const MIN_FRAME_COUNT = 10;
+
+
+ class FrameEvent {
+ constructor(event) {
+ this.event_ = event;
+ }
+
+ get eventStart() {
+ return this.event_.start;
+ }
+
+ get frameStart() {
+ if (this.event_.title !== DRM_EVENT) return this.event_.start;
+ const data = this.event_.args.data;
+ const TIME = tr.b.UnitScale.TIME;
+ return tr.b.convertUnit(data['vblank.tv_sec'], TIME.SEC, TIME.MILLI_SEC) +
+ tr.b.convertUnit(
+ data['vblank.tv_usec'], TIME.MICRO_SEC, TIME.MILLI_SEC);
+ }
+
+ get event() { return this.event_; }
+ }
+
+
+ function getDisplayCompositorPresentationEvents_(model) {
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!modelHelper || !modelHelper.browserProcess) return [];
+ // On ChromeOS, DRM events, if they exist, are the source of truth. On
+ // Android, Surface Flinger events are the source of truth. Otherwise, look
+ // for display rendering stats. With viz, display rendering stats are
+ // emitted from the GPU process; otherwise, they are emitted from the
+ // browser process.
+ let events = [];
+ if (modelHelper.surfaceFlingerProcess) {
+ events = [...modelHelper.surfaceFlingerProcess.findTopmostSlicesNamed(
+ SURFACE_FLINGER_EVENT)];
+ if (events.length > 0) return events;
+ }
+ if (modelHelper.gpuHelper) {
+ const gpuProcess = modelHelper.gpuHelper.process;
+ events = [...gpuProcess.findTopmostSlicesNamed(DRM_EVENT)];
+ if (events.length > 0) return events;
+ events = [...gpuProcess.findTopmostSlicesNamed(DISPLAY_EVENT)];
+ if (events.length > 0) return events;
+ }
+ return [...modelHelper.browserProcess.findTopmostSlicesNamed(
+ DISPLAY_EVENT)];
+ }
+
+
+ function computeFrameSegments(model, segments) {
+ const events = getDisplayCompositorPresentationEvents_(model);
+ if (!events) return [];
+ // We use filterArray for the sake of a cleaner code. The time complexity
+ // will be O(m + n log m), where m is |timestamps| and n is |segments|.
+ // Alternatively, we could directly loop through the timestamps and segments
+ // here for a slightly better time complexity of O(m + n).
+ 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 < MIN_FRAME_COUNT) continue;
+ for (let i = 1; i < filtered.length; i++) {
+ const duration = filtered[i].frameStart - filtered[i - 1].frameStart;
+ frameSegments.push(new tr.model.um.Segment(filtered[i - 1].eventStart, duration));
+ }
+ }
+ return frameSegments;
+ }
+
+ return {
+ computeFrameSegments,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html
index 386bd444658..aa690649f66 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html
@@ -22,8 +22,8 @@ found in the LICENSE file.
* ScheduledActionSendBeginMainFrame event in the compositor thread and the
* corresponding BeginMainFrame event in the main thread.
*
- * TODO(chiniforooshan): Does it make sense to just ignore data from OOPIF
- * processes, like what we are doing here?
+ * For OOPIF they might send a BeginMainFrame with the same ID, in those cases
+ * the earliest slice's time is used.
*/
tr.exportTo('tr.metrics.rendering', function() {
// Various tracing events.
@@ -38,7 +38,12 @@ tr.exportTo('tr.metrics.rendering', function() {
if (slice.title !== title) continue;
const id = slice.args.begin_frame_id;
if (id === undefined) throw new Error('Event is missing begin_frame_id');
- if (out.has(id)) throw new Error(`There must be exactly one ${title}`);
+ // If we've already seen an even with this name, we only track the first.
+ // Multiple ThreadProxy::BeginMainFrames can occur when OOPIF share the
+ // same origin and get routed to the same RendererMain.
+ if (out.has(id) && out[id] <= slice.start) {
+ continue;
+ }
out.set(id, slice.start);
}
return out;
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html
index b7d292eec14..0944c00c049 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html
@@ -6,7 +6,8 @@ found in the LICENSE file.
-->
<link rel="import" href="/tracing/metrics/metric_registry.html">
-<link rel="import" href="/tracing/metrics/rendering/frame_time.html">
+<link rel="import" href="/tracing/metrics/rendering/cpu_utilization.html">
+<link rel="import" href="/tracing/metrics/rendering/frame_segment_filter.html">
<link rel="import" href="/tracing/metrics/rendering/image_decode_time.html">
<link rel="import" href="/tracing/metrics/rendering/pixels.html">
<link rel="import" href="/tracing/metrics/rendering/queueing_duration.html">
@@ -28,19 +29,28 @@ tr.exportTo('tr.metrics.rendering', function() {
segments = chromeHelper.telemetryHelper.animationSegments;
}
if (segments.length > 0) {
- tr.metrics.rendering.addFrameTimeHistograms(histograms, model, segments);
+ const frameSegments = tr.metrics.rendering.computeFrameSegments(model, segments);
+ if (frameSegments.length > 0) {
+ tr.metrics.rendering.addCpuSegmentCostHistograms(
+ 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.addCpuSegmentCostHistograms(
+ histograms, model, frameSegments,
+ (thread, segment) =>
+ thread.getNumToplevelSlicesForRange(segment.boundsRange),
+ category => `tasks_per_frame_${category}`,
+ 'Number of tasks of a thread group per frame');
+ tr.metrics.rendering.addCpuWallTimeHistogram(histograms, model, frameSegments);
+ }
+
tr.metrics.rendering.addImageDecodeTimeHistograms(histograms, model,
segments);
tr.metrics.rendering.addPixelsHistograms(histograms, model, segments);
tr.metrics.rendering.addQueueingDurationHistograms(
histograms, model, segments);
}
-
- const uiSegments = chromeHelper.telemetryHelper.uiSegments;
- if (uiSegments.length > 0) {
- tr.metrics.rendering.addUIFrameTimeHistograms(
- histograms, model, chromeHelper.telemetryHelper.uiSegments);
- }
}
tr.metrics.MetricRegistry.register(renderingMetric, {
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html
index 1d30078252a..8cdf4b42b5c 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html
@@ -39,11 +39,11 @@ tr.b.unittest.testSuite(function() {
// The gesture interaction record should be adjusted to [10, 30]. So, the
// first two frames and the last frame are outside the interaction record
// and should be discarded. The remaining frames are 11 to 29 which result
- // in 9 frame times of 2.
- const hist = histograms.getHistogramNamed('frame_times');
- assert.closeTo(2, hist.min, 1e-6);
- assert.closeTo(2, hist.max, 2e-6);
- assert.closeTo(2, hist.average, 1e-6);
+ // in 9 frames which have 1 task each.
+ const hist = histograms.getHistogramNamed('tasks_per_frame_total_all');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(1, hist.max, 1e-6);
+ assert.closeTo(1, hist.average, 1e-6);
});
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html
index b40db0341b4..30f9dbe2cee 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html
@@ -33,7 +33,7 @@ tr.b.unittest.testSuite(function() {
// Add layout categories
mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
cat: 'blink',
- title: 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser',
+ title: 'HTMLDocumentParser::DeferredPumpTokenizerIfPossible',
start: 200,
duration: 200,
cpuStart: 1160,
@@ -102,7 +102,7 @@ tr.b.unittest.testSuite(function() {
assert.deepEqual({
total: 150,
events: {
- 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser': 150
+ 'HTMLDocumentParser::DeferredPumpTokenizerIfPossible': 150
}
}, breakdownTree.parseHTML);
assert.deepEqual({
@@ -147,7 +147,7 @@ tr.b.unittest.testSuite(function() {
assert.deepEqual({
total: 100,
events: {
- 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser': 100
+ 'HTMLDocumentParser::DeferredPumpTokenizerIfPossible': 100
}
}, breakdownTree.parseHTML);
assert.deepEqual({
@@ -181,7 +181,7 @@ tr.b.unittest.testSuite(function() {
assert.deepEqual({
total: 120,
events: {
- 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser': 120
+ 'HTMLDocumentParser::DeferredPumpTokenizerIfPossible': 120
}
}, breakdownTree.parseHTML);
assert.deepEqual({
@@ -226,7 +226,7 @@ tr.b.unittest.testSuite(function() {
assert.deepEqual({
total: 80,
events: {
- 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser': 80
+ 'HTMLDocumentParser::DeferredPumpTokenizerIfPossible': 80
}
}, breakdownTree.parseHTML);
assert.deepEqual({
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html
index f8a63e84ba7..2d22034dbad 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html
@@ -8,6 +8,7 @@ found in the LICENSE file.
<link rel="import" href="/tracing/metrics/metric_registry.html">
<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
<link rel="import" href="/tracing/model/helpers/chrome_renderer_helper.html">
+<link rel="import" href="/tracing/value/diagnostics/alert_groups.html">
<link rel="import" href="/tracing/value/histogram.html">
<script>
@@ -78,6 +79,7 @@ tr.exportTo('tr.metrics.sh', function() {
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,
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html
index d6884fa43c4..2c5ab4b2d03 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html
@@ -18,6 +18,7 @@ found in the LICENSE file.
<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
<link rel="import" href="/tracing/model/helpers/chrome_thread_helper.html">
<link rel="import" href="/tracing/model/timed_event.html">
+<link rel="import" href="/tracing/value/diagnostics/alert_groups.html">
<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
<link rel="import" href="/tracing/value/histogram.html">
@@ -186,7 +187,14 @@ tr.exportTo('tr.metrics.sh', function() {
const frameIdRef = targetEvent.args.frame;
const snapshot = findFrameLoaderSnapshotAt(
rendererHelper, frameIdRef, targetEvent.start);
- if (snapshot === undefined || !snapshot.args.isLoadingMainFrame) continue;
+ if (snapshot === undefined) continue;
+ // If isOutermostMainFrame is available, use it, if not use
+ // isLoadingMainFrame.
+ const isOutermostMainFrame =
+ (snapshot.args.isOutermostMainFrame !== undefined) ?
+ snapshot.args.isOutermostMainFrame :
+ snapshot.args.isLoadingMainFrame;
+ if (!isOutermostMainFrame) continue;
const url = snapshot.args.documentLoaderURL;
if (tr.e.chrome.CHROME_INTERNAL_URLS.includes(url)) continue;
let navigationStartEvent;
@@ -264,7 +272,7 @@ tr.exportTo('tr.metrics.sh', function() {
return samples;
}
- function findLayoutShiftSamples(rendererHelper) {
+ function findMainFrameLayoutShiftSamples(rendererHelper) {
let sample;
EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,
'LayoutShift', 'loading').forEach((events) => {
@@ -274,7 +282,34 @@ tr.exportTo('tr.metrics.sh', function() {
sample = {value: evData.cumulative_score};
}
});
- return sample ? [sample] : [];
+ // When there is no layout shift event on found on the page, CLS is 0.
+ return sample ? [sample] : [{value: 0}];
+ }
+
+ function findAllLayoutShiftSamples(chromeHelper) {
+ let total = 0;
+ let foundMainFrame = false;
+ for (const pid in chromeHelper.rendererHelpers) {
+ const rendererHelper = chromeHelper.rendererHelpers[pid];
+ if (rendererHelper.isChromeTracingUI) continue;
+
+ tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(
+ rendererHelper, 'LayoutShift', 'loading').forEach((events) => {
+ // Add up the scores for main frames and weighted scores for subframes.
+ for (const event of events) {
+ const evData = event.args.data;
+ if (evData.is_main_frame) {
+ total += evData.score;
+ foundMainFrame = true;
+ } else {
+ total += evData.weighted_score_delta;
+ }
+ }
+ });
+ }
+
+ // If no CLS is found, report value as 0 instead of null.
+ return foundMainFrame ? [{value: total}] : [{value: 0}];
}
function addFirstMeaningfulPaintSample(samples, rendererHelper,
@@ -487,7 +522,8 @@ tr.exportTo('tr.metrics.sh', function() {
const largestTextPaintSamples = findLargestTextPaintSamples(
rendererHelper, frameToNavStartEvents,
navIdToNavStartEvents);
- const layoutShiftSamples = findLayoutShiftSamples(rendererHelper);
+ const mainFrameLayoutShiftSamples = findMainFrameLayoutShiftSamples(
+ rendererHelper);
const navigationStartSamples = timeToFCPEntries.map(entry => {
return { value: entry.navigationStartEvent.start};
});
@@ -502,7 +538,7 @@ tr.exportTo('tr.metrics.sh', function() {
firstViewportReadySamples,
largestImagePaintSamples,
largestTextPaintSamples,
- layoutShiftSamples,
+ mainFrameLayoutShiftSamples,
navigationStartSamples,
};
}
@@ -568,40 +604,6 @@ tr.exportTo('tr.metrics.sh', function() {
function addSamplesToHistogram(samples, histogram, histograms) {
for (const sample of samples) {
histogram.addSample(sample.value, sample.diagnostics);
-
- // Only add breakdown histograms for FCP.
- // http://crbug.com/771610
- 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)),
- });
- }
}
}
@@ -611,18 +613,21 @@ tr.exportTo('tr.metrics.sh', function() {
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, [], {
@@ -636,30 +641,36 @@ tr.exportTo('tr.metrics.sh', function() {
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, [], {
@@ -690,12 +701,21 @@ tr.exportTo('tr.metrics.sh', function() {
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(
+ const mainFrameLayoutShiftHistogram = 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 allLayoutShiftHistogram = histograms.createHistogram(
+ 'overallCumulativeLayoutShift', unitlessNumber_smallerIsBetter, [], {
+ binBoundaries: LAYOUT_SHIFT_SCORE_BOUNDARIES,
+ description: 'Document Cumulative Layout Shift Score with iframes',
+ summaryOptions: SUMMARY_OPTIONS,
+ alertGrouping: [tr.v.d.ALERT_GROUPS.LOADING_LAYOUT],
});
const navigationStartHistogram = histograms.createHistogram(
'navigationStart', timeDurationInMs_smallerIsBetter, [], {
@@ -707,6 +727,20 @@ tr.exportTo('tr.metrics.sh', function() {
const chromeHelper = model.getOrCreateHelper(
tr.model.helpers.ChromeModelHelper);
+
+ // Layout Shift and LCP are reported in the browser process, so we do not
+ // need to loop over the renderers to add samples.
+ const allLayoutShiftSamples = findAllLayoutShiftSamples(chromeHelper);
+ addSamplesToHistogram(
+ allLayoutShiftSamples,
+ allLayoutShiftHistogram,
+ histograms);
+
+ const lcpSamples = findLargestContentfulPaintHistogramSamples(
+ chromeHelper.browserHelper.mainThread.sliceGroup.slices);
+ addSamplesToHistogram(
+ lcpSamples, largestContentfulPaintHistogram, histograms);
+
for (const pid in chromeHelper.rendererHelpers) {
const rendererHelper = chromeHelper.rendererHelpers[pid];
if (rendererHelper.isChromeTracingUI) continue;
@@ -714,11 +748,6 @@ tr.exportTo('tr.metrics.sh', function() {
const samplesSet =
collectLoadingMetricsForRenderer(rendererHelper);
- const lcpSamples = findLargestContentfulPaintHistogramSamples(
- chromeHelper.browserHelper.mainThread.sliceGroup.slices);
- addSamplesToHistogram(
- lcpSamples, largestContentfulPaintHistogram, histograms);
-
addSamplesToHistogram(
samplesSet.firstPaintSamples, firstPaintHistogram, histograms);
addSamplesToHistogram(
@@ -748,7 +777,9 @@ tr.exportTo('tr.metrics.sh', function() {
largestTextPaintHistogram,
histograms);
addSamplesToHistogram(
- samplesSet.layoutShiftSamples, layoutShiftHistogram, histograms);
+ samplesSet.mainFrameLayoutShiftSamples,
+ mainFrameLayoutShiftHistogram,
+ histograms);
addSamplesToHistogram(
samplesSet.navigationStartSamples,
navigationStartHistogram,
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html
index f27187f5cb0..8d7f4eb53ef 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html
@@ -30,6 +30,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -63,6 +64,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -88,15 +90,6 @@ tr.b.unittest.testSuite(function() {
const hist = histograms.getHistogramNamed('timeToFirstContentfulPaint');
assert.strictEqual(1, hist.running.count);
assert.strictEqual(800, hist.running.mean);
- const fcpResourceLoading = histograms.getHistogramNamed(
- 'timeToFirstContentfulPaint:resource_loading');
- assert.strictEqual(
- hist.diagnostics.get('breakdown').get(
- 'resource_loading'),
- 'timeToFirstContentfulPaint:resource_loading');
- assert.strictEqual(fcpResourceLoading.sum, 100);
- assert.strictEqual(tr.b.getOnlyElement(hist.getBinForValue(
- 800).diagnosticMaps).get('breakdown').get('resource_loading'), 100);
});
test('timeToLargestImagePaint', function() {
@@ -112,6 +105,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -147,6 +141,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -190,6 +185,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -232,6 +228,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -275,6 +272,45 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(100, hist.running.mean);
});
+ test('timeToLargestContentfulPaint_NoMultipleReporting', function() {
+ // Test that we do not report the same sample value multiple times if there
+ // is more than one renderer.
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const browerMain = model.browserMain;
+ browerMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: tr.e.chrome.LCP_CANDIDATE_EVENT_TITLE,
+ start: 400,
+ duration: 0.0,
+ args: {
+ data: { durationInMilliseconds: 100, type: 'text', size: 1000,
+ inMainFrame: true },
+ main_frame_tree_node_id: 12345,
+ }
+ }));
+
+ const rendererProcess1 = model.rendererProcess;
+ const mainThread1 = model.rendererMain;
+ addNavigationStart_(mainThread1, 50,
+ { isOutermostMainFrame: true, isLoadingMainFrame: true,
+ documentLoaderURL: 'http://example.com'});
+
+ const rendererProcess2 = model.getOrCreateProcess(10);
+ const mainThread2 = rendererProcess2.getOrCreateThread(10);
+ mainThread2.name = 'CrRendererMain';
+
+ addNavigationStart_(mainThread2, 100,
+ { isOutermostMainFrame: true, isLoadingMainFrame: true,
+ documentLoaderURL: 'http://example.com'});
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('largestContentfulPaint');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(100, hist.running.mean);
+ });
+
test('timeToLargestContentfulPaint_LastCandidate', function() {
const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
const browerMain = model.browserMain;
@@ -452,6 +488,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -504,6 +541,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: 'firstframeid'},
documentLoaderURL: 'http://example.com'
@@ -526,6 +564,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 2300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: 'secondframeid'},
documentLoaderURL: 'http://example.com'
@@ -636,6 +675,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -664,6 +704,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 2100,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -696,6 +737,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -745,6 +787,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -770,15 +813,6 @@ tr.b.unittest.testSuite(function() {
const hist = histograms.getHistogramNamed('timeToFirstContentfulPaint');
assert.strictEqual(1, hist.running.count);
assert.strictEqual(800, hist.running.mean);
- const fcpResourceLoading = histograms.getHistogramNamed(
- 'timeToFirstContentfulPaint:resource_loading');
- assert.strictEqual(
- hist.diagnostics.get('breakdown').get(
- 'resource_loading'),
- 'timeToFirstContentfulPaint:resource_loading');
- assert.strictEqual(fcpResourceLoading.sum, 100);
- assert.strictEqual(tr.b.getOnlyElement(hist.getBinForValue(
- 800).diagnosticMaps).get('breakdown').get('resource_loading'), 100);
});
test('timeToFirstMeaningfulPaint', function() {
@@ -794,6 +828,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -842,6 +877,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -904,6 +940,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -973,6 +1010,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess1.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -1009,6 +1047,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess2.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -1046,6 +1085,7 @@ tr.b.unittest.testSuite(function() {
function addFrameLoaderObject_(rendererProcess, timestamp) {
rendererProcess.objects.addSnapshot(
'ptr', 'loading', 'FrameLoader', timestamp, {
+ isOutermostMainFrame: true,
isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com',
});
@@ -1119,13 +1159,15 @@ tr.b.unittest.testSuite(function() {
const mainThread = model.rendererMain;
addNavigationStart_(mainThread, 200,
- {isLoadingMainFrame: true, documentLoaderURL: 'http://example.com'});
+ { isOutermostMainFrame: true, isLoadingMainFrame: true,
+ documentLoaderURL: 'http://example.com'});
addNetworkRequest_(mainThread, 200, 250);
// FrameLoader creation time after navigation start.
rendererProcess.objects.idWasCreated(
'ptr', 'loading', 'FrameLoader', 250);
rendererProcess.objects.addSnapshot(
'ptr', 'loading', 'FrameLoader', 300, {
+ isOutermostMainFrame: true,
isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com',
});
@@ -1136,7 +1178,8 @@ tr.b.unittest.testSuite(function() {
// New navigation to close the search window.
addNavigationStart_(mainThread, 7000,
- {isLoadingMainFrame: true, documentLoaderURL: 'http://example.com'});
+ { isOutermostMainFrame: true, isLoadingMainFrame: true,
+ documentLoaderURL: 'http://example.com'});
});
const histograms = new tr.v.HistogramSet();
@@ -1401,6 +1444,7 @@ tr.b.unittest.testSuite(function() {
// DomContentLoadedEnd and NavigationStart for a different frame.
rendererProcess.objects.addSnapshot(
'ptr', 'loading', 'FrameLoader', 4000, {
+ isOutermostMainFrame: true,
isLoadingMainFrame: true, frame: {id_ref: '0xffffffff'},
documentLoaderURL: 'http://example.com'
});
@@ -1474,6 +1518,7 @@ tr.b.unittest.testSuite(function() {
}));
process.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -1600,6 +1645,32 @@ tr.b.unittest.testSuite(function() {
partialNetworkEvents);
});
+ test('noLayoutShiftEventMeansZeroCLS', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 10,
+ duration: 510,
+ args: {frame: '0xdeadbeef'}
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const mainHist =
+ histograms.getHistogramNamed('mainFrameCumulativeLayoutShift');
+ assert.strictEqual(1, mainHist.sampleValues.length);
+ assert.strictEqual(1, mainHist.running.count);
+ assert.strictEqual(0, mainHist.running.mean);
+ const overallHist =
+ histograms.getHistogramNamed('overallCumulativeLayoutShift');
+ assert.strictEqual(1, overallHist.sampleValues.length);
+ assert.strictEqual(1, overallHist.running.count);
+ assert.strictEqual(0, overallHist.running.mean);
+ });
+
test('mainFrameCumulativeLayoutShift', function() {
const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
const rendererProcess = model.rendererProcess;
@@ -1632,6 +1703,44 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(3.5, hist.running.mean);
});
+ test('overallCumulativeLayoutShift', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ const mainFrame = {id: '0xdeadbeef', is_main: true};
+ const subframe = {id: '0xdeadb33f', is_main: false};
+ const emitEvent = (thread, time, score, weightedScore, frame) => {
+ const data = {
+ is_main_frame: frame.is_main,
+ score,
+ weighted_score_delta: weightedScore
+ };
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'LayoutShift',
+ start: time,
+ duration: 0.0,
+ args: {frame: frame.id, data}
+ }));
+ };
+ emitEvent(mainThread, 1000, 1.5, 1000, mainFrame);
+ emitEvent(mainThread, 3000, 3.5, 1000, mainFrame);
+ emitEvent(mainThread, 2000, 3.0, 1000, mainFrame);
+ emitEvent(mainThread, 4000, 4000, 4.0, subframe);
+ const rendererProcess2 = model.getOrCreateProcess(10);
+ const mainThread2 = rendererProcess2.getOrCreateThread(20);
+ mainThread2.name = 'CrRendererMain';
+ const subframe2 = { id: '0xdeadb33f', is_main: false };
+ emitEvent(mainThread2, 2500, 1000, 2.0, subframe2);
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('overallCumulativeLayoutShift');
+ assert.strictEqual(1, hist.sampleValues.length);
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(14, hist.running.mean);
+ });
+
test('speedIndexIsAddedToHistograms', function() {
// The speed index code is fully tested in
// rects_based_speed_index_metric_test.
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html
index fea57533ba6..188000809ea 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html
@@ -390,6 +390,28 @@ tr.exportTo('tr.metrics.sh', function() {
}
};
+ const MAX_ALLOCATED_SIZE = {
+ name: 'max_allocated_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyName: 'max size of all allocations',
+ componentPreposition: 'of'
+ });
+ }
+ };
+
+ const MAX_COMMITTED_SIZE = {
+ name: 'max_committed_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyName: 'max size of all committed memory',
+ componentPreposition: 'of'
+ });
+ }
+ };
+
const SHIM_ALLOCATED_OBJECTS_SIZE = {
name: 'shim_allocated_objects_size',
unit: sizeInBytes_smallerIsBetter,
@@ -451,6 +473,8 @@ tr.exportTo('tr.metrics.sh', function() {
EFFECTIVE_SIZE,
ALLOCATED_OBJECTS_SIZE,
SHIM_ALLOCATED_OBJECTS_SIZE,
+ MAX_ALLOCATED_SIZE,
+ MAX_COMMITTED_SIZE,
LOCKED_SIZE,
PEAK_SIZE
];
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html
index e3a6c40d327..6cac038fad7 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html
@@ -397,6 +397,8 @@ tr.b.unittest.testSuite(function() {
size: 8,
allocated_objects_size: 4,
shim_allocated_objects_size: 3,
+ max_allocated_size: 5,
+ max_committed_size: 8
}})
];
pmdBrowser1.totals = {
@@ -565,7 +567,9 @@ tr.b.unittest.testSuite(function() {
newAllocatorDump(pmdBrowser3, 'malloc', {numerics: {
size: 8000,
allocated_objects_size: 4000,
- shim_allocated_objects_size: 3000
+ shim_allocated_objects_size: 3000,
+ max_allocated_size: 4000,
+ max_committed_size: 8000
}})
];
const pmdRendererB3 = addProcessMemoryDump(gmd3, pRendererB, {ts: 61});
@@ -656,6 +660,18 @@ tr.b.unittest.testSuite(function() {
description: 'total size of all allocated objects reported by Chrome ' +
'for all processes in Chrome'
},
+ 'memory:chrome:all_processes:reported_by_chrome:max_allocated_size': {
+ value: [5, 0, 4000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total max size of all allocations reported by Chrome ' +
+ 'for all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:max_committed_size': {
+ value: [8, 0, 8000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total max size of all committed memory reported by Chrome ' +
+ 'for all processes in Chrome'
+ },
'memory:chrome:all_processes:reported_by_chrome:blinkgc:BlinkObject:heap_category_size':
{
value: [0, 0, 1687992 + 1252376, 0],
@@ -765,6 +781,18 @@ tr.b.unittest.testSuite(function() {
description: 'size of all objects allocated through shim by malloc in ' +
'all processes in Chrome'
},
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:max_allocated_size': {
+ value: [5, 0, 4000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'max size of all allocations of malloc ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:max_committed_size': {
+ value: [8, 0, 8000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'max size of all committed memory of malloc ' +
+ 'in all processes in Chrome'
+ },
'memory:chrome:all_processes:reported_by_chrome:malloc:allocated_objects_size':
{
value: [4, 40 + 750, 4000, 0],
@@ -994,6 +1022,18 @@ tr.b.unittest.testSuite(function() {
description: 'total size of all allocated objects through shim ' +
'reported by Chrome for the browser process in Chrome'
},
+ 'memory:chrome:browser_process:reported_by_chrome:max_allocated_size': {
+ value: [5, 0, 4000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total max size of all allocations reported by Chrome ' +
+ 'for the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:max_committed_size': {
+ value: [8, 0, 8000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total max size of all committed memory reported by Chrome ' +
+ 'for the browser process in Chrome'
+ },
'memory:chrome:browser_process:reported_by_chrome:malloc:effective_size': {
value: [8, 120 - 40, 8000, 80000],
unit: sizeInBytes_smallerIsBetter,
@@ -1020,6 +1060,18 @@ tr.b.unittest.testSuite(function() {
description: 'size of all objects allocated through shim by malloc in ' +
'the browser process in Chrome'
},
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:max_allocated_size': {
+ value: [5, 0, 4000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'max size of all allocations of malloc ' +
+ 'in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:max_committed_size': {
+ value: [8, 0, 8000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'max size of all committed memory of malloc ' +
+ 'in the browser process in Chrome'
+ },
'memory:chrome:browser_process:reported_by_chrome:tracing:effective_size': {
value: [0, 40, 0, 0],
unit: sizeInBytes_smallerIsBetter,
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/persecond_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/persecond_metric_test.html
index f57d06da7dd..b34e7399322 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/persecond_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/persecond_metric_test.html
@@ -29,6 +29,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -112,6 +113,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -164,6 +166,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -188,6 +191,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr2', 'loading', 'FrameLoader',
1200, {
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xlivebeef'},
documentLoaderURL: 'http://example.com'
@@ -240,6 +244,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
@@ -295,6 +300,7 @@ tr.b.unittest.testSuite(function() {
}));
rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
{
+ isOutermostMainFrame: true,
isLoadingMainFrame: true,
frame: {id_ref: '0xdeadbeef'},
documentLoaderURL: 'http://example.com'
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/weblayer_startup_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/weblayer_startup_metric.html
new file mode 100644
index 00000000000..914f4cef743
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/weblayer_startup_metric.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'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';
+
+ // TODO(alexandermont): Only iterate over the processes and threads that
+ // could contain these events.
+ for (const slice of model.getDescendantEvents()) {
+ if (!(slice instanceof tr.model.ThreadSlice)) continue;
+
+ // WebLayerStartupInterval is the title of the section of code that is
+ // entered (via android.os.Trace.beginSection) when WebLayer is started
+ // up. This value is defined in TelemetryActivity.java.
+ if (slice.title === 'WebLayerStartupInterval') {
+ startupWallHist.addSample(slice.duration);
+ }
+
+ // WebLayerBlankUrlLoadInterval is the title of the section of code
+ // that is entered (via android.os.Trace.beginSection) when WebLayer
+ // is started up. This value is defined in TelemetryActivity.java.
+ if (slice.title === 'WebLayerBlankUrlLoadInterval') {
+ loadWallHist.addSample(slice.duration);
+ }
+ }
+
+ histograms.addHistogram(startupWallHist);
+ histograms.addHistogram(loadWallHist);
+ }
+
+ tr.metrics.MetricRegistry.register(weblayerStartupMetric);
+
+ return {
+ weblayerStartupMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/weblayer_startup_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/weblayer_startup_metric_test.html
new file mode 100644
index 00000000000..acc5a8dc1c1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/weblayer_startup_metric_test.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/system_health/weblayer_startup_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ function makeTestModel() {
+ return tr.c.TestUtils.newModel(function(model) {
+ const mainThread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'weblayer',
+ title: 'WebLayerStartupInterval',
+ start: 200,
+ duration: 42.0,
+ cpuStart: 150,
+ cpuDuration: 32.0
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'weblayer',
+ title: 'WebLayerBlankUrlLoadInterval',
+ start: 250,
+ duration: 27.0,
+ cpuStart: 190,
+ cpuDuration: 17.0
+ }));
+ });
+ }
+
+ test('weblayerStartupMetric', function() {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.weblayerStartupMetric(histograms, makeTestModel());
+ assert.closeTo(42, histograms.getHistogramNamed(
+ 'weblayer_startup_wall_time').average, 1e-2);
+ assert.closeTo(27, histograms.getHistogramNamed(
+ 'weblayer_url_load_wall_time').average, 1e-2);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/uma_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/uma_metric.html
index 8f741b9cf7f..959006e9749 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/uma_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/uma_metric.html
@@ -20,15 +20,12 @@ found in the LICENSE file.
*
* UMA histograms are logged in trace events titled 'UMAHistogramSamples'. The
* event arguments contain the histogram name and the base-64 coded of an
- * snapshot of histogram samples serialized in a pickle.
+ * snapshot of histogram samples serialized in a pickle. These are emitted at
+ * the end of tracing, and represent the difference in the UMA histograms from
+ * when the tracing began.
*
* If there are several processes that have snapshots of the same histogram,
* the snapshots will be merged.
- *
- * If there are two snapshots of the same histogram in the same process, we
- * assume that the first snapshot is taken when tracing started and the second
- * snapshot is taken when tracing is stopped. So, we compute the difference to
- * show the samples added during the tracing session.
*/
tr.exportTo('tr.metrics', function() {
function parseBuckets_(event, processName) {
@@ -78,36 +75,16 @@ tr.exportTo('tr.metrics', function() {
}
}
- 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) {
// Customize histogram units here.
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) {
// Customize histogram boundaries here. Ideally, this would not be
// necessary.
@@ -150,13 +127,10 @@ tr.exportTo('tr.metrics', function() {
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);
+ mergeBins_(values, endValues, name);
} else {
- throw new Error('There should be at most two snapshots of an UMA ' +
- 'histogram in each process');
+ throw new Error('There should be at most one snapshot of UMA ' +
+ `histogram for ${name} in each process.`);
}
}
}
@@ -164,6 +138,7 @@ tr.exportTo('tr.metrics', function() {
for (const [name, values] of histogramValues) {
const histogram = new tr.v.Histogram(
name, getHistogramUnit_(name), getHistogramBoundaries_(name));
+ const isLinear = getIsHistogramBinsLinear_(name);
// If we just put samples at the middle of the bins, their sum may not
// match the sum we read from traces. Compute how much samples should be
// shifted so that their sum matches what we expect.
@@ -173,16 +148,45 @@ tr.exportTo('tr.metrics', function() {
sumOfMiddles += bin.count * (bin.min + bin.max) / 2;
sumOfBinLengths += bin.count * (bin.max - bin.min);
}
+
+ if (name.startsWith('CompositorLatency.Type')) {
+ let histogramBoundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 101);
+ let histogramUnit = getHistogramUnit_(name);
+ let presentedCount = values.bins[0] ? values.bins[0].count : 0;
+ let delayedCount = values.bins[1] ? values.bins[1].count : 0;
+ let droppedCount = values.bins[2] ? values.bins[2].count : 0;
+ let inTimeCount = presentedCount - delayedCount;
+ let totalCount = presentedCount + droppedCount;
+
+ const inTimeHistogram = new tr.v.Histogram(
+ name+'.Percentage_of_in_time_frames', histogramUnit, histogramBoundaries);
+ inTimeHistogram.addSample(100.0 * inTimeCount / totalCount);
+ histograms.addHistogram(inTimeHistogram);
+
+ const delayedHistogram = new tr.v.Histogram(
+ name+'.Percentage_of_delayed_frames', histogramUnit, histogramBoundaries);
+ delayedHistogram.addSample(100.0 * delayedCount / totalCount);
+ histograms.addHistogram(delayedHistogram);
+
+ const droppedHistogram = new tr.v.Histogram(
+ name+'.Percentage_of_dropped_frames', histogramUnit, histogramBoundaries);
+ droppedHistogram.addSample(100.0 * droppedCount / totalCount);
+ histograms.addHistogram(droppedHistogram);
+ }
+
const shift = (values.sum - sumOfMiddles) / sumOfBinLengths;
- // Note: if shift is less than -0.5, it means that even if we put all
- // samples at the lowest value of their bins their sum will be less than
- // the sum we read from traces. So, there is an inconsistency: either the
- // bins are reported incorrectly, or the sum is reported incorrectly.
+ // Note: for linear bins, if shift is less than -0.5, it means that even
+ // if we put all samples at the lowest value of their bins their sum will
+ // be less than the sum we read from traces. So, there is an
+ // inconsistency: either the bins are reported incorrectly, or the sum is
+ // reported incorrectly.
//
// Similarly, if shift is greater than 0.5, the sum of samples cannot add
// up to the sum we read from traces, even if we put all samples at the
// highest value of their bins.
- if (Math.abs(shift) > 0.5) throw new Error('Samples sum is wrong');
+ 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;
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/uma_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/uma_metric_test.html
index ae512c6b4ef..e11aca5c4f8 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/uma_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/uma_metric_test.html
@@ -15,13 +15,11 @@ found in the LICENSE file.
tr.b.unittest.testSuite(function() {
// 1 sample in [1, 3) and 2 samples in [3, 7).
- const BROWSER_BUCKETS1 =
+ const BROWSER_BUCKETS =
'LAAAAAwAAAAAAAAAAwAAAAEAAAADAAAAAAAAAAEAAAADAAAABwAAAAAAAAACAAAA';
// 1 sample in [3, 7).
- const BROWSER_BUCKETS2 = 'HAAAAAUAAAAAAAAAAQAAAAMAAAAHAAAAAAAAAAEAAAA=';
- // 2 samples in [7, 9).
const RENDERER_BUCKETS = 'HAAAABAAAAAAAAAAAgAAAAcAAAAJAAAAAAAAAAIAAAA=';
- // 1 sample in [8, 10).
+ // 2 samples in [8, 10).
const RENDERER_INCOMPATIBLE_BUCKETS =
'HAAAAAkAAAAAAAAAAQAAAAgAAAAKAAAAAAAAAAEAAAA=';
// 1 sample in [1, 3) and 2 samples in [3, 7). The sum is 9.
@@ -38,7 +36,7 @@ tr.b.unittest.testSuite(function() {
title: 'UMAHistogramSamples', start: 2,
args: {
name: 'metric1',
- buckets: BROWSER_BUCKETS1}}));
+ buckets: BROWSER_BUCKETS}}));
});
const histograms = new tr.v.HistogramSet();
tr.metrics.umaMetric(histograms, model);
@@ -57,47 +55,15 @@ tr.b.unittest.testSuite(function() {
assert.closeTo(2, processes.get('browser_process_1'), 1e-6);
});
- test('twoUMASnapshots', function() {
- const model = tr.c.TestUtils.newModel((model) => {
- const browserProcess = model.getOrCreateProcess(0);
- browserProcess.getOrCreateThread(0).name = 'CrBrowserMain';
- browserProcess.instantEvents.push(tr.c.TestUtils.newInstantEvent({
- title: 'UMAHistogramSamples', start: 1,
- args: {
- name: 'metric1',
- buckets: BROWSER_BUCKETS2}}));
- browserProcess.instantEvents.push(tr.c.TestUtils.newInstantEvent({
- title: 'UMAHistogramSamples', start: 2,
- args: {
- name: 'metric1',
- buckets: BROWSER_BUCKETS1}}));
- });
- const histograms = new tr.v.HistogramSet();
- tr.metrics.umaMetric(histograms, model);
- const hist = histograms.getHistogramNamed('metric1');
-
- // (BROWSER_BUCKETS1 - BROWSER_BUCKETS2) looks like
- // * *
- // 1 2 3 4 5 6 7
- assert.closeTo(2, hist.min, 1e-6);
- assert.closeTo(5, hist.max, 1e-6);
- assert.closeTo(3.5, hist.average, 1e-6);
- });
-
test('twoUMASnapshotsInDifferentProcesses', function() {
const model = tr.c.TestUtils.newModel((model) => {
const browserProcess = model.getOrCreateProcess(0);
browserProcess.getOrCreateThread(0).name = 'CrBrowserMain';
browserProcess.instantEvents.push(tr.c.TestUtils.newInstantEvent({
- title: 'UMAHistogramSamples', start: 1,
- args: {
- name: 'metric1',
- buckets: BROWSER_BUCKETS2}}));
- browserProcess.instantEvents.push(tr.c.TestUtils.newInstantEvent({
title: 'UMAHistogramSamples', start: 2,
args: {
name: 'metric1',
- buckets: BROWSER_BUCKETS1}}));
+ buckets: BROWSER_BUCKETS}}));
const process = model.getOrCreateProcess(1);
process.instantEvents.push(tr.c.TestUtils.newInstantEvent({
title: 'UMAHistogramSamples', start: 2,
@@ -110,12 +76,12 @@ tr.b.unittest.testSuite(function() {
const hist = histograms.getHistogramNamed('metric1');
// The aggregated histogram looks like
- // *
+ // * *
// * * *
// 1 2 3 4 5 6 7 8 9
assert.closeTo(2, hist.min, 1e-6);
assert.closeTo(8, hist.max, 1e-6);
- assert.closeTo(5.75, hist.average, 1e-6);
+ assert.closeTo(5.6, hist.average, 1e-6);
const bin = hist.getBinForValue(8);
for (const diagnostics of bin.diagnosticMaps) {
@@ -188,27 +154,5 @@ tr.b.unittest.testSuite(function() {
tr.metrics.umaMetric(histograms, model);
}, 'Incompatible bins');
});
-
- test('badStartStopUMASnapshots', function() {
- const model = tr.c.TestUtils.newModel((model) => {
- const browserProcess = model.getOrCreateProcess(0);
- browserProcess.getOrCreateThread(0).name = 'CrBrowserMain';
- browserProcess.instantEvents.push(tr.c.TestUtils.newInstantEvent({
- title: 'UMAHistogramSamples', start: 1,
- args: {
- name: 'metric1',
- buckets: BROWSER_BUCKETS1}}));
- browserProcess.instantEvents.push(tr.c.TestUtils.newInstantEvent({
- title: 'UMAHistogramSamples', start: 2,
- args: {
- name: 'metric1',
- buckets: BROWSER_BUCKETS2}}));
- });
- const histograms = new tr.v.HistogramSet();
-
- assert.throws(function() {
- tr.metrics.umaMetric(histograms, model);
- }, 'Cannot subtract');
- });
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/OWNERS b/chromium/third_party/catapult/tracing/tracing/metrics/v8/OWNERS
index 3ecc1606516..1de8cc86062 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/v8/OWNERS
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/OWNERS
@@ -1,3 +1,2 @@
mlippautz@chromium.org
-mythria@chromium.org
-ulan@chromium.org
+omerkatz@chromium.org
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html
index 75cae51c2e1..5390adb2eb2 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html
@@ -22,6 +22,795 @@ 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;
+
+ /**
+ * A list of metrics that are measured and tracked.
+ *
+ * See https://bit.ly/v8-gc-stats-collection for the metric naming convention.
+ * You can add a variant of an existing metric by simply adding its name to
+ * this list. E.g. v8:gc:cycle:background_threads:full:atomic:mark:cpp.
+ *
+ * If you want to add a completely new metric with its own TRACE_EVENT then
+ * you also need to add the corresponding rule to the RULES list below.
+ *
+ * @const {!Array<string>}
+ */
+ 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:cycle:main_thread:full:atomic',
+ 'v8:gc:cycle:main_thread:full:atomic:cpp',
+ 'v8:gc:cycle:main_thread:full:atomic:mark',
+ 'v8:gc:cycle:main_thread:full:atomic:mark:cpp',
+ 'v8:gc:cycle:main_thread:full:atomic:weak',
+ 'v8:gc:cycle:main_thread:full:atomic:weak:cpp',
+ 'v8:gc:cycle:main_thread:full:atomic:sweep',
+ 'v8:gc:cycle:main_thread:full:atomic:sweep:cpp',
+ 'v8:gc:cycle:main_thread:full:atomic:compact',
+ 'v8:gc:cycle:main_thread:full:atomic:compact:cpp',
+ 'v8:gc:cycle:main_thread:full:incremental',
+ 'v8:gc:cycle:main_thread:full:incremental:cpp',
+ 'v8:gc:cycle:main_thread:full:incremental:mark',
+ 'v8:gc:cycle:main_thread:full:incremental:mark:cpp',
+ 'v8:gc:cycle:main_thread:full:incremental:sweep',
+ 'v8:gc:cycle:main_thread:full:incremental:sweep: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:young:mark',
+ 'v8:gc:cycle:young:weak',
+ 'v8:gc:cycle:young:sweep',
+ 'v8:gc:cycle:young:compact',
+ 'v8:gc:cycle:main_thread:young',
+ 'v8:gc:cycle:main_thread:young:mark',
+ 'v8:gc:cycle:main_thread:young:weak',
+ 'v8:gc:cycle:main_thread:young:sweep',
+ 'v8:gc:cycle:main_thread:young:compact',
+ 'v8:gc:cycle:main_thread:young:atomic',
+ 'v8:gc:cycle:main_thread:young:atomic:mark',
+ 'v8:gc:cycle:main_thread:young:atomic:weak',
+ 'v8:gc:cycle:main_thread:young:atomic:sweep',
+ 'v8:gc:cycle:main_thread:young:atomic:compact',
+ 'v8:gc:cycle:main_thread:young:incremental',
+ 'v8:gc:cycle:main_thread:young:incremental:mark',
+ 'v8:gc:cycle:main_thread:young:incremental:sweep',
+ 'v8:gc:event:main_thread:young:atomic',
+ 'v8:gc:event:main_thread:young:atomic:mark',
+ 'v8:gc:event:main_thread:young:atomic:weak',
+ 'v8:gc:event:main_thread:young:atomic:sweep',
+ 'v8:gc:event:main_thread:young:atomic:compact',
+ 'v8:gc:event:main_thread:young:incremental',
+ 'v8:gc:event:main_thread:young:incremental:mark',
+ 'v8:gc:event:main_thread:young:incremental:sweep',
+ ];
+
+ /**
+ * Shorthands for various event groups to be used in RULES below.
+ */
+ const V8_FULL_ATOMIC_EVENTS = [
+ 'V8.GC_MARK_COMPACTOR'
+ ];
+
+ const V8_FULL_MARK_EVENTS = [
+ 'V8.GC_MC_BACKGROUND_MARKING',
+ 'V8.GC_MC_MARK',
+ 'V8.GC_MC_INCREMENTAL',
+ 'V8.GC_MC_INCREMENTAL_START',
+ ];
+
+ 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',
+ 'V8.GC_MC_COMPLETE_SWEEPING',
+ ];
+
+ const V8_FULL_WEAK_EVENTS = [
+ 'V8.GC_MC_CLEAR',
+ ];
+
+ const V8_YOUNG_ATOMIC_EVENTS = [
+ 'V8.GC_SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL',
+ 'V8.GC_SCAVENGER',
+ 'V8.GC_MINOR_MARK_COMPACTOR',
+ ];
+
+ const V8_YOUNG_MARK_EVENTS = [
+ 'V8.GC_MINOR_MC_BACKGROUND_MARKING',
+ 'V8.GC_MINOR_MC_MARK',
+ 'V8.GC_MINOR_MC_INCREMENTAL',
+ 'V8.GC_MINOR_MC_INCREMENTAL_START',
+ ];
+
+ const V8_YOUNG_COMPACT_EVENTS = [
+ 'V8.GC_MINOR_MC_BACKGROUND_EVACUATE_COPY',
+ 'V8.GC_MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS',
+ 'V8.GC_MINOR_MC_EVACUATE',
+ ];
+
+ const V8_YOUNG_SWEEP_EVENTS = [
+ 'V8.GC_MINOR_MC_BACKGROUND_SWEEPING',
+ 'V8.GC_MINOR_MC_SWEEP',
+ ];
+
+ const V8_YOUNG_WEAK_EVENTS = [
+ 'V8.GC_MINOR_MC_CLEAR',
+ ];
+
+ 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',
+ ];
+
+ /**
+ * A Rule object describes a mapping from events to metrics.
+ *
+ * For each event in a single GC cycle there can be at most one rule that
+ * that applies to that event. An event E applies to a rule R if all the
+ * following conditions hold:
+ *
+ * 1. R.events contains E.title.
+ *
+ * 2. if R.inside is not empty, then at least one event X specified by
+ * R.inside exists on some thread and fully encloses E:
+ * X.start <= E.start && E.end <= X.end.
+ * Note that X and E don't have to be on the same thread, which allows
+ * us to find background thread events that happen during atomic pause.
+ *
+ * 3. if R.outside is not empty, then there is no such event X specified
+ * by R.outside that fully encloses E. This is useful for background
+ * events that happen during incremental phases.
+ *
+ * TODO(chromium:1056170): Currently event names of V8 and CppGC do not
+ * collide because V8 events are prefixed with 'V8' and CppGC events are
+ * prefixed with 'CppGC'. Revisit this it before switching to the library.
+ * We may need to either include the category to rules or keep the prefixes.
+ *
+ * @typedef {Object} Rule
+ * @property {!Array<string>} events - Event names selected by this rule.
+ * @property {?Array<string>} inside - Allowlist of enclosing event names.
+ * @property {?Array<string>} outside - Blocklist of enclosing event names.
+ * @property {string} contribute_to - The most specific target metric name.
+ * The rule automatically applies to all more general metrics that can
+ * be derived by dropping parts of the target metric name.
+ * Note that the metric name does not include granularity and threads.
+ */
+
+ /**
+ * @const {!Array<!Rule>}
+ */
+ 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,
+ outside: V8_FULL_COMPACT_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.concat(V8_FULL_COMPACT_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_ATOMIC_EVENTS,
+ contribute_to: 'young:atomic',
+ },
+ {
+ events: V8_YOUNG_MARK_EVENTS,
+ inside: V8_YOUNG_ATOMIC_EVENTS,
+ contribute_to: 'young:atomic:mark',
+ },
+ {
+ events: V8_YOUNG_MARK_EVENTS,
+ outside: V8_YOUNG_ATOMIC_EVENTS,
+ contribute_to: 'young:incremental:mark',
+ },
+ {
+ events: V8_YOUNG_COMPACT_EVENTS,
+ inside: V8_YOUNG_ATOMIC_EVENTS,
+ contribute_to: 'young:atomic:compact',
+ },
+ {
+ events: V8_YOUNG_SWEEP_EVENTS,
+ inside: V8_YOUNG_ATOMIC_EVENTS,
+ outside: V8_YOUNG_COMPACT_EVENTS,
+ contribute_to: 'young:atomic:sweep',
+ },
+ {
+ events: V8_YOUNG_WEAK_EVENTS,
+ inside: V8_YOUNG_ATOMIC_EVENTS,
+ contribute_to: 'young:atomic:weak',
+ },
+ {
+ events: V8_YOUNG_SWEEP_EVENTS,
+ outside: V8_YOUNG_ATOMIC_EVENTS.concat(V8_YOUNG_COMPACT_EVENTS),
+ contribute_to: 'young:incremental:sweep',
+ },
+ ];
+
+ /**
+ * A part of the metric name that defines how the events contributing to
+ * the metric are aggregated. See Metric.apply() below.
+ * @enum {string}
+ */
+ const Granularity = {
+ CYCLE: 'cycle',
+ EVENT: 'event',
+ };
+
+ /**
+ * A thread of a V8 isolate is considered a main thread including:
+ *
+ * - the main thread of the renderer.
+ * - the main thread of a dedicated worker.
+ * - the main thread of a service worker.
+ *
+ * A thread that runs background tasks is considered a background
+ * thread. See jsExecutionThreadsWithTypes() below.
+ *
+ * @enum {string}
+ */
+ const ThreadType = {
+ MAIN: 'main',
+ BACKGROUND: 'background',
+ ALL_THREADS: 'all_threads',
+ };
+
+ /**
+ * Represents a single metric together with its histogram of measurements.
+ */
+ class Metric {
+ /**
+ * @param{string} name The name of the metric.
+ * See https://bit.ly/v8-gc-stats-collection for the metric naming
+ * convention and the meanining of name parts.
+ */
+ constructor(name) {
+ const parts = name.split(':');
+
+ /** @private @const {Granularity} */
+ this.granularity_ = parts[2];
+ assert(this.granularity_ === Granularity.CYCLE ||
+ this.granularity_ === Granularity.EVENT);
+
+ /** @private @const {?ThreadType} */
+ 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;
+ }
+
+ /** @private @const {!Array<string>} */
+ this.phases_ = parts.slice(phasesIndex);
+
+ const maxValue = this.isPerCycleMetric() ? 10000 : 1000;
+ const boundaries =
+ tr.v.HistogramBinBoundaries.createExponential(0.1, maxValue, 100);
+
+ /** @package @const {!tr.v.Histogram} */
+ 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(),
+ });
+ }
+
+ /**
+ * @return {boolean} Whether the granularity of this metric is per cycle.
+ */
+ isPerCycleMetric() {
+ return this.granularity_ === Granularity.CYCLE;
+ }
+
+ /**
+ * @param {!Array<string>} phases - A list of metric phases.
+ * @return {boolean} Whether the phases of this metric are more general
+ * than (or equal to) the given phases.
+ */
+ isMoreGeneralThanOrEqualTo(phases) {
+ // Check that this.phases_ is a subset of phases.
+ const phasesSet = new Set(phases.split(':'));
+ return this.phases_.every(phase => phasesSet.has(phase));
+ }
+
+ /**
+ * @param {!Array<!Rule>} rules - Rules that map events to metrics.
+ * @param {!Array<!tr.model.Slice>} events - All events of a single GC cycle
+ * including the events of the main and background threads.
+ * @return {!Array<!tr.model.Slice>} A subset of the given events that
+ * contribute to this metric.
+ */
+ contributingEvents(rules, events) {
+ // A map from an event name to the events with that name.
+ // It is used to speed up enclosing checks below.
+ const eventsByName = groupBy(events, e => e.title);
+
+ // Checks if the given rule matches (or applies) to the given event.
+ function matches(rule, event) {
+ // Checks if there is an event with the given name that encloses
+ // |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;
+ }
+
+ // For each event find the applying rule and check if the rule also
+ // applies to this metric.
+ 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;
+ }
+
+ /**
+ * Finds all events that contribute to this metric and aggregates them
+ * in the metric's histogram.
+ *
+ * @param {!Array<!Rule>} rules - Rules that map events to metrics.
+ * @param {!Array<!tr.model.Slice>} events - All events of a single GC cycle
+ * including the events of the main and background threads.
+ * @param {!Map<number, ThreadType>} threadTypes - A map from a thread-id
+ * to a thread type.
+ */
+ apply(rules, events, threadTypes) {
+ // Find all events that are relevant for this metric.
+ const filtered = this.contributingEvents(rules, events);
+
+ // Group the events by thread.
+ const eventsByThread = groupBy(filtered, e => e.parentContainer.tid);
+
+ // Drop events nested in other events and also drop events from
+ // the irrelevant threads.
+ let flattened = [];
+ for (const [tid, threadEvents] of eventsByThread) {
+ if (this.thread_ === ThreadType.ALL_THREADS ||
+ this.thread_ === threadTypes.get(tid)) {
+ flattened = flattened.concat(flatten(threadEvents));
+ }
+ }
+
+ // Aggregate events in the histogram.
+ 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);
+ }
+ }
+ }
+ }
+
+ /**
+ * A helper for checking the condition.
+ * @param {boolean} condition
+ * @param {string} message
+ */
+ function assert(condition, message) {
+ if (!condition) {
+ throw new Error(message);
+ }
+ }
+
+ /**
+ * A helper for grouping objects by the custom key.
+ * @param {!Array<!Object>} objects
+ * @param {!function(!Object): !Object} keyCallback
+ * @param {!Map<!Object, !Array<!Object>>} Objects grouped by the key.
+ */
+ 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;
+ }
+
+ /**
+ * A helper for getting all events relevant for the rules.
+ * @param {!Array<Rule>} rules
+ * @return {!Array<string>} Event names.
+ */
+ 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;
+ }
+
+
+ /**
+ * Performs thread-independent check for event nesting.
+ *
+ * @param {!Array<!tr.model.Slice>} event1
+ * @param {!Array<!tr.model.Slice>} event2
+ * @return {boolean} Whether the first event encloses the second event.
+ */
+ function encloses(event1, event2) {
+ return (event1.start - EPSILON <= event2.start &&
+ event2.end <= event1.end + EPSILON);
+ }
+
+ /**
+ * Finds all threads that may execute JS code in the given renderer
+ * and return them together with the thread-id to thread type mapping.
+ *
+ * @param {!tr.model.helpers.ChromeRendererHelper} rendererHelper
+ * @return {[!Array<tr.model.Thread>, !Map<number, ThreadType>] A pair
+ * of a thread list and a thread type mapping.
+ */
+ 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];
+ }
+
+ /**
+ * Drops all events that are nested in other events.
+ *
+ * @param {!Array<!tr.model.Slice>} events - Events on the same thread.
+ * @return {!Array<!tr.model.Slice>} Top-level events.
+ */
+ 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;
+ }
+
+ /**
+ * Groups the events by GC cycle using the epoch argument of events.
+ *
+ * The function is more complex than expected for two reasons:
+ *
+ * 1. V8 and CppGC do not syncronize their epoch counters (yet).
+ * 2. V8 adds the epoch argument only to the top-level events. Nested
+ * events are not requred to have the epoch.
+ *
+ * The function first finds the mapping from CppGC epoch to V8 epoch assuming
+ * that there will always be a CppGC event nested in a V8 event.
+ * Then it finds the V8 epoch for each nested V8 event and CppGC event.
+ * Finally, it groups the events by their V8 epoch.
+ *
+ * @param {!Array<!tr.model.Slice>} events - Events from multiple GC cycles
+ * and multiple threads.
+ * @return {!Map<string, !Array<!tr.model.Slice>>} Grouped events.
+ */
+ function groupByEpoch(events) {
+ function isV8Event(event) {
+ // TODO(1056170): Adjust this if the CppGC library uses a v8 category
+ // for trace events.
+ return event.category && event.category.includes('v8');
+ }
+
+ // Finds the V8 and CppGC epoch arguments in the given event and its
+ // ancestors.
+ 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;
+ }
+
+ // The following two functions combine V8 and CppGC epoch into a single
+ // global epoch. We give V8 even global epochs and CppGC odd global epochs.
+ function GlobalEpochFromV8(v8Epoch) {
+ return 2 * v8Epoch;
+ }
+
+ function GlobalEpochFromCpp(cppEpoch) {
+ return 2 * cppEpoch + 1;
+ }
+
+ // Find the mapping from a CppGC epoch to a V8 epoch.
+ const cppToV8 = new Map();
+ for (const event of events) {
+ const epoch = getEpoch(event);
+ if (epoch.cpp !== null && epoch.v8 !== null) {
+ // The start of V8 incremental marking may finalize GppGC sweeping
+ // of the previous garbage collection cycle. Thus it may happen that
+ // the same CppGC epoch maps to two V8 epoch. In such a conflict
+ // the smaller V8 epoch wins, essentially mapping the event back to
+ // the previous V8 cycle.
+ if (!cppToV8.has(epoch.cpp) || cppToV8.get(epoch.cpp) > epoch.v8) {
+ cppToV8.set(epoch.cpp, epoch.v8);
+ }
+ }
+ }
+
+ // For each event infer its V8 epoch and group by that.
+ const result = new Map();
+ for (const event of events) {
+ const epoch = getEpoch(event);
+ if (epoch.cpp === null && epoch.v8 === null) {
+ continue;
+ }
+ let globalEpoch;
+ if (epoch.v8 !== null) {
+ // Case 1: either a V8 event or a CppGC event nested in a V8 event.
+ globalEpoch = GlobalEpochFromV8(epoch.v8);
+ } else if (cppToV8.has(epoch.cpp)) {
+ // Case 2: A CppGC event of a unified garbage collection.
+ globalEpoch = GlobalEpochFromV8(cppToV8.get(epoch.cpp));
+ } else {
+ // Case 3: An event from a standalone CppGC garbage collection.
+ globalEpoch = GlobalEpochFromCpp(epoch.cpp);
+ }
+ if (result.has(globalEpoch)) {
+ result.get(globalEpoch).push(event);
+ } else {
+ result.set(globalEpoch, [event]);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The main entry point of GC metric computation.
+ *
+ * @param {!Array<string} metricNames - A list of metric names to be computed.
+ * @param {!tr.v.HistogramSet} histograms - The histogram set where the new
+ * histograms will be added.
+ * @param {!tr.Model} model
+ */
+ function addGarbageCollectionMetrics(metricNames, histograms, model) {
+ // Parse the metric names and store them in a list.
+ const metrics = metricNames.map(name => new Metric(name));
+
+ // Compute the set of GC related event names.
+ const gcEventNames = new Set(eventsMentionedIn(RULES));
+
+ // Iterate all renderer processes.
+ 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);
+
+ // Get all GC related events.
+ const events = [];
+ for (const thread of threads) {
+ for (const event of thread.sliceGroup.childEvents()) {
+ if (gcEventNames.has(event.title)) {
+ events.push(event);
+ }
+ }
+ }
+
+ // Group events by GC cycle and consider each cycle separately.
+ for (const cycleEvents of groupByEpoch(events).values()) {
+ // If any event is in the cycle is forced, then the whole cycle
+ // is considered forced. Skip all events in the cycle.
+ if (cycleEvents.some(
+ tr.metrics.v8.utils.isForcedGarbageCollectionEvent)) {
+ continue;
+ }
+
+ for (const metric of metrics) {
+ metric.apply(RULES, cycleEvents, threadTypes);
+ }
+ }
+ }
+
+ // Add the new histograms to the resulting histogram set.
+ for (const metric of metrics) {
+ histograms.addHistogram(metric.histogram);
+ }
+ }
function gcMetric(histograms, model, options) {
options = options || {};
@@ -36,6 +825,7 @@ tr.exportTo('tr.metrics.v8', function() {
addTotalMarkCompactorTime(histograms, model);
addTotalMarkCompactorMarkingTime(histograms, model);
addScavengerSurvivedFromStackEvents(histograms, model);
+ addGarbageCollectionMetrics(METRICS, histograms, model);
}
tr.metrics.MetricRegistry.register(gcMetric);
@@ -380,6 +1170,7 @@ tr.exportTo('tr.metrics.v8', function() {
return {
gcMetric,
WINDOW_SIZE_MS, // For testing purposes only.
+ addGarbageCollectionMetrics, // For testing purposes only.
};
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html
index 4d0d3beca88..d542c1e25dd 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html
@@ -16,16 +16,21 @@ found in the LICENSE file.
'use strict';
tr.b.unittest.testSuite(function() {
- function createModel(start, end, slices) {
- return tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
- const rendererProcess = model.rendererProcess;
- const mainThread = model.rendererMain;
- const group = mainThread.sliceGroup;
+ function createModel(slices, backgroundSlices) {
+ function addSlices(thread, slices) {
+ const group = thread.sliceGroup;
for (const slice of slices) {
group.pushSlice(tr.c.TestUtils.newSliceEx(slice));
}
group.createSubSlices();
- mainThread.updateBounds();
+ thread.updateBounds();
+ }
+ return tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ addSlices(model.rendererMain, slices);
+ if (backgroundSlices) {
+ addSlices(model.foregroundWorker1, backgroundSlices);
+ }
});
}
@@ -35,21 +40,24 @@ tr.b.unittest.testSuite(function() {
function run(slices) {
const histograms = new tr.v.HistogramSet();
- const startTime = slices.reduce(
- (acc, slice) => (Math.min(acc, slice.start)));
- const endTime = slices.reduce((acc, slice) => (Math.max(acc, slice.end)));
- const model = createModel(startTime - 1, endTime + 1, slices);
+ const model = createModel(slices);
tr.metrics.v8.gcMetric(histograms, model, {include_sub_events: true});
return histograms;
}
+ function addGarbageCollectionMetrics(metrics, slices, backgroundSlices) {
+ const histograms = new tr.v.HistogramSet();
+ const model = createModel(slices, backgroundSlices);
+ tr.metrics.v8.addGarbageCollectionMetrics(metrics, histograms, model);
+ return histograms;
+ }
+
test('topEvents', function() {
const events = {
'V8.GCCompactor': 'v8-gc-full-mark-compactor',
'V8.GCFinalizeMC': 'v8-gc-latency-mark-compactor',
'V8.GCFinalizeMCReduceMemory': 'v8-gc-memory-mark-compactor',
'V8.GCIncrementalMarking': 'v8-gc-incremental-step',
- 'V8.GCIncrementalMarkingFinalize': 'v8-gc-incremental-finalize',
'V8.GCIncrementalMarkingStart': 'v8-gc-incremental-start',
'V8.GCPhantomHandleProcessingCallback': 'v8-gc-phantom-handle-callback',
'V8.GCScavenger': 'v8-gc-scavenger'
@@ -147,11 +155,6 @@ tr.b.unittest.testSuite(function() {
cpuStart: 150, cpuEnd: 160
},
{
- title: 'V8.GCIncrementalMarkingFinalize',
- args: {}, start: 200, end: 220,
- cpuStart: 200, cpuEnd: 220
- },
- {
title: 'V8.GCFinalizeMC',
args: {}, start: 250, end: 300,
cpuStart: 250, cpuEnd: 300
@@ -160,7 +163,7 @@ tr.b.unittest.testSuite(function() {
const histograms = run(slices);
const mmu = histograms.getHistogramNamed(
'v8-gc-mark-compactor-mmu-100ms_window');
- assert.closeTo(0.3, mmu.min, 1e-3);
+ assert.closeTo(0.5, mmu.min, 1e-3);
assert.strictEqual(mmu.summaryOptions.get('min'), true);
assert.strictEqual(mmu.summaryOptions.get('max'), false);
});
@@ -244,5 +247,685 @@ tr.b.unittest.testSuite(function() {
'v8-gc-scavenger-survived-percentage-from-stack');
assert.closeTo(0.375, percentageFromStack.average, 1e-3);
});
+
+ test('cycleAndEvent', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MC_INCREMENTAL',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 100, cpuStart: 100, end: 110, cpuEnd: 110,
+ },
+ {
+ title: 'V8.GC_MC_INCREMENTAL',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 200, cpuStart: 200, end: 220, cpuEnd: 220,
+ },
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 300, cpuStart: 300, end: 400, cpuEnd: 400,
+ },
+ {
+ title: 'V8.GC_MC_MARK',
+ cat: 'v8.gc',
+ start: 300, cpuStart: 300, end: 340, cpuEnd: 340,
+ },
+ ];
+ const backgroundSlices = [];
+ const expectedAverages = [
+ ['v8:gc:cycle:main_thread:full:atomic:mark', 40],
+ ['v8:gc:cycle:main_thread:full:incremental:mark', 10 + 20],
+ ['v8:gc:event:main_thread:full:atomic:mark', 40],
+ ['v8:gc:event:main_thread:full:incremental:mark', (10 + 20) / 2],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(
+ metrics, mainSlices, backgroundSlices);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('nested', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 100, cpuStart: 100, end: 900, cpuEnd: 900,
+ },
+ {
+ title: 'V8.GC_MC_MARK',
+ cat: 'v8.gc',
+ start: 100, cpuStart: 100, end: 300, cpuEnd: 300,
+ },
+ {
+ title: 'V8.GC_MC_MARK',
+ cat: 'v8.gc',
+ start: 110, cpuStart: 110, end: 120, cpuEnd: 120,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 110, cpuStart: 110, end: 111, cpuEnd: 111,
+ },
+ {
+ title: 'CppGC.AtomicMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 111, cpuStart: 111, end: 112, cpuEnd: 112,
+ },
+ {
+ title: 'V8.GC_MC_MARK',
+ cat: 'v8.gc',
+ start: 230, cpuStart: 230, end: 250, cpuEnd: 250,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 230, cpuStart: 230, end: 232, cpuEnd: 232,
+ },
+ {
+ title: 'CppGC.AtomicMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 232, cpuStart: 232, end: 234, cpuEnd: 234,
+ },
+ {
+ title: 'V8.GC_MC_MARK',
+ cat: 'v8.gc',
+ start: 400, cpuStart: 400, end: 500, cpuEnd: 500,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 400, cpuStart: 400, end: 403, cpuEnd: 403,
+ },
+ {
+ title: 'CppGC.AtomicMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 403, cpuStart: 403, end: 406, cpuEnd: 406,
+ },
+ ];
+ const backgroundSlices = [];
+ const expectedAverages = [
+ ['v8:gc:cycle:main_thread:full:atomic:mark', 200 + 100],
+ ['v8:gc:event:main_thread:full:atomic:mark', (200 + 100) / 2],
+ ['v8:gc:cycle:main_thread:full:atomic:mark:cpp', 1 + 2 + 3 + 1 + 2 + 3],
+ ['v8:gc:event:main_thread:full:atomic:mark:cpp',
+ (1 + 2 + 3 + 1 + 2 + 3) / 6],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(
+ metrics, mainSlices, backgroundSlices);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('phases', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 100, cpuStart: 100, end: 900, cpuEnd: 900,
+ },
+ {
+ title: 'V8.GC_MC_MARK',
+ cat: 'v8.gc',
+ start: 100, cpuStart: 100, end: 110, cpuEnd: 110,
+ },
+ {
+ title: 'V8.GC_MC_CLEAR',
+ cat: 'v8.gc',
+ start: 200, cpuStart: 200, end: 220, cpuEnd: 220,
+ },
+ {
+ title: 'V8.GC_MC_EVACUATE',
+ cat: 'v8.gc',
+ start: 300, cpuStart: 300, end: 330, cpuEnd: 330,
+ },
+ {
+ title: 'V8.GC_MC_SWEEP',
+ cat: 'v8.gc',
+ start: 400, cpuStart: 400, end: 440, cpuEnd: 440,
+ },
+ ];
+ const backgroundSlices = [];
+ const expectedAverages = [
+ ['v8:gc:cycle:main_thread:full:atomic:mark', 10],
+ ['v8:gc:cycle:main_thread:full:atomic:weak', 20],
+ ['v8:gc:cycle:main_thread:full:atomic:compact', 30],
+ ['v8:gc:cycle:main_thread:full:atomic:sweep', 40],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(
+ metrics, mainSlices, backgroundSlices);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('minorPhases', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MINOR_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 100, cpuStart: 100, end: 900, cpuEnd: 900,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_MARK',
+ cat: 'v8.gc',
+ start: 100, cpuStart: 100, end: 110, cpuEnd: 110,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_CLEAR',
+ cat: 'v8.gc',
+ start: 200, cpuStart: 200, end: 220, cpuEnd: 220,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_EVACUATE',
+ cat: 'v8.gc',
+ start: 300, cpuStart: 300, end: 330, cpuEnd: 330,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_SWEEP',
+ cat: 'v8.gc',
+ start: 400, cpuStart: 400, end: 440, cpuEnd: 440,
+ },
+ ];
+ const backgroundSlices = [];
+ const expectedAverages = [
+ ['v8:gc:cycle:main_thread:young:atomic:mark', 10],
+ ['v8:gc:cycle:main_thread:young:atomic:weak', 20],
+ ['v8:gc:cycle:main_thread:young:atomic:compact', 30],
+ ['v8:gc:cycle:main_thread:young:atomic:sweep', 40],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(
+ metrics, mainSlices, backgroundSlices);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('fullAndYoung', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 100, cpuStart: 100, end: 110, cpuEnd: 110,
+ },
+ {
+ title: 'V8.GC_SCAVENGER',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 200, cpuStart: 200, end: 220, cpuEnd: 220,
+ },
+ {
+ title: 'V8.GC_SCAVENGER',
+ cat: 'v8',
+ args: {'epoch': 2},
+ start: 300, cpuStart: 300, end: 330, cpuEnd: 330,
+ },
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 4},
+ start: 400, cpuStart: 400, end: 440, cpuEnd: 440,
+ },
+ {
+ title: 'V8.GC_MINOR_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 5},
+ start: 500, cpuStart: 500, end: 550, cpuEnd: 550,
+ },
+ ];
+ const backgroundSlices = [];
+ const expectedAverages = [
+ ['v8:gc:cycle:main_thread:full:atomic', (10 + 40) / 2],
+ ['v8:gc:cycle:main_thread:full', (10 + 40) / 2],
+ ['v8:gc:cycle:full', (10 + 40) / 2],
+ ['v8:gc:cycle:main_thread:young:atomic', (20 + 30 + 50) / 3],
+ ['v8:gc:cycle:main_thread:young', (20 + 30 + 50) / 3],
+ ['v8:gc:cycle:young', (20 + 30 + 50) / 3],
+ ['v8:gc:cycle:main_thread', (10 + 20 + 30 + 40 + 50) / 5],
+ ['v8:gc:cycle', (10 + 20 + 30 + 40 + 50) / 5],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(
+ metrics, mainSlices, backgroundSlices);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('cpp', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MC_INCREMENTAL',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 100, cpuStart: 100, end: 200, cpuEnd: 200,
+ },
+ {
+ title: 'BlinkGC.IncrementalMarkingStep',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 100, cpuStart: 100, end: 110, cpuEnd: 110,
+ },
+ {
+ title: 'CppGC.IncrementalMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 110, cpuStart: 110, end: 120, cpuEnd: 120,
+ },
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 200, cpuStart: 200, end: 300, cpuEnd: 300,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 200, cpuStart: 200, end: 220, cpuEnd: 220,
+ },
+ {
+ title: 'CppGC.AtomicMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 220, cpuStart: 220, end: 240, cpuEnd: 240,
+ },
+ ];
+ const backgroundSlices = [
+ {
+ title: 'BlinkGC.ConcurrentMarkingStep',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 100, cpuStart: 100, end: 130, cpuEnd: 130,
+ },
+ {
+ title: 'CppGC.ConcurrentMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 130, cpuStart: 130, end: 160, cpuEnd: 160,
+ },
+ {
+ title: 'BlinkGC.ConcurrentMarkingStep',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 200, cpuStart: 200, end: 240, cpuEnd: 240,
+ },
+ {
+ title: 'CppGC.ConcurrentMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 240, cpuStart: 240, end: 280, cpuEnd: 280,
+ },
+ ];
+ const expectedAverages = [
+ ['v8:gc:cycle:main_thread:full:atomic:mark:cpp', 20 + 20],
+ ['v8:gc:cycle:main_thread:full:incremental:mark:cpp', 10 + 10],
+ ['v8:gc:cycle:full:atomic:mark:cpp', 20 + 40 + 20 + 40],
+ ['v8:gc:cycle:full:incremental:mark:cpp', 10 + 30 + 10 + 30],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(
+ metrics, mainSlices, backgroundSlices);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('atomicAndIncremental', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MC_COMPLETE_SWEEPING',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 80, cpuStart: 80, end: 100, cpuEnd: 100,
+ },
+ {
+ title: 'V8.GC_MC_INCREMENTAL',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 100, cpuStart: 100, end: 110, cpuEnd: 110,
+ },
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 200, cpuStart: 200, end: 300, cpuEnd: 300,
+ },
+ {
+ title: 'V8.GC_MC_MARK',
+ cat: 'v8',
+ start: 200, cpuStart: 200, end: 220, cpuEnd: 220,
+ },
+ ];
+ const backgroundSlices = [
+ {
+ title: 'V8.GC_MC_BACKGROUND_MARKING',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 100, cpuStart: 100, end: 130, cpuEnd: 130,
+ },
+ {
+ title: 'V8.GC_MC_BACKGROUND_MARKING',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 200, cpuStart: 200, end: 240, cpuEnd: 240,
+ },
+ ];
+ const expectedAverages = [
+ ['v8:gc:cycle:main_thread:full:incremental:sweep', 20],
+ ['v8:gc:cycle:main_thread:full:atomic:mark', 20],
+ ['v8:gc:cycle:main_thread:full:incremental:mark', 10],
+ ['v8:gc:cycle:background_threads:full:atomic:mark', 40],
+ ['v8:gc:cycle:background_threads:full:incremental:mark', 30],
+ ['v8:gc:cycle:full:atomic:mark', 20 + 40],
+ ['v8:gc:cycle:full:incremental:mark', 10 + 30],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(
+ metrics, mainSlices, backgroundSlices);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('multipleCycles', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MC_INCREMENTAL',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 100, cpuStart: 100, end: 110, cpuEnd: 110,
+ },
+ {
+ title: 'BlinkGC.IncrementalMarkingStep',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 200, cpuStart: 200, end: 220, cpuEnd: 220,
+ },
+ {
+ title: 'CppGC.IncrementalMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 220, cpuStart: 220, end: 240, cpuEnd: 240,
+ },
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 300, cpuStart: 300, end: 400, cpuEnd: 400,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 300, cpuStart: 300, end: 330, cpuEnd: 330,
+ },
+ {
+ title: 'CppGC.AtomicMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 330, cpuStart: 330, end: 360, cpuEnd: 360,
+ },
+ {
+ title: 'V8.GC_MC_INCREMENTAL',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 600, cpuStart: 600, end: 640, cpuEnd: 640,
+ },
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 700, cpuStart: 700, end: 900, cpuEnd: 900,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 2},
+ start: 700, cpuStart: 700, end: 750, cpuEnd: 750,
+ },
+ {
+ title: 'CppGC.AtomicMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 2},
+ start: 750, cpuStart: 750, end: 800, cpuEnd: 800,
+ },
+ ];
+ const expectedAverages = [
+ ['v8:gc:cycle:full', ((10 + 20 + 20 + 100) + (40 + 200)) / 2],
+ ['v8:gc:cycle:full:cpp', ((20 + 30 + 20 + 30) + (50 + 50)) / 2],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(metrics, mainSlices, []);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('standaloneCppGC', function() {
+ const mainSlices = [
+ {
+ title: 'BlinkGC.IncrementalMarkingStep',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 200, cpuStart: 200, end: 220, cpuEnd: 220,
+ },
+ {
+ title: 'CppGC.IncrementalMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 220, cpuStart: 220, end: 240, cpuEnd: 240,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 300, cpuStart: 300, end: 330, cpuEnd: 330,
+ },
+ {
+ title: 'CppGC.AtomicMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 1},
+ start: 330, cpuStart: 330, end: 360, cpuEnd: 360,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 2},
+ start: 700, cpuStart: 700, end: 750, cpuEnd: 750,
+ },
+ {
+ title: 'CppGC.AtomicMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 2},
+ start: 750, cpuStart: 750, end: 800, cpuEnd: 800,
+ },
+ ];
+ const expectedAverages = [
+ ['v8:gc:cycle:full', ((20 + 30 + 20 + 30) + (50 + 50)) / 2],
+ ['v8:gc:cycle:full:cpp', ((20 + 30 + 20 + 30) + (50 + 50)) / 2],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(metrics, mainSlices, []);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('ambigousEpoch', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 300, cpuStart: 300, end: 400, cpuEnd: 400,
+ },
+ {
+ title: 'BlinkGC.AtomicPauseMarkTransitiveClosure',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 300, cpuStart: 300, end: 330, cpuEnd: 330,
+ },
+ {
+ title: 'V8.GC_MC_INCREMENTAL',
+ cat: 'v8',
+ args: {'epoch': 3},
+ start: 600, cpuStart: 600, end: 640, cpuEnd: 640,
+ },
+ {
+ title: 'BlinkGC.CompleteSweep',
+ cat: 'blink.gc',
+ args: {'epoch': 1},
+ start: 600, cpuStart: 600, end: 610, cpuEnd: 610,
+ },
+ {
+ title: 'CppGC.IncrementalMark',
+ cat: 'cpp.gc',
+ args: {'epoch': 2},
+ start: 610, cpuStart: 610, end: 640, cpuEnd: 640,
+ },
+ ];
+ const expectedAverages = [
+ ['v8:gc:cycle:full', ((100) + (40)) / 2],
+ ['v8:gc:cycle:full:cpp', ((30 + 10) + (30)) / 2],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(metrics, mainSlices, []);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
+
+ test('sweepingInEvacuation', function() {
+ const mainSlices = [
+ {
+ title: 'V8.GC_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 100, cpuStart: 100, end: 200, cpuEnd: 200,
+ },
+ {
+ title: 'V8.GC_MC_EVACUATE',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 110, cpuStart: 110, end: 150, cpuEnd: 150,
+ },
+ {
+ title: 'V8.GC_MC_SWEEP',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 120, cpuStart: 120, end: 140, cpuEnd: 140,
+ },
+ {
+ title: 'V8.GC_MC_SWEEP',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 160, cpuStart: 160, end: 190, cpuEnd: 190,
+ },
+ {
+ title: 'V8.GC_MINOR_MARK_COMPACTOR',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 200, cpuStart: 200, end: 300, cpuEnd: 300,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_EVACUATE',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 210, cpuStart: 210, end: 250, cpuEnd: 250,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_SWEEP',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 220, cpuStart: 220, end: 240, cpuEnd: 240,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_SWEEP',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 260, cpuStart: 260, end: 290, cpuEnd: 290,
+ },
+ ];
+ const backgroundSlices = [
+ {
+ title: 'V8.GC_MC_BACKGROUND_EVACUATE_COPY',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 110, cpuStart: 110, end: 150, cpuEnd: 150,
+ },
+ {
+ title: 'V8.GC_MC_BACKGROUND_SWEEPING',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 120, cpuStart: 120, end: 140, cpuEnd: 140,
+ },
+ {
+ title: 'V8.GC_MC_BACKGROUND_SWEEPING',
+ cat: 'v8',
+ args: {'epoch': 0},
+ start: 160, cpuStart: 160, end: 190, cpuEnd: 190,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_BACKGROUND_EVACUATE_COPY',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 210, cpuStart: 210, end: 250, cpuEnd: 250,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_BACKGROUND_SWEEPING',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 220, cpuStart: 220, end: 240, cpuEnd: 240,
+ },
+ {
+ title: 'V8.GC_MINOR_MC_BACKGROUND_SWEEPING',
+ cat: 'v8',
+ args: {'epoch': 1},
+ start: 260, cpuStart: 260, end: 290, cpuEnd: 290,
+ },
+ ];
+ const expectedAverages = [
+ ['v8:gc:cycle:full:compact', 40 + 40],
+ ['v8:gc:cycle:full:sweep', 30 + 30],
+ ['v8:gc:cycle:young:compact', 40 + 40],
+ ['v8:gc:cycle:young:sweep', 30 + 30],
+ ];
+ const metrics = expectedAverages.map(pair => pair[0]);
+ const histograms = addGarbageCollectionMetrics(
+ metrics, mainSlices, backgroundSlices);
+ for (const [name, expectedAverage] of expectedAverages) {
+ const h = histograms.getHistogramNamed(name);
+ assert.closeTo(expectedAverage, h.average, 1e-3);
+ }
+ });
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html
index cb5e9fe2f3a..1c06d3a590a 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html
@@ -41,7 +41,6 @@ tr.exportTo('tr.metrics.v8.utils', function() {
'V8.GCFinalizeMC': 'v8-gc-latency-mark-compactor',
'V8.GCFinalizeMCReduceMemory': 'v8-gc-memory-mark-compactor',
'V8.GCIncrementalMarking': 'v8-gc-incremental-step',
- 'V8.GCIncrementalMarkingFinalize': 'v8-gc-incremental-finalize',
'V8.GCIncrementalMarkingStart': 'v8-gc-incremental-start',
'V8.GCPhantomHandleProcessingCallback': 'v8-gc-phantom-handle-callback',
'V8.GCScavenger': 'v8-gc-scavenger'
@@ -52,7 +51,6 @@ tr.exportTo('tr.metrics.v8.utils', function() {
'V8.GCFinalizeMC',
'V8.GCFinalizeMCReduceMemory',
'V8.GCIncrementalMarking',
- 'V8.GCIncrementalMarkingFinalize',
'V8.GCIncrementalMarkingStart',
'V8.GCPhantomHandleProcessingCallback'
]);
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html
index 507d23e6119..524814d55af 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html
@@ -9,6 +9,7 @@ found in the LICENSE file.
<link rel="import" href="/tracing/metrics/system_health/memory_metric.html">
<link rel="import" href="/tracing/metrics/v8/execution_metric.html">
<link rel="import" href="/tracing/metrics/v8/gc_metric.html">
+<link rel="import" href="/tracing/metrics/v8/runtime_stats_metric.html">
<script>
'use strict';
@@ -17,6 +18,7 @@ tr.exportTo('tr.metrics.v8', function() {
function v8AndMemoryMetrics(histograms, model) {
tr.metrics.v8.executionMetric(histograms, model);
tr.metrics.v8.gcMetric(histograms, model);
+ tr.metrics.v8.runtimeStatsTotalMetric(histograms, model);
tr.metrics.sh.memoryMetric(histograms, model,
{rangeOfInterest: tr.metrics.v8.utils.rangeForMemoryDumps(model)});
}
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric.html
index b9e500c50fd..6e12457e664 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric.html
@@ -38,6 +38,52 @@ tr.exportTo('tr.metrics.v8', function() {
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 computeDeserializeTimeMetric(histograms, wasmEvents) {
+ if (!wasmEvents.hasOwnProperty('wasm.Deserialize')) return;
+
+ const wasmDeserializeTimeCPU = new tr.v.Histogram(
+ 'v8:wasm:deserialize:cpu_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ wasmDeserializeTimeCPU.description =
+ 'cpu time spent deserializing a WebAssembly module';
+ const wasmDeserializeTimeWall = new tr.v.Histogram(
+ 'v8:wasm:deserialize:wall_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ wasmDeserializeTimeWall.description =
+ 'wall time spent deserializing a WebAssembly module';
+
+ for (const e of wasmEvents['wasm.Deserialize']) {
+ wasmDeserializeTimeCPU.addSample(e.cpuDuration);
+ wasmDeserializeTimeWall.addSample(e.duration);
+ }
+
+ histograms.addHistogram(wasmDeserializeTimeCPU);
+ histograms.addHistogram(wasmDeserializeTimeWall);
+ }
+
function computeStreamingBaselineCompileTimeMetric(histograms, wasmEvents) {
// With streaming compilation, baseline compilation happens from when the
// first bytes get received until when baseline compilation finishes. If
@@ -51,12 +97,14 @@ tr.exportTo('tr.metrics.v8', function() {
'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);
+ 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);
}
@@ -70,10 +118,14 @@ tr.exportTo('tr.metrics.v8', function() {
'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);
+ 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);
}
@@ -90,6 +142,8 @@ tr.exportTo('tr.metrics.v8', function() {
const wasmEvents = collectWasmEvents(model);
computeSyncInstantiationTimeMetric(histograms, wasmEvents);
+ computeSyncCompileTimeMetric(histograms, wasmEvents);
+ computeDeserializeTimeMetric(histograms, wasmEvents);
computeStreamingBaselineCompileTimeMetric(histograms, wasmEvents);
computeCompilationTierupWallTimeMetric(histograms, wasmEvents);
}
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric_test.html
index 0681b6ddf3b..573c02d4ff3 100644
--- a/chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/wasm_metric_test.html
@@ -67,14 +67,70 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(wallValue.running.max, 30);
});
+ test('testSyncCompileMetric', function() {
+ const slices = [
+ {
+ title: 'wasm.SyncCompile', args: {}, start: 10, end: 20,
+ cpuStart: 100, cpuEnd: 200
+ },
+ {
+ title: 'wasm.SyncCompile', args: {}, start: 30, end: 60,
+ cpuStart: 300, cpuEnd: 600
+ }
+ ];
+ const histograms = runMetrics(slices);
+
+ const cpuValue =
+ histograms.getHistogramNamed('v8:wasm:sync_compile:cpu_time');
+ assert.strictEqual(cpuValue.running.sum, 400);
+ assert.strictEqual(cpuValue.numValues, 2);
+ assert.strictEqual(cpuValue.average, 200);
+ assert.strictEqual(cpuValue.running.max, 300);
+
+ const wallValue =
+ histograms.getHistogramNamed('v8:wasm:sync_compile:wall_time');
+ assert.strictEqual(wallValue.running.sum, 40);
+ assert.strictEqual(wallValue.numValues, 2);
+ assert.strictEqual(wallValue.average, 20);
+ assert.strictEqual(wallValue.running.max, 30);
+ });
+
+ test('testDeserializeMetric', function() {
+ const slices = [
+ {
+ title: 'wasm.Deserialize', args: {}, start: 10, end: 20,
+ cpuStart: 100, cpuEnd: 200
+ },
+ {
+ title: 'wasm.Deserialize', args: {}, start: 30, end: 60,
+ cpuStart: 300, cpuEnd: 600
+ }
+ ];
+ const histograms = runMetrics(slices);
+
+ const cpuValue =
+ histograms.getHistogramNamed('v8:wasm:deserialize:cpu_time');
+ assert.strictEqual(cpuValue.running.sum, 400);
+ assert.strictEqual(cpuValue.numValues, 2);
+ assert.strictEqual(cpuValue.average, 200);
+ assert.strictEqual(cpuValue.running.max, 300);
+
+ const wallValue =
+ histograms.getHistogramNamed('v8:wasm:deserialize:wall_time');
+ assert.strictEqual(wallValue.running.sum, 40);
+ assert.strictEqual(wallValue.numValues, 2);
+ assert.strictEqual(wallValue.average, 20);
+ assert.strictEqual(wallValue.running.max, 30);
+ });
+
test('testStreamingBaselineCompileTime', function() {
const slices = [
{
- title: 'wasm.StartStreamingCompilation', args: {}, start: 10, end: 20,
- cpuStart: 10, cpuEnd: 20
+ title: 'wasm.StartStreamingCompilation', args: {id: 0}, start: 10,
+ end: 20, cpuStart: 10, cpuEnd: 20
},
{
- title: 'wasm.BaselineFinished', args: {}, start: 100, end: 110,
+ title: 'wasm.BaselineFinished', args: {id: 0}, start: 100, end: 110,
cpuStart: 100, cpuEnd: 110
},
];
@@ -87,10 +143,38 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(compileTime.running.max, 100);
});
+ test('testStreamingBaselineCompileTimeTwoCompilations', function() {
+ const slices = [
+ {
+ title: 'wasm.StartStreamingCompilation', args: {id: 0}, start: 10,
+ end: 20, cpuStart: 10, cpuEnd: 20
+ },
+ {
+ title: 'wasm.StartStreamingCompilation', args: {id: 1}, start: 110,
+ end: 120, cpuStart: 110, cpuEnd: 120
+ },
+ {
+ title: 'wasm.BaselineFinished', args: {id: 1}, start: 200, end: 210,
+ cpuStart: 200, cpuEnd: 210
+ },
+ {
+ title: 'wasm.BaselineFinished', args: {id: 0}, start: 100, end: 110,
+ cpuStart: 100, cpuEnd: 110
+ },
+ ];
+ const histograms = runMetrics(slices);
+
+ const compileTime = histograms.getHistogramNamed(
+ 'v8:wasm:streaming_baseline_compilation:wall_time');
+ assert.strictEqual(compileTime.numValues, 2);
+ assert.strictEqual(compileTime.average, 100);
+ assert.strictEqual(compileTime.running.max, 100);
+ });
+
test('testStreamingBaselineCompileTimeNoStartEvent', function() {
const slices = [
{
- title: 'wasm.BaselineFinished', args: {}, start: 100, end: 110,
+ title: 'wasm.BaselineFinished', args: {id: 0}, start: 100, end: 110,
cpuStart: 100, cpuEnd: 110
},
];
@@ -104,8 +188,8 @@ tr.b.unittest.testSuite(function() {
test('testStreamingBaselineCompileTimeNoEndEvent', function() {
const slices = [
{
- title: 'wasm.StartStreamingCompilation', args: {}, start: 100, end: 110,
- cpuStart: 100, cpuEnd: 110
+ title: 'wasm.StartStreamingCompilation', args: {id: 0}, start: 100,
+ end: 110, cpuStart: 100, cpuEnd: 110
},
];
const histograms = runMetrics(slices);
@@ -118,11 +202,11 @@ tr.b.unittest.testSuite(function() {
test('testTierupWallTime', function() {
const slices = [
{
- title: 'wasm.BaselineFinished', args: {}, start: 100, end: 110,
+ title: 'wasm.BaselineFinished', args: {id: 0}, start: 100, end: 110,
cpuStart: 100, cpuEnd: 110
},
{
- title: 'wasm.TopTierFinished', args: {}, start: 200, end: 210,
+ title: 'wasm.TopTierFinished', args: {id: 0}, start: 200, end: 210,
cpuStart: 200, cpuEnd: 210
},
];
@@ -136,10 +220,39 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(tierupTime.running.max, 110);
});
+ test('testTierupWallTimeTwoTierups', function() {
+ const slices = [
+ {
+ title: 'wasm.BaselineFinished', args: {id: 0}, start: 100, end: 110,
+ cpuStart: 100, cpuEnd: 110
+ },
+ {
+ title: 'wasm.BaselineFinished', args: {id: 1}, start: 200, end: 210,
+ cpuStart: 200, cpuEnd: 210
+ },
+ {
+ title: 'wasm.TopTierFinished', args: {id: 1}, start: 300, end: 310,
+ cpuStart: 200, cpuEnd: 210
+ },
+ {
+ title: 'wasm.TopTierFinished', args: {id: 0}, start: 200, end: 210,
+ cpuStart: 200, cpuEnd: 210
+ },
+ ];
+
+ const histograms = runMetrics(slices);
+
+ const tierupTime = histograms.getHistogramNamed(
+ 'v8:wasm:compilation_tierup:wall_time');
+ assert.strictEqual(tierupTime.numValues, 2);
+ assert.strictEqual(tierupTime.average, 110);
+ assert.strictEqual(tierupTime.running.max, 110);
+ });
+
test('testTierupNoStartEvent', function() {
const slices = [
{
- title: 'wasm.TopTierFinished', args: {}, start: 200, end: 210,
+ title: 'wasm.TopTierFinished', args: {id: 0}, start: 200, end: 210,
cpuStart: 200, cpuEnd: 210
},
];
@@ -154,7 +267,7 @@ tr.b.unittest.testSuite(function() {
test('testTierupNoEndEvent', function() {
const slices = [
{
- title: 'wasm.BaselineFinished', args: {}, start: 100, end: 110,
+ title: 'wasm.BaselineFinished', args: {id: 0}, start: 100, end: 110,
cpuStart: 100, cpuEnd: 110
},
];
diff --git a/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html b/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html
index 8e9e6be8170..57a4da9ea90 100644
--- a/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html
+++ b/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html
@@ -18,6 +18,7 @@ tr.exportTo('tr.model', function() {
// didn't explicitly specify the clock being used.
UNKNOWN_CHROME_LEGACY: 'UNKNOWN_CHROME_LEGACY',
+ FUCHSIA_ZX_CLOCK_MONOTONIC: 'FUCHSIA_ZX_CLOCK_MONOTONIC',
LINUX_CLOCK_MONOTONIC: 'LINUX_CLOCK_MONOTONIC',
LINUX_FTRACE_GLOBAL: 'LINUX_FTRACE_GLOBAL',
MAC_MACH_ABSOLUTE_TIME: 'MAC_MACH_ABSOLUTE_TIME',
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html
index 64ff046b3ef..415400638a9 100644
--- a/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html
@@ -117,7 +117,6 @@ tr.exportTo('tr.model.helpers', function() {
this.irSegments_.push(new tr.model.um.Segment(
gestureEvent.start, gestureEvent.duration));
gestureEventFound = true;
- break;
}
}
} else if (parts[1].startsWith('ui_')) {
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html
index f4a47ef74d1..705ab281dfc 100644
--- a/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html
@@ -71,6 +71,36 @@ tr.b.unittest.testSuite(function() {
assert.deepEqual([6, 8], [segments[2].start, segments[2].end]);
});
+ test('irSegmentWithMultipleGestures', function() {
+ const m = tr.c.TestUtils.newModel((m) => {
+ // There is no IR in this renderer process.
+ const r = m.getOrCreateProcess(1).getOrCreateThread(1);
+ r.name = 'CrRendererMain';
+ r.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceNamed(
+ 'SyntheticGestureController::running', 1, 1));
+ r.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceNamed(
+ 'SyntheticGestureController::running', 3, 1));
+ r.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceNamed(
+ 'SyntheticGestureController::running', 5, 2));
+ r.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Gesture_A', 1, 7));
+ });
+
+ // Async slices are:
+ //
+ // 1 2 3 4 5 6 7 8
+ // Interactions <---------------------- A ------------------------------>
+ // Gestures <-------> <-------> <--------------->
+ //
+ // Segments should be: [1, 2], [3, 4], and [6, 8].
+ const modelHelper = m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ const segments = modelHelper.telemetryHelper.irSegments;
+ assert.strictEqual(3, segments.length);
+ assert.deepEqual([1, 2], [segments[0].start, segments[0].end]);
+ assert.deepEqual([3, 4], [segments[1].start, segments[1].end]);
+ assert.deepEqual([5, 7], [segments[2].start, segments[2].end]);
+ });
+
test('uiSegments', function() {
const m = tr.c.TestUtils.newModel((m) => {
// There is no IR in this renderer process.
diff --git a/chromium/third_party/catapult/tracing/tracing/model/thread.html b/chromium/third_party/catapult/tracing/tracing/model/thread.html
index 0822a6140b3..b31de4aadd6 100644
--- a/chromium/third_party/catapult/tracing/tracing/model/thread.html
+++ b/chromium/third_party/catapult/tracing/tracing/model/thread.html
@@ -239,7 +239,8 @@ tr.exportTo('tr.model', function() {
let sum = 0;
tr.b.iterateOverIntersectingIntervals(
this.sliceGroup.topLevelSlices,
- slice => slice.start, slice => slice.end,
+ slice => slice.start, // mapLoFn
+ slice => slice.duration, // mapWidthFn measures width not end of slice
range.min, range.max,
slice => {
let fractionOfSliceInsideRangeOfInterest = 1;
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py b/chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py
index 877ddaa0645..34e8c431bb0 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py
@@ -22,6 +22,8 @@ class CloudStorageError(Exception):
' 3. For the project-id, just enter 0.' % command)
+# TODO(https://1277796): Rename this once we're Python 3-only.
+# pylint: disable=redefined-builtin
class PermissionError(CloudStorageError):
def __init__(self):
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/failure.py b/chromium/third_party/catapult/tracing/tracing/mre/failure.py
index 8c0713e1d8b..cc70f4ee215 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/failure.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/failure.py
@@ -21,7 +21,7 @@ class Failure(object):
def __str__(self):
return (
'Failure for job %s with function handle %s and trace handle %s:\n'
- 'of type %s wtih description %s. Stack:\n\n%s' % (
+ 'of type "%s" with description "%s". Stack:\n\n%s' % (
self.job.guid, self.function_handle_string,
self.trace_canonical_url, self.failure_type_name,
self.description, self.stack))
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py
index 1140b17aa66..348b63ecf42 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py
@@ -24,7 +24,7 @@ class FailureTests(unittest.TestCase):
'file://foo.html',
'err', 'desc', 'stack')
- self.assertEquals(failure.AsDict(), {
+ self.assertEqual(failure.AsDict(), {
'job_guid': '1',
'function_handle_string': 'foo.html:Foo',
'trace_canonical_url': 'file://foo.html',
@@ -48,9 +48,9 @@ class FailureTests(unittest.TestCase):
failure = failure_module.Failure.FromDict(failure_dict, job)
- self.assertEquals(failure.job.guid, '1')
- self.assertEquals(failure.function_handle_string, 'foo.html:Foo')
- self.assertEquals(failure.trace_canonical_url, 'file://foo.html')
- self.assertEquals(failure.failure_type_name, 'err')
- self.assertEquals(failure.description, 'desc')
- self.assertEquals(failure.stack, 'stack')
+ self.assertEqual(failure.job.guid, '1')
+ self.assertEqual(failure.function_handle_string, 'foo.html:Foo')
+ self.assertEqual(failure.trace_canonical_url, 'file://foo.html')
+ self.assertEqual(failure.failure_type_name, 'err')
+ self.assertEqual(failure.description, 'desc')
+ self.assertEqual(failure.stack, 'stack')
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/function_handle.py b/chromium/third_party/catapult/tracing/tracing/mre/function_handle.py
index 1efa5d647a9..f000e46edef 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/function_handle.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/function_handle.py
@@ -99,7 +99,7 @@ class FunctionHandle(object):
abspath = module.filename
if not abspath:
- raise AbspathInvalidError('Filename %s invalid', abspath)
+ raise AbspathInvalidError('Filename %s invalid' % abspath)
new_modules_to_load.append(ModuleToLoad(filename=abspath))
@@ -136,4 +136,3 @@ class FunctionHandle(object):
return FunctionHandle(modules_to_load=modules_to_load,
function_name=parts[-1])
-
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py
index d3bf71dfe66..522ec69eade 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py
@@ -20,18 +20,18 @@ class ModuleToLoadTests(unittest.TestCase):
mtl0 = function_handle.ModuleToLoad(href='/foo')
mtl1 = function_handle.ModuleToLoad(filename='foo.html')
- self.assertEquals(str(mtl0), 'ModuleToLoad(href="/foo")')
- self.assertEquals(str(mtl1), 'ModuleToLoad(filename="foo.html")')
+ self.assertEqual(str(mtl0), 'ModuleToLoad(href="/foo")')
+ self.assertEqual(str(mtl1), 'ModuleToLoad(filename="foo.html")')
def testAsDict(self):
mtl0 = function_handle.ModuleToLoad(href='/foo')
mtl1 = function_handle.ModuleToLoad(filename='foo.html')
- self.assertEquals(mtl0.AsDict(), {
+ self.assertEqual(mtl0.AsDict(), {
'href': '/foo'
})
- self.assertEquals(mtl1.AsDict(), {
+ self.assertEqual(mtl1.AsDict(), {
'filename': 'foo.html'
})
@@ -47,9 +47,9 @@ class ModuleToLoadTests(unittest.TestCase):
mtl0 = function_handle.ModuleToLoad.FromDict(module_dict0)
mtl1 = function_handle.ModuleToLoad.FromDict(module_dict1)
- self.assertEquals(mtl0.href, '/foo')
+ self.assertEqual(mtl0.href, '/foo')
self.assertIsNone(mtl0.filename)
- self.assertEquals(mtl1.filename, 'foo.html')
+ self.assertEqual(mtl1.filename, 'foo.html')
self.assertIsNone(mtl1.href)
@@ -59,7 +59,7 @@ class FunctionHandleTests(unittest.TestCase):
module = function_handle.ModuleToLoad(href='/foo')
handle = function_handle.FunctionHandle([module], 'Bar')
- self.assertEquals(
+ self.assertEqual(
str(handle),
'FunctionHandle(modules_to_load=[ModuleToLoad(href="/foo")], '
'function_name="Bar")')
@@ -68,7 +68,7 @@ class FunctionHandleTests(unittest.TestCase):
module = function_handle.ModuleToLoad(href='/foo')
handle = function_handle.FunctionHandle([module], 'Bar')
- self.assertEquals(
+ self.assertEqual(
handle.AsDict(), {
'modules_to_load': [{'href': '/foo'}],
'function_name': 'Bar'
@@ -81,6 +81,6 @@ class FunctionHandleTests(unittest.TestCase):
}
handle = function_handle.FunctionHandle.FromDict(handle_dict)
- self.assertEquals(len(handle.modules_to_load), 1)
- self.assertEquals(handle.modules_to_load[0].href, '/foo')
- self.assertEquals(handle.function_name, 'Bar')
+ self.assertEqual(len(handle.modules_to_load), 1)
+ self.assertEqual(handle.modules_to_load[0].href, '/foo')
+ self.assertEqual(handle.function_name, 'Bar')
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py b/chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py
index aafc8838de3..6d5e86c72da 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py
@@ -13,8 +13,8 @@ class JSONOutputFormatter(output_formatter.OutputFormatter):
super(JSONOutputFormatter, self).__init__(output_file)
self.output_file = output_file
- def Format(self, result_list):
- d = [result.AsDict() for result in result_list]
+ def Format(self, results):
+ d = [result.AsDict() for result in results]
json.dump(d, self.output_file, indent=2)
if hasattr(self.output_file, 'flush'):
self.output_file.flush()
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py b/chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py
index a235f916baf..ee78dd585ca 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py
@@ -66,4 +66,3 @@ class LocalDirectoryCorpusDriver(corpus_driver.CorpusDriver):
trace_handles.append(th)
return trace_handles
-
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py
index f035b693758..92a366062ba 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py
@@ -120,7 +120,7 @@ def MapSingleTrace(trace_handle,
job,
trace_handle.canonical_url,
'Error', 'vinn runtime error while mapping trace.',
- e.message, 'Unknown stack'))
+ str(e), 'Unknown stack'))
return result
stdout = res.stdout
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py
index 6f0f2f43c5d..3cf0658c943 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py
@@ -51,7 +51,7 @@ class MapSingleTraceTests(unittest.TestCase):
self.assertFalse(result.failures)
r = result.pairs['result']
- self.assertEquals(r['numProcesses'], 1)
+ self.assertEqual(r['numProcesses'], 1)
def testProcessingGiantTrace(self):
@@ -87,7 +87,7 @@ class MapSingleTraceTests(unittest.TestCase):
self.assertFalse(result.failures,
msg='\n'.join(str(f) for f in result.failures))
r = result.pairs['result']
- self.assertEquals(r['numEvents'], 2000000)
+ self.assertEqual(r['numEvents'], 2000000)
@@ -104,8 +104,8 @@ class MapSingleTraceTests(unittest.TestCase):
result = map_single_trace.MapSingleTrace(trace_handle,
_Handle(map_script.filename))
- self.assertEquals(len(result.failures), 1)
- self.assertEquals(len(result.pairs), 0)
+ self.assertEqual(len(result.failures), 1)
+ self.assertEqual(len(result.pairs), 0)
f = result.failures[0]
self.assertIsInstance(f, map_single_trace.TraceImportFailure)
@@ -128,8 +128,8 @@ class MapSingleTraceTests(unittest.TestCase):
result = map_single_trace.MapSingleTrace(trace_handle,
_Handle(map_script.filename))
- self.assertEquals(len(result.failures), 1)
- self.assertEquals(len(result.pairs), 0)
+ self.assertEqual(len(result.failures), 1)
+ self.assertEqual(len(result.pairs), 0)
f = result.failures[0]
self.assertIsInstance(f, map_single_trace.MapFunctionFailure)
@@ -149,8 +149,8 @@ class MapSingleTraceTests(unittest.TestCase):
result = map_single_trace.MapSingleTrace(trace_handle,
_Handle(map_script.filename))
- self.assertEquals(len(result.failures), 1)
- self.assertEquals(len(result.pairs), 0)
+ self.assertEqual(len(result.failures), 1)
+ self.assertEqual(len(result.pairs), 0)
f = result.failures[0]
self.assertIsInstance(f, map_single_trace.FunctionLoadingFailure)
@@ -168,8 +168,8 @@ class MapSingleTraceTests(unittest.TestCase):
result = map_single_trace.MapSingleTrace(trace_handle,
_Handle(map_script.filename))
- self.assertEquals(len(result.failures), 1)
- self.assertEquals(len(result.pairs), 0)
+ self.assertEqual(len(result.failures), 1)
+ self.assertEqual(len(result.pairs), 0)
f = result.failures[0]
self.assertIsInstance(f, failure.Failure)
@@ -188,8 +188,8 @@ class MapSingleTraceTests(unittest.TestCase):
result = map_single_trace.MapSingleTrace(trace_handle,
_Handle(map_script.filename))
- self.assertEquals(len(result.failures), 1)
- self.assertEquals(len(result.pairs), 0)
+ self.assertEqual(len(result.failures), 1)
+ self.assertEqual(len(result.pairs), 0)
f = result.failures[0]
self.assertIsInstance(f, map_single_trace.FunctionNotDefinedFailure)
@@ -211,8 +211,8 @@ class MapSingleTraceTests(unittest.TestCase):
result = map_single_trace.MapSingleTrace(trace_handle,
_Handle(map_script.filename))
- self.assertEquals(len(result.failures), 1)
- self.assertEquals(len(result.pairs), 0)
+ self.assertEqual(len(result.failures), 1)
+ self.assertEqual(len(result.pairs), 0)
f = result.failures[0]
self.assertIsInstance(f, map_single_trace.NoResultsAddedFailure)
@@ -226,7 +226,7 @@ class MapSingleTraceTests(unittest.TestCase):
results.addPair('numProcesses', model.getAllProcesses().length);
};
""")
- self.assertEquals(results['numProcesses'], 2)
+ self.assertEqual(results['numProcesses'], 2)
def testExecuteTraceMappingCodeWithError(self):
test_trace_path = os.path.join(os.path.dirname(__file__), 'test_trace.json')
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_traces.py b/chromium/third_party/catapult/tracing/tracing/mre/map_traces.py
index 749e7acab39..b87c76c57f2 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/map_traces.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_traces.py
@@ -60,8 +60,7 @@ def Main(argv):
results = runner.Run()
if not any(result.failures for result in results):
return 0
- else:
- return 255
+ return 255
finally:
if ofile != sys.stdout:
ofile.close()
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/mre_result.py b/chromium/third_party/catapult/tracing/tracing/mre/mre_result.py
index f3d128e23a8..572b3114ccf 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/mre_result.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/mre_result.py
@@ -38,7 +38,7 @@ class MreResult(object):
def AddFailure(self, failure):
if not isinstance(failure, failure_module.Failure):
- raise ValueError('Attempted to add %s as Failure', failure)
+ raise ValueError('Attempted to add %s as Failure' % failure)
self._failures.append(failure)
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py
index 2bdb5a8f19a..88ab596405e 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py
@@ -37,8 +37,8 @@ class MreResultTests(unittest.TestCase):
result_dict = result.AsDict()
- self.assertEquals(result_dict['failures'], [failure.AsDict()])
- self.assertEquals(result_dict['pairs'], {'foo': 'bar'})
+ self.assertEqual(result_dict['failures'], [failure.AsDict()])
+ self.assertEqual(result_dict['pairs'], {'foo': 'bar'})
def testAddingNonFailure(self):
result = mre_result.MreResult()
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py
index 9bb086e05e0..e4b98a42a28 100644
--- a/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py
@@ -23,7 +23,7 @@ class ThreadedWorkQueueTests(unittest.TestCase):
wq = threaded_work_queue.ThreadedWorkQueue(num_threads=1)
wq.PostAnyThreadTask(Ex)
res = wq.Run()
- self.assertEquals(res, None)
+ self.assertEqual(res, None)
def _RunSimpleDecrementingTest(self, wq):
@@ -39,4 +39,4 @@ class ThreadedWorkQueueTests(unittest.TestCase):
wq.PostAnyThreadTask(Decrement)
res = wq.Run()
- self.assertEquals(res, 314)
+ self.assertEqual(res, 314)
diff --git a/chromium/third_party/catapult/tracing/tracing/proto/histogram_proto.py b/chromium/third_party/catapult/tracing/tracing/proto/histogram_proto.py
index 087454926df..de0eedb8e08 100644
--- a/chromium/third_party/catapult/tracing/tracing/proto/histogram_proto.py
+++ b/chromium/third_party/catapult/tracing/tracing/proto/histogram_proto.py
@@ -2,14 +2,25 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from __future__ import absolute_import
try:
# Note: from tracing.proto import histogram_pb2 would make more sense here,
# but unfortunately protoc does not generate __init__.py files if you specify
# an out package (at least for the gn proto_library rule).
- import histogram_pb2 # pylint:disable=relative-import
+ import histogram_pb2
HAS_PROTO = True
-except ImportError:
- HAS_PROTO = False
+except ImportError as e:
+ try:
+ # crbug/1234919
+ # Catapult put the generated histogram_pb2.py in the same source folder,
+ # while the others (e.g., webrtc) put it in output path. By default we
+ # try to import from the sys.path. Here allows to try import from the
+ # source folder as well.
+ # TODO(wenbinzhang): Clean up import paths to work consistently.
+ from . import histogram_pb2
+ HAS_PROTO = True
+ except ImportError:
+ HAS_PROTO = False
def _EnsureProto():
@@ -51,14 +62,14 @@ if HAS_PROTO:
histogram_pb2.COUNT: 'count',
histogram_pb2.SIGMA: 'sigma',
}
- UNIT_PROTO_MAP = {v: k for k, v in PROTO_UNIT_MAP.iteritems()}
+ UNIT_PROTO_MAP = {v: k for k, v in PROTO_UNIT_MAP.items()}
PROTO_IMPROVEMENT_DIRECTION_MAP = {
histogram_pb2.BIGGER_IS_BETTER: 'biggerIsBetter',
histogram_pb2.SMALLER_IS_BETTER: 'smallerIsBetter',
}
IMPROVEMENT_DIRECTION_PROTO_MAP = {
- v: k for k, v in PROTO_IMPROVEMENT_DIRECTION_MAP.iteritems()
+ v: k for k, v in PROTO_IMPROVEMENT_DIRECTION_MAP.items()
}
@@ -87,4 +98,3 @@ def ProtoFromUnit(unit):
proto_unit.improvement_direction = IMPROVEMENT_DIRECTION_PROTO_MAP[parts[1]]
return proto_unit
-
diff --git a/chromium/third_party/catapult/tracing/tracing/proto/histogram_proto_unittest.py b/chromium/third_party/catapult/tracing/tracing/proto/histogram_proto_unittest.py
index 0c0edf1a6ac..3bba48eee13 100644
--- a/chromium/third_party/catapult/tracing/tracing/proto/histogram_proto_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/proto/histogram_proto_unittest.py
@@ -3,8 +3,16 @@
# found in the LICENSE file.
import unittest
+import sys
+from six.moves import reload_module
-from tracing.proto import histogram_proto
+# Some packages, such as protobuf, clobber the google
+# namespace package. This prevents that.
+# crbug/1233198
+if 'google' in sys.modules:
+ reload_module(sys.modules['google'])
+
+from tracing.proto import histogram_proto# pylint: disable=wrong-import-position
class HistogramProtoUnittest(unittest.TestCase):
diff --git a/chromium/third_party/catapult/tracing/tracing/tests.html b/chromium/third_party/catapult/tracing/tracing/tests.html
index 2851bfae495..b2cb2cfd7b9 100644
--- a/chromium/third_party/catapult/tracing/tracing/tests.html
+++ b/chromium/third_party/catapult/tracing/tracing/tests.html
@@ -14,8 +14,6 @@ found in the LICENSE file.
<!-- WebComponents V0 origin trial token for 127.0.0.1:8003. Expires 1 Feb 2020.
See https://crbug.com/1021137. -->
<meta http-equiv="origin-trial" content="AuwWuUBIJgUHKi5rgEkqYaWR/Rbl/WrQPklxP3Lb9JBLQwdU4ykouPn0hTva5pHumlKNc1TqeZD1GEWo3YXTtQUAAABSeyJvcmlnaW4iOiJodHRwOi8vMTI3LjAuMC4xOjgwMDMiLCJmZWF0dXJlIjoiV2ViQ29tcG9uZW50c1YwIiwiZXhwaXJ5IjoxNjEyMjIzOTk5fQ==">
- <script src="/components/webcomponentsjs/webcomponents.js"></script>
-
<link rel="shortcut icon" href="data:image/x-icon;base64,"
type="image/x-icon">
diff --git a/chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py b/chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py
index bdb1f26b0b7..a22a6ee39a9 100644
--- a/chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py
+++ b/chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py
@@ -1,4 +1,3 @@
# 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/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py b/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py
index e599502c1d4..693f5c110d4 100644
--- a/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py
+++ b/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py
@@ -6,11 +6,11 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import collections
+import sys
import gzip
import json
import logging
import os
-import platform
import shutil
import subprocess
import tempfile
@@ -18,6 +18,10 @@ import time
import traceback
import six
+if sys.version_info.major == 3:
+ JSON_FILE_MODE = 'w+'
+else:
+ JSON_FILE_MODE = 'w+b'
try:
StringTypes = six.string_types # pylint: disable=invalid-name
@@ -126,7 +130,7 @@ class TraceDataBuilder(object):
def __exit__(self, *args):
self.CleanUpTraceData()
- def OpenTraceHandleFor(self, part, suffix):
+ def OpenTraceHandleFor(self, part, suffix, mode=None):
"""Open a file handle for writing trace data into it.
Args:
@@ -139,10 +143,16 @@ class TraceDataBuilder(object):
raise TypeError('part must be a TraceDataPart instance')
if self._frozen:
raise RuntimeError('trace data builder is no longer open for writing')
- trace = _TraceItem(
- part_name=part.raw_field_name,
- handle=tempfile.NamedTemporaryFile(
- delete=False, dir=self._temp_dir, suffix=suffix))
+ if mode:
+ trace = _TraceItem(
+ part_name=part.raw_field_name,
+ handle=tempfile.NamedTemporaryFile(
+ mode=mode, delete=False, dir=self._temp_dir, suffix=suffix))
+ else:
+ trace = _TraceItem(
+ part_name=part.raw_field_name,
+ handle=tempfile.NamedTemporaryFile(
+ delete=False, dir=self._temp_dir, suffix=suffix))
self._traces.append(trace)
return trace.handle
@@ -190,7 +200,7 @@ class TraceDataBuilder(object):
suffix = '.json'
else:
raise TypeError('invalid trace data type')
- with self.OpenTraceHandleFor(part, suffix) as handle:
+ with self.OpenTraceHandleFor(part, suffix, JSON_FILE_MODE) as handle:
do_write(data, handle)
def Freeze(self):
@@ -324,14 +334,7 @@ def SerializeAsHtml(trace_files, html_file, trace_title=None):
input_size = sum(os.path.getsize(trace_file) for trace_file in trace_files)
- cmd = []
- if platform.system() == 'Windows':
- version_cmd = ['python', '-c',
- 'import sys\nprint(sys.version_info.major)']
- version = subprocess.check_output(version_cmd)
- if version.strip() == '3':
- raise RuntimeError('trace2html cannot run with python 3.')
- cmd.append('python')
+ cmd = [sys.executable]
cmd.append(_TRACE2HTML_PATH)
cmd.extend(trace_files)
cmd.extend(['--output', html_file])
diff --git a/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py b/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py
index 37874841140..b59bd86e55f 100644
--- a/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py
@@ -59,7 +59,8 @@ class TraceDataBuilderTest(unittest.TestCase):
def testAddTraceFileFor(self):
original_data = {'msg': 'The answer is 42'}
- with tempfile.NamedTemporaryFile(delete=False, suffix='.json') as source:
+ with tempfile.NamedTemporaryFile(
+ delete=False, suffix='.json', mode='w+') as source:
json.dump(original_data, source)
with trace_data.TraceDataBuilder() as builder:
builder.AddTraceFileFor(trace_data.CHROME_TRACE_PART, source.name)
@@ -72,7 +73,7 @@ class TraceDataBuilderTest(unittest.TestCase):
original_data = {'msg': 'The answer is 42'}
with trace_data.TraceDataBuilder() as builder:
with builder.OpenTraceHandleFor(
- trace_data.CHROME_TRACE_PART, suffix='.json') as handle:
+ trace_data.CHROME_TRACE_PART, suffix='.json', mode='w+') as handle:
handle.write(json.dumps(original_data))
out_data = builder.AsData().GetTraceFor(trace_data.CHROME_TRACE_PART)
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html
index 574cf5f0b86..0f639da1572 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html
@@ -15,7 +15,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
const newSliceEx = tr.c.TestUtils.newSliceEx;
test('instantiate', function() {
@@ -47,7 +48,8 @@ tr.b.unittest.testSuite(function() {
assert.lengthOf(columns, 2);
});
- test('instantiate_twoAlertsWithRelatedEvents', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_twoAlertsWithRelatedEvents', function() {
const slice1 = newSliceEx({title: 'b', start: 0, duration: 0.002});
const slice2 = newSliceEx({title: 'b', start: 1, duration: 0.002});
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html
index 974837f545e..92be2bedc27 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html
@@ -300,7 +300,8 @@ tr.b.unittest.testSuite(function() {
}, containerEl);
});
- test('instantiate_differentProcessMemoryDumps', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_differentProcessMemoryDumps', function() {
const globalMemoryDumps =
tr.ui.analysis.createMultipleTestGlobalMemoryDumps();
// 2 dumps in Process 1, 3 dumps in Process 2, and 1 dump in Process 4
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html
index 04ba9388852..43772870d97 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html
@@ -47,7 +47,8 @@ tr.b.unittest.testSuite(function() {
assert.isUndefined(chart.chart);
});
- test('instantiate_oneFrame', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_oneFrame', function() {
const series = new tr.model.PowerSeries(new tr.Model().device);
const vSyncTimestamps = [0];
@@ -70,7 +71,8 @@ tr.b.unittest.testSuite(function() {
assert.sameDeepMembers(chart.chart.data, expectedChartData);
});
- test('instantiate_twoFrames', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_twoFrames', function() {
const series = new tr.model.PowerSeries(new tr.Model().device);
const vSyncTimestamps = [0, 4];
@@ -101,7 +103,8 @@ tr.b.unittest.testSuite(function() {
assert.sameDeepMembers(chart.chart.data, expectedChartData);
});
- test('instantiate_twoFramesDifferentXValues', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_twoFramesDifferentXValues', function() {
const series = new tr.model.PowerSeries(new tr.Model().device);
// Power samples taken at 0, 1, 2, and 3s after frame start.
@@ -134,7 +137,8 @@ tr.b.unittest.testSuite(function() {
assert.sameDeepMembers(chart.chart.data, expectedChartData);
});
- test('instantiate_samplesBeforeFirstVSync', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_samplesBeforeFirstVSync', function() {
const series = new tr.model.PowerSeries(new tr.Model().device);
const vSyncTimestamps = [4];
@@ -182,7 +186,8 @@ tr.b.unittest.testSuite(function() {
assert.isUndefined(chart.chart);
});
- test('instantiate_vSyncsAfterLastPowerSample', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_vSyncsAfterLastPowerSample', function() {
const series = new tr.model.PowerSeries(new tr.Model().device);
const vSyncTimestamps = [0, 4, 8, 12];
@@ -232,8 +237,8 @@ tr.b.unittest.testSuite(function() {
assert.isUndefined(chart.chart);
});
-
- test('instantiate_samplesNotInChronologicalOrder', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_samplesNotInChronologicalOrder', function() {
const series = new tr.model.PowerSeries(new tr.Model().device);
const vSyncTimestamps = [0, 4];
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html
index e0c33df1231..969a9871a90 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html
@@ -95,7 +95,7 @@ Polymer({
if (!(object instanceof Object)) {
const type = typeof object;
if (type !== 'string') {
- return this.appendSimpleText_(label, indent, object, suffix);
+ return this.appendSimpleText_(label, indent, String(object), suffix);
}
let objectReplaced = false;
if ((object[0] === '{' && object[object.length - 1] === '}') ||
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html
index 2e7812e2730..cca52ae3ae2 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html
@@ -62,7 +62,8 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(view.$.content.children.length, 3);
});
- test('booleanValue', function() {
+ // See https://crbug.com/1143376.
+ skipTest('booleanValue', function() {
const view = document.createElement('tr-ui-a-generic-object-view');
view.object = false;
assert.strictEqual(Polymer.dom(view.$.content).textContent, 'false');
@@ -196,7 +197,8 @@ tr.b.unittest.testSuite(function() {
view.$.content, 'tr-v-ui-scalar-span'));
});
- test('scalarValue', function() {
+ // See https://crbug.com/1143376.
+ skipTest('scalarValue', function() {
const view = document.createElement('tr-ui-a-generic-object-view');
view.object =
new tr.b.Scalar(tr.b.Unit.byName.normalizedPercentage, .3);
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html
index 9d17e39ce85..15ad35863a1 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html
@@ -141,7 +141,7 @@ tr.exportTo('tr.ui.analysis', function() {
if (!this.displayedNode_.parentNode) break;
// Enter the parent node upon pressing backspace.
- const viewEvent = new tr.b.Event('enter-node');
+ const viewEvent = new tr.b.Event('enter-node', true /*bubbles*/);
viewEvent.node = this.displayedNode_.parentNode;
this.dispatchEvent(viewEvent);
keyHandled = true;
@@ -180,7 +180,7 @@ tr.exportTo('tr.ui.analysis', function() {
ready() {
this.$.table.addEventListener('step-into', function(tableEvent) {
- const viewEvent = new tr.b.Event('enter-node');
+ const viewEvent = new tr.b.Event('enter-node', true /*bubbles*/);
viewEvent.node = tableEvent.tableRow;
this.dispatchEvent(viewEvent);
}.bind(this));
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html
index 9958b7db81c..edabfc7fe54 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html
@@ -14,7 +14,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
const Model = tr.Model;
const Thread = tr.model.Thread;
const EventSet = tr.model.EventSet;
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/base.html b/chromium/third_party/catapult/tracing/tracing/ui/base/base.html
index e0ca9e23c6b..e24c88c653a 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/base.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/base.html
@@ -5,6 +5,8 @@ Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
+<link rel="import" href="/tracing/base/base.html" data-suppress-import-order>
+
<link rel="import" href="/tracing/ui/base/polymer_preload.html" data-suppress-import-order>
<!--
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html
index 7083856c539..090d8f70743 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html
@@ -11,7 +11,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1111537
+tr.b.unittest.skippedTestSuite(function() {
function createQuads() {
const quads = [
tr.b.math.Quad.fromXYWH(-500, -500, 30, 30), // 4 corners
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html
index 54417b3ded6..72d66adfd15 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html
@@ -45,7 +45,8 @@ tr.b.unittest.testSuite(function() {
assert.isTrue(container.children[2].decorated);
});
- test('clearUsingTextContent', function() {
+ // See https://crbug.com/1111537
+ skipTest('clearUsingTextContent', function() {
const c0 = createChild();
const container = new SimpleContainer();
Polymer.dom(container).appendChild(c0);
@@ -61,7 +62,8 @@ tr.b.unittest.testSuite(function() {
assert.isFalse(c0.decorated);
});
- test('insertNewBefore', function() {
+ // See https://crbug.com/1111537
+ skipTest('insertNewBefore', function() {
const c0 = createChild();
const c1 = createChild();
const container = new SimpleContainer();
@@ -82,7 +84,8 @@ tr.b.unittest.testSuite(function() {
assert.isTrue(c1.decorated);
});
- test('testReplace', function() {
+ // See https://crbug.com/1111537
+ skipTest('testReplace', function() {
const c0 = createChild();
const c1 = createChild();
const container = new SimpleContainer();
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html
index 46313143710..4f35f0467cd 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html
@@ -9,7 +9,7 @@ found in the LICENSE file.
'use strict';
tr.b.unittest.testSuite(function() {
- const THIS_DOC = document.currentScript.ownerDocument;
+ const THIS_DOC = document._currentScript.ownerDocument;
test('simpleSpanAndDiv', function() {
const divEl = tr.ui.b.createDiv({
@@ -145,25 +145,25 @@ tr.b.unittest.testSuite(function() {
let node = tr.ui.b.asHTMLOrTextNode('Hello, World!');
assert.instanceOf(node, Node);
assert.strictEqual(Polymer.dom(node).textContent, 'Hello, World!');
- assert.strictEqual(node.ownerDocument, document);
+ assert.strictEqual(unwrap(node.ownerDocument), document);
// Custom owner document.
node = tr.ui.b.asHTMLOrTextNode('Bye, World!', THIS_DOC);
assert.instanceOf(node, Node);
assert.strictEqual(Polymer.dom(node).textContent, 'Bye, World!');
- assert.strictEqual(node.ownerDocument, THIS_DOC);
+ assert.strictEqual(unwrap(node.ownerDocument), unwrap(THIS_DOC));
});
test('asHTMLOrTextNode_node', function() {
// Node object. Owner document should NOT be modified.
let node = document.createTextNode('Hi', THIS_DOC);
assert.strictEqual(tr.ui.b.asHTMLOrTextNode(node), node);
- assert.strictEqual(node.ownerDocument, document);
+ assert.strictEqual(unwrap(node.ownerDocument), unwrap(document));
// HTMLElement object. Owner document should NOT be modified.
node = THIS_DOC.createElement('div');
assert.strictEqual(tr.ui.b.asHTMLOrTextNode(node), node);
- assert.strictEqual(node.ownerDocument, THIS_DOC);
+ assert.strictEqual(unwrap(node.ownerDocument), unwrap(THIS_DOC));
});
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html
index bdc118a4d09..e0953f00e84 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html
@@ -27,7 +27,8 @@ tr.b.unittest.testSuite(function() {
elem.dispatchEvent(clickEvent);
}
- test('basic', function() {
+ // See https://crbug.com/1143376.
+ skipTest('basic', function() {
const dd = document.createElement('tr-ui-b-dropdown');
dd.style.marginLeft = '50px';
dd.style.width = '50px';
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html
index cff10cb775c..ab7a018009e 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html
@@ -11,7 +11,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
const KeyEventManager = tr.b.KeyEventManager;
function newKeyEvent(eventType, dict) {
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html
index 304d48ede37..7dc93a60272 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html
@@ -21,7 +21,8 @@ tr.b.unittest.testSuite(function() {
this.addHTMLOutput(infoBarGroup);
});
- test('group-populate-then-clear', function() {
+ // See https://crbug.com/1143376.
+ skipTest('group-populate-then-clear', function() {
const infoBarGroup = document.createElement('tr-ui-b-info-bar-group');
infoBarGroup.addMessage(
'Message 1',
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html
index d5e9c19e672..7912b58d344 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html
@@ -28,7 +28,8 @@ Polymer({
behaviors: [nonSubViewBehavior]
});
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
function createPowerSampleSubView() {
const model = tr.c.TestUtils.newModel(function(m) {
m.device.powerSeries = new tr.model.PowerSeries(m.device);
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html
index 73e8aca4418..4f768817c9d 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html
@@ -1052,7 +1052,8 @@ tr.b.unittest.testSuite(function() {
assert.isFalse(table.getExpandedForTableRow(rows[0]));
});
- test('focus_empty', function() {
+ // See https://crbug.com/1143376.
+ skipTest('focus_empty', function() {
const table = createSimpleOneColumnNestedTable();
table.tableRows = [];
table.emptyValue = 'This table is left intentionally empty';
@@ -1105,7 +1106,8 @@ tr.b.unittest.testSuite(function() {
assert.isUndefined(table.selectedColumnIndex);
});
- test('focus_rows', function() {
+ // See https://crbug.com/1143376.
+ skipTest('focus_rows', function() {
const table = createSimpleOneColumnNestedTable();
table.selectionMode = SelectionMode.ROW;
this.addHTMLOutput(table);
@@ -1165,7 +1167,8 @@ tr.b.unittest.testSuite(function() {
assert.isUndefined(table.selectedColumnIndex);
});
- test('focus_cells', function() {
+ // See https://crbug.com/1143376.
+ skipTest('focus_cells', function() {
const table = createMultiColumnNestedTable();
table.selectionMode = SelectionMode.CELL;
this.addHTMLOutput(table);
@@ -1232,7 +1235,8 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(table.selectedColumnIndex, 1);
});
- test('focus_allCellsUnselectable', function() {
+ // See https://crbug.com/1143376.
+ skipTest('focus_allCellsUnselectable', function() {
const table = createMultiColumnNestedTable();
table.selectionMode = SelectionMode.CELL;
for (const c of table.tableColumns) {
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/utils.html b/chromium/third_party/catapult/tracing/tracing/ui/base/utils.html
index cca1003cc06..87b2f344b1f 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/utils.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/utils.html
@@ -60,19 +60,7 @@ tr.exportTo('tr.ui.b', function() {
undefined, {minimumFractionDigits: 3, maximumFractionDigits: 3});
}
- /**
- * Returns true if |name| is the name of an unknown HTML element. Registered
- * polymer elements are known, so this returns false. Typos of registered
- * polymer element names are unknown, so this returns true for typos.
- *
- * @return {boolean}
- */
- function isUnknownElementName(name) {
- return document.createElement(name) instanceof HTMLUnknownElement;
- }
-
return {
- isUnknownElementName,
toThreeDigitLocaleString,
instantiateTemplate,
windowRectForElement,
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html
index 4ab76e1d221..aa84b3b40df 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html
@@ -37,7 +37,8 @@ Polymer({
tr.b.unittest.testSuite(function() {
const THIS_DOC = document.currentScript.ownerDocument;
- test('instantiateTemplatePolymer', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiateTemplatePolymer', function() {
const e = tr.ui.b.instantiateTemplate(
'#instantiate-template-polymer-test',
THIS_DOC);
@@ -45,7 +46,8 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(e.children[0].testProperty, 'Test');
});
- test('instantiateTemplateMultipleTemplates', function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiateTemplateMultipleTemplates', function() {
const outerElement = tr.ui.b.instantiateTemplate(
'#multiple-template-test',
THIS_DOC);
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html
index 26d01ad27cf..08c5b67c69f 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html
@@ -45,6 +45,21 @@ x-timeline-view-buttons {
display: flex;
align-items: center;
}
+
+#perfetto-banner-outer {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ margin: auto 0;
+}
+
+#perfetto-banner-inner {
+ margin: auto 0;
+}
+
+#perfetto-logo-caption {
+ margin: 50px;
+}
</style>
<template id="profiling-view-template">
@@ -55,7 +70,18 @@ x-timeline-view-buttons {
<button id="load-button">Load</button>
</x-timeline-view-buttons>
<tr-ui-timeline-view>
- <track-view-container id='track_view_container'></track-view-container>
+ <track-view-container id='track_view_container'>
+ <div id="perfetto-banner-outer">
+ <div id="perfetto-banner-inner">
+ <img
+ src="data:image/jpeg;base64,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"></a>
+ <div id="perfetto-logo-caption">
+ Try the new <a href="https://ui.perfetto.dev">Perfetto UI</a>!
+ <a href="https://chromium.googlesource.com/catapult/+/refs/heads/main/tracing/docs/perfetto.md">Learn more</a>.
+ </div>
+ </div>
+ </div>
+ </track-view-container>
</tr-ui-timeline-view>
</template>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html
index 1344c1a36f9..11de7bca881 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html
@@ -15,7 +15,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
const Base64 = tr.b.Base64;
const testData = [
{name: 'a', args: {}, pid: 52, ts: 15000, cat: 'foo', tid: 53, ph: 'B'},
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html
index e3e0438f3a2..1f6aaf36da7 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html
@@ -13,7 +13,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
const testData = [
{name: 'a', args: {}, pid: 52, ts: 15000, cat: 'foo', tid: 53, ph: 'B'},
{name: 'a', args: {}, pid: 52, ts: 19000, cat: 'foo', tid: 53, ph: 'E'},
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html
index 7c62b487305..b286c065ec1 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html
@@ -12,7 +12,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
test('instantitate', function() {
const showButton = document.createElement('button');
Polymer.dom(showButton).textContent = 'Show record selection dialog';
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html
index c10d6995db3..067e8dc820d 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html
@@ -11,7 +11,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
test('instantiate', function() {
const displayItemList = new tr.e.cc.DisplayItemListSnapshot(
{id: '31415'},
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html
index 1831be24618..bc2b35939d5 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html
@@ -18,7 +18,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
test('instantiate', function() {
const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
const p = Object.values(m.processes)[0];
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html
index 66932ae785f..e8d31358ee5 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html
@@ -17,7 +17,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
test('tileCoverageRectCount', function() {
const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
const p = m.processes[1];
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html
index ed3de7b87e1..0694f977a4b 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html
@@ -17,7 +17,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
test('instantiate', function() {
const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
const p = m.processes[1];
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html
index 56767cfcc89..90488f46b5f 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html
@@ -47,7 +47,8 @@ tr.b.unittest.testSuite(function() {
this.addHTMLOutput(view);
});
- test('analysisViewIntegration', function() {
+ // See https://crbug.com/1143376.
+ skipTest('analysisViewIntegration', function() {
const selection = createSelection();
const timelineView = {model: selection.model};
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html
index 723e120ebc6..288ab5df807 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html
@@ -120,7 +120,13 @@ found in the LICENSE file.
<div id="control">
<div id="bar">
<div id="left_controls"></div>
- <div id="title">^_^</div>
+ <div id="title">
+ ^_^
+ <div style="padding-left: 3em">
+ Try the new <a href="https://ui.perfetto.dev">Perfetto UI</a>!
+ <a href="https://chromium.googlesource.com/catapult/+/refs/heads/main/tracing/docs/perfetto.md">Learn more</a>
+ </div>
+ </div>
<div id="right_controls">
<tr-ui-b-dropdown id="flow_event_filter_dropdown" label="Flow events"></tr-ui-b-dropdown>
<tr-ui-b-dropdown id="process_filter_dropdown" label="Processes"></tr-ui-b-dropdown>
@@ -140,8 +146,6 @@ found in the LICENSE file.
<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>
@@ -161,9 +165,7 @@ found in the LICENSE file.
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.';
+ 'features may be broken. See crbug.com/1036492.';
Polymer({
is: 'tr-ui-timeline-view',
@@ -278,19 +280,6 @@ Polymer({
if (this.polyfillWarnedOnce_) return;
console.warn(POLYFILL_WARNING_MESSAGE); // eslint-disable-line no-console
this.polyfillWarnedOnce_ = true;
-
- // You can set window.__hideTraceViewerPolyfillWarning = true somewhere
- // in your setup code if you embed trace viewer and want to hide the
- // UI polyfill warning.
- if (!window.__hideTraceViewerPolyfillWarning) {
- const polyfillWarningsEl =
- Polymer.dom(this.root).querySelector('#polyfill-warning');
- polyfillWarningsEl.addMessage(
- POLYFILL_WARNING_MESSAGE, [{
- buttonText: 'Hide',
- onClick: () => polyfillWarningsEl.clearMessages()
- }]);
- }
},
updateDocumentFavicon() {
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html
index d922030ce70..49a31c0e1a0 100644
--- a/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html
@@ -30,6 +30,9 @@ tr.exportTo('tr.ui.tracks', function() {
tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
Polymer.dom(this).classList.add('async-slice-group-track');
this.group_ = undefined;
+ // Set the collapse threshold so we don't collapse by default, but the
+ // user can explicitly collapse if they want it.
+ this.defaultToCollapsedWhenSubRowCountMoreThan = 30;
},
addSubTrack_(slices) {
@@ -94,7 +97,8 @@ tr.exportTo('tr.ui.tracks', function() {
* a single track but provide no information themselves.
*/
function stripSlice_(slice) {
- if (slice.subSlices !== undefined && slice.subSlices.length === 1) {
+ if (slice.subSlices !== undefined && slice.subSlices.length === 1
+ && !slice.args) {
const subSlice = slice.subSlices[0];
if (tr.b.math.approximately(subSlice.start, slice.start, 1) &&
tr.b.math.approximately(subSlice.duration, slice.duration, 1)) {
@@ -112,6 +116,9 @@ tr.exportTo('tr.ui.tracks', function() {
function makeLevelSubRows_(slices) {
const rows = [];
const putSlice = (slice, level) => {
+ if (slice.hidden) {
+ return;
+ }
while (rows.length <= level) {
rows.push([]);
}
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/alert_groups.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/alert_groups.html
new file mode 100644
index 00000000000..b7d1382c3ac
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/alert_groups.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ // All alert groups used in TBMv2 metrics. If you add a new group, add it
+ // here first to make sure you're not accidentally reusing a name.
+ // The keys and values are same here by convention.
+ const ALERT_GROUPS = {
+ // For metrics measuring cpu usage in general, like cpu time percentage
+ // metric.
+ CPU_USAGE: 'cpu_usage',
+ // For paint related loading metrics like First Contentful Paint and Largest
+ // Contentful Paint
+ LOADING_PAINT: 'loading_paint',
+ // For interactivity related loading metrics like Time to Interactive and
+ // Total Blocking Time.
+ LOADING_INTERACTIVITY: 'loading_interactivity',
+ // For layour related metrics like Cumulative Layout Shift.
+ LOADING_LAYOUT: 'loading_layout',
+ };
+
+ return {
+ ALERT_GROUPS,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py
index e37d85753b4..2605e6c343d 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py
@@ -53,10 +53,10 @@ class Breakdown(diagnostic.Diagnostic):
return breakdown
@staticmethod
- def FromDict(d):
+ def FromDict(dct):
result = Breakdown()
- result._color_scheme = d.get('colorScheme')
- for name, value in d['values'].items():
+ result._color_scheme = dct.get('colorScheme')
+ for name, value in dct['values'].items():
if value in ['NaN', 'Infinity', '-Infinity']:
value = float(value)
result.Set(name, value)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py
index 1fe181319fb..eb30a71efe8 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py
@@ -1,16 +1,17 @@
# Copyright 2018 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 __future__ import absolute_import
import datetime
+from tracing.value import histogram
from tracing.value.diagnostics import diagnostic
class DateRange(diagnostic.Diagnostic):
- __slots__ = '_range',
+ __slots__ = ('_range',)
def __init__(self, ms):
- from tracing.value import histogram
super(DateRange, self).__init__()
self._range = histogram.Range()
self._range.AddValue(ms)
@@ -88,4 +89,3 @@ class DateRange(diagnostic.Diagnostic):
def AddDiagnostic(self, other_diagnostic):
self._range.AddRange(other_diagnostic._range)
-
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py
index 457c3fb9645..074bfd0175d 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py
@@ -15,7 +15,7 @@ from tracing.value.diagnostics import all_diagnostics
class Diagnostic(object):
- __slots__ = '_guid',
+ __slots__ = ('_guid',)
# Ensure that new subclasses remember to specify __slots__ in order to prevent
# regressing memory consumption:
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py
index 31966b02b66..8fd24f5e6c2 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import json
+import six
from tracing.proto import histogram_proto
from tracing.value.diagnostics import diagnostic
@@ -106,12 +107,13 @@ class GenericSet(diagnostic.Diagnostic):
for value_json in d.values:
try:
values.append(json.loads(value_json))
- except (TypeError, ValueError):
- raise TypeError('The value %s is not valid JSON. You cannot pass naked '
- 'strings as a GenericSet value, for instance; they '
- 'have to be quoted. Therefore, 1234 is a valid value '
- '(int), "abcd" is a valid value (string), but abcd is '
- 'not valid.' % value_json)
+ except (TypeError, ValueError) as e:
+ six.raise_from(
+ TypeError('The value %s is not valid JSON. You cannot pass naked '
+ 'strings as a GenericSet value, for instance; they '
+ 'have to be quoted. Therefore, 1234 is a valid value '
+ '(int), "abcd" is a valid value (string), but abcd is '
+ 'not valid.' % value_json), e)
return GenericSet(values)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py
index be422e9f788..590ea5c22cc 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py
@@ -11,7 +11,7 @@ from tracing.value.diagnostics import diagnostic
class RelatedEventSet(diagnostic.Diagnostic):
- __slots__ = '_events_by_stable_id',
+ __slots__ = ('_events_by_stable_id',)
def __init__(self, events=()):
super(RelatedEventSet, self).__init__()
@@ -47,9 +47,9 @@ class RelatedEventSet(diagnostic.Diagnostic):
return events
@staticmethod
- def FromDict(d):
+ def FromDict(dct):
result = RelatedEventSet()
- for event in d['events']:
+ for event in dct['events']:
result.Add(event)
return result
@@ -68,7 +68,7 @@ class RelatedEventSet(diagnostic.Diagnostic):
for e in self]
def _AsDictInto(self, d):
- d['events'] = [event for event in self]
+ d['events'] = list(self)
def _AsProto(self):
raise NotImplementedError()
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py
index c644da95bf3..7f17b9890b0 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py
@@ -10,7 +10,7 @@ from tracing.value.diagnostics import diagnostic
class RelatedNameMap(diagnostic.Diagnostic):
- __slots__ = '_map',
+ __slots__ = ('_map',)
def __init__(self, entries=None):
super(RelatedNameMap, self).__init__()
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py
index e3087e5719f..ca975908acc 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py
@@ -25,11 +25,13 @@ class _Info(object):
return self._entry_type
+ALERT_GROUPING = _Info('alertGrouping', 'GenericSet', str)
ANGLE_REVISIONS = _Info('angleRevisions', 'GenericSet', str)
ARCHITECTURES = _Info('architectures', 'GenericSet', str)
BENCHMARKS = _Info('benchmarks', 'GenericSet', str)
BENCHMARK_START = _Info('benchmarkStart', 'DateRange')
BENCHMARK_DESCRIPTIONS = _Info('benchmarkDescriptions', 'GenericSet', str)
+BOT_ID = _Info('botId', 'GenericSet', str)
BOTS = _Info('bots', 'GenericSet', str)
BUG_COMPONENTS = _Info('bugComponents', 'GenericSet', str)
BUILD_URLS = _Info('buildUrls', 'GenericSet', str)
@@ -54,6 +56,7 @@ MASTERS = _Info('masters', 'GenericSet', str)
MEMORY_AMOUNTS = _Info('memoryAmounts', 'GenericSet', int)
OS_NAMES = _Info('osNames', 'GenericSet', str)
OS_VERSIONS = _Info('osVersions', 'GenericSet', str)
+OS_DETAILED_VERSIONS = _Info('osDetailedVersions', 'GenericSet', str)
OWNERS = _Info('owners', 'GenericSet', str)
POINT_ID = _Info('pointId', 'GenericSet', int)
PRODUCT_VERSIONS = _Info('productVersions', 'GenericSet', str)
@@ -70,7 +73,16 @@ TRACE_URLS = _Info('traceUrls', 'GenericSet', str)
V8_COMMIT_POSITIONS = _Info('v8CommitPositions', 'DateRange')
V8_REVISIONS = _Info('v8Revisions', 'GenericSet', str)
WEBRTC_REVISIONS = _Info('webrtcRevisions', 'GenericSet', str)
-WEBRTC_INTERNAL_REVISIONS = _Info('webrtcInternalRevisions', 'GenericSet', str)
+WEBRTC_INTERNAL_SIRIUS_REVISIONS = _Info(
+ 'webrtcInternalSiriusRevisions', 'GenericSet', str)
+WEBRTC_INTERNAL_VEGA_REVISIONS = _Info(
+ 'webrtcInternalVegaRevisions', 'GenericSet', str)
+WEBRTC_INTERNAL_CANOPUS_REVISIONS = _Info(
+ 'webrtcInternalCanopusRevisions', 'GenericSet', str)
+WEBRTC_INTERNAL_ARCTURUS_REVISIONS = _Info(
+ 'webrtcInternalArcturusRevisions', 'GenericSet', str)
+WEBRTC_INTERNAL_RIGEL_REVISIONS = _Info(
+ 'webrtcInternalRigelRevisions', 'GenericSet', str)
def _CreateCachedInfoTypes():
@@ -86,6 +98,7 @@ def GetTypeForName(name):
info = _CACHED_INFO_TYPES.get(name)
if info:
return info.type
+ return None
def AllInfos():
for info in _CACHED_INFO_TYPES.values():
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html
index e1f7c686d23..b25f946ec6d 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html
@@ -17,12 +17,14 @@ tr.exportTo('tr.v.d', function() {
// Diagnostics that are produced outside of metrics (e.g. by telemetry) use
// reserved names.
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},
+ BOT_ID: {name: 'botId', 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},
@@ -32,7 +34,7 @@ tr.exportTo('tr.v.d', function() {
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},
+ 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},
@@ -50,6 +52,7 @@ tr.exportTo('tr.v.d', function() {
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},
+ OS_DETAILED_VERSIONS: {name: 'osDetailedVersions', 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},
@@ -66,8 +69,16 @@ tr.exportTo('tr.v.d', function() {
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},
+ WEBRTC_INTERNAL_SIRIUS_REVISIONS: {
+ name:'webrtcInternalSiriusRevisions', type: tr.v.d.GenericSet},
+ WEBRTC_INTERNAL_VEGA_REVISIONS: {
+ name:'webrtcInternalVegaRevisions', type: tr.v.d.GenericSet},
+ WEBRTC_INTERNAL_CANOPUS_REVISIONS: {
+ name:'webrtcInternalCanopusRevisions', type: tr.v.d.GenericSet},
+ WEBRTC_INTERNAL_ARCTURUS_REVISIONS: {
+ name:'webrtcInternalArcturusRevisions', type: tr.v.d.GenericSet},
+ WEBRTC_INTERNAL_RIGEL_REVISIONS: {
+ name:'webrtcInternalRigelRevisions', type: tr.v.d.GenericSet},
};
const RESERVED_NAMES = {};
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py
index c6de25894d5..db5e20965c4 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py
@@ -16,7 +16,7 @@ except NameError:
class UnmergeableDiagnosticSet(diagnostic.Diagnostic):
- __slots__ = '_diagnostics',
+ __slots__ = ('_diagnostics',)
def __init__(self, diagnostics):
super(UnmergeableDiagnosticSet, self).__init__()
diff --git a/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py b/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py
index 4238c4b8bd4..fae316177a5 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py
@@ -107,7 +107,7 @@ def _ConvertUnit(unit):
# back to checking the histogram units directly, and defaulting to unitless if
# the unit is unrecognized.
legacy_unit = legacy_unit_info.LEGACY_UNIT_INFO.get(unit)
- if legacy_unit != None:
+ if legacy_unit is not None:
return legacy_unit.AsTuple()
if unit in histogram.UNIT_NAMES:
return unit, 1
diff --git a/chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py b/chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py
index 0ffd17b3a4b..9a85031112d 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py
@@ -23,7 +23,7 @@ from tracing_build import render_histograms_viewer
def _IsUserDefinedInstance(obj):
- return str(type(obj)).startswith('<class ')
+ return type(obj).__module__ != six.moves.builtins.__name__
class _HeapProfiler(object):
@@ -199,7 +199,7 @@ def Profile(root, label=None, html_filename=None, html_stream=None,
render_histograms_viewer.RenderHistogramsViewer(
histograms.AsDicts(), html_stream, reset_results, vulcanized_viewer)
else:
- from tracing_build import vulcanize_histograms_viewer
+ from tracing_build import vulcanize_histograms_viewer # pylint: disable=import-outside-toplevel
vulcanize_histograms_viewer.VulcanizeAndRenderHistogramsViewer(
histograms.AsDicts(), html_stream)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py
index e5d1ea8d05b..556ca6c5902 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py
@@ -26,38 +26,41 @@ class HeapProfilerUnitTest(unittest.TestCase):
histograms = heap_profiler.Profile(test_data)
set_size_hist = histograms.GetHistogramNamed('heap:HistogramSet')
- self.assertEquals(set_size_hist.num_values, 1)
+ self.assertEqual(set_size_hist.num_values, 1)
# The exact sizes of python objects can vary between platforms and versions.
self.assertGreater(set_size_hist.sum, 10000)
hist_size_hist = histograms.GetHistogramNamed('heap:Histogram')
- self.assertEquals(hist_size_hist.num_values, 10)
+ self.assertEqual(hist_size_hist.num_values, 10)
self.assertGreater(hist_size_hist.sum, 10000)
related_names = hist_size_hist.diagnostics['types']
- self.assertEquals(related_names.Get('HistogramBin'), 'heap:HistogramBin')
- self.assertEquals(related_names.Get('DiagnosticMap'), 'heap:DiagnosticMap')
+ self.assertEqual(related_names.Get('HistogramBin'), 'heap:HistogramBin')
+ self.assertEqual(related_names.Get('DiagnosticMap'), 'heap:DiagnosticMap')
- properties = hist_size_hist.bins[33].diagnostic_maps[0]['properties']
- types = hist_size_hist.bins[33].diagnostic_maps[0]['types']
+ diagnostic_bin = [
+ hist_bin for hist_bin in hist_size_hist.bins
+ if len(hist_bin.diagnostic_maps)][-1]
+ properties = diagnostic_bin.diagnostic_maps[0]['properties']
+ types = diagnostic_bin.diagnostic_maps[0]['types']
self.assertGreater(len(properties), 3)
self.assertGreater(properties.Get('_bins'), 1000)
- self.assertEquals(len(types), 4)
+ self.assertEqual(len(types), 4)
self.assertGreater(types.Get('HistogramBin'), 1000)
self.assertGreater(types.Get('(builtin types)'), 1000)
bin_size_hist = histograms.GetHistogramNamed('heap:HistogramBin')
- self.assertEquals(bin_size_hist.num_values, 32)
+ self.assertEqual(bin_size_hist.num_values, 32)
self.assertGreater(bin_size_hist.sum, 1000)
diag_map_size_hist = histograms.GetHistogramNamed('heap:DiagnosticMap')
- self.assertEquals(diag_map_size_hist.num_values, 10)
+ self.assertEqual(diag_map_size_hist.num_values, 10)
self.assertGreater(diag_map_size_hist.sum, 1000)
range_size_hist = histograms.GetHistogramNamed('heap:Range')
- self.assertEquals(range_size_hist.num_values, 22)
+ self.assertEqual(range_size_hist.num_values, 22)
self.assertGreater(range_size_hist.sum, 1000)
stats_size_hist = histograms.GetHistogramNamed('heap:RunningStatistics')
- self.assertEquals(stats_size_hist.num_values, 10)
+ self.assertEqual(stats_size_hist.num_values, 10)
self.assertGreater(stats_size_hist.sum, 1000)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram.h b/chromium/third_party/catapult/tracing/tracing/value/histogram.h
index d29eac31de0..ff99d3311fe 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram.h
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram.h
@@ -5,6 +5,7 @@
#include <map>
#include <memory>
#include <string>
+#include <unordered_map>
#include <vector>
#include "tracing/tracing/proto/histogram.pb.h"
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram.html b/chromium/third_party/catapult/tracing/tracing/value/histogram.html
index 0a652d081fd..df47f36c554 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram.html
@@ -12,6 +12,7 @@ found in the LICENSE file.
<link rel="import" href="/tracing/base/unit.html">
<link rel="import" href="/tracing/base/utils.html">
<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
+<link rel="import" href="/tracing/value/diagnostics/reserved_names.html">
<script>
'use strict';
@@ -234,6 +235,9 @@ tr.exportTo('tr.v', function() {
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;
@@ -275,6 +279,26 @@ tr.exportTo('tr.v', function() {
return this.diagnostics_;
}
+ /* Set alert grouping for a Histogram.
+ * See https://go/chromeperf-alert-grouping-dd
+ * @param {Array.< String >=} opt_alertGrouping
+ */
+ 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_;
}
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram.py b/chromium/third_party/catapult/tracing/tracing/value/histogram.py
index d94f1a12327..28863bdda84 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram.py
@@ -150,7 +150,6 @@ def Percentile(ary, percent):
class HistogramError(ValueError):
"""Base execption type for Histogram related exceptions."""
- pass
class InvalidBucketError(HistogramError):
@@ -434,7 +433,7 @@ class RunningStatistics(object):
class DiagnosticMap(dict):
- __slots__ = '_allow_reserved_names',
+ __slots__ = ('_allow_reserved_names',)
def __init__(self, *args, **kwargs):
self._allow_reserved_names = True
@@ -752,8 +751,8 @@ class Histogram(object):
if summary_options:
hist.CustomizeSummaryOptions(summary_options)
if diagnostics:
- for name, diag in diagnostics.items():
- hist.diagnostics[name] = diag
+ for diag_name, diag in diagnostics.items():
+ hist.diagnostics[diag_name] = diag
if not isinstance(samples, list):
samples = [samples]
@@ -824,7 +823,7 @@ class Histogram(object):
upper = PercentFromString(stat_name[8:])
self._summary_options.get('iprs').push(
Range.FromExplicitRange(lower, upper))
- for stat_name in self._summary_options.keys():
+ for stat_name in self._summary_options:
if stat_name in ['percentile', 'iprs']:
continue
self._summary_options[stat_name] = stat_name in statistics_names
@@ -1030,10 +1029,9 @@ class Histogram(object):
continue
if hbin.range.min == -JS_MAX_VALUE:
return hbin.range.max
- elif hbin.range.max == JS_MAX_VALUE:
+ if hbin.range.max == JS_MAX_VALUE:
return hbin.range.min
- else:
- return hbin.range.center
+ return hbin.range.center
return self._bins[len(self._bins) - 1].range.min
def _ResampleMean(self, percent):
@@ -1215,6 +1213,8 @@ class Histogram(object):
return Scalar(self.unit, (self.GetApproximatePercentile(upper) -
self.GetApproximatePercentile(lower)))
+ return None
+
@property
def statistics_scalars(self):
results = {}
@@ -1256,7 +1256,7 @@ class Histogram(object):
dct['maxNumSampleValues'] = self.max_num_sample_values
if self.num_nans:
dct['numNans'] = self.num_nans
- if len(self.nan_diagnostic_maps):
+ if self.nan_diagnostic_maps:
dct['nanDiagnostics'] = [m.AsDict() for m in self.nan_diagnostic_maps]
if self.num_values:
dct['sampleValues'] = list(self.sample_values)
@@ -1268,7 +1268,7 @@ class Histogram(object):
summary_options = {}
any_overridden_summary_options = False
for name, option in self._summary_options.items():
- if name == 'percentile' or name == 'ci':
+ if name in ('percentile', 'ci'):
if len(option) == 0:
continue
elif name == 'iprs':
@@ -1313,8 +1313,8 @@ class Histogram(object):
self._GetAllBinsAsProto(proto.all_bins)
any_overridden_summary_options = any(
- [self._summary_options[k] != DEFAULT_SUMMARY_OPTIONS[k]
- for k in DEFAULT_SUMMARY_OPTIONS])
+ self._summary_options[k] != DEFAULT_SUMMARY_OPTIONS[k]
+ for k in DEFAULT_SUMMARY_OPTIONS)
if any_overridden_summary_options or self._summary_options['percentile']:
# Note: iprs and ci are not supported in the proto format yet.
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html
index c9a36824d73..49f1ecc7e87 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html
@@ -51,26 +51,26 @@ tr.exportTo('tr.v', function() {
* The |view| should have 'display:none' so that it doesn't obnoxiously
* display "zero Histograms" while they are being imported.
*
- * @param {!String} string
+ * @param {!String[]} strings
* @param {!Element} view A histogram-set-view.
* @return {Promise} resolves when |view| is displayed.
*/
- async importHistograms(string, view) {
+ async importHistograms(strings, view) {
this.histograms_ = new tr.v.HistogramSet();
- this.string_ = string;
this.view_ = view;
tr.b.Timing.instant('HistogramImporter', 'string', this.string_.length);
-
- if (this.string_.length > 0) {
+ const loadMark = tr.b.Timing.mark('HistogramImporter', 'loadHistograms');
+ for (const string of strings) {
+ this.string_ = string;
+ this.dataOffset_ = 0;
+ if (this.string_.length == 0) continue;
await this.update_('Loading Histogram 0');
- const loadMark = tr.b.Timing.mark(
- 'HistogramImporter', 'loadHistograms');
- if (!this.findDataStart_()) return;
+ if (!this.findDataStart_()) continue
await this.loadSomeHistograms_();
- loadMark.end();
- tr.b.Timing.instant('HistogramImporter', 'nsPerJson',
- parseInt(1e3 * loadMark.durationMs / this.histograms_.length));
}
+ loadMark.end();
+ tr.b.Timing.instant('HistogramImporter', 'nsPerJson',
+ parseInt(1e3 * loadMark.durationMs / this.histograms_.length));
await this.update_('Displaying Histogram table...');
await this.displayHistograms_();
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_serializer_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_serializer_unittest.py
index 6b834056313..abd40370205 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram_serializer_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_serializer_unittest.py
@@ -41,42 +41,84 @@ class HistogramSerializerUnittest(unittest.TestCase):
hist.diagnostics['hhh'] = generic_set.GenericSet(['ggg'])
hist.AddSample(0, {
'bbb': breakdown.Breakdown.FromEntries({
- 'ccc': 11,
- 'ddd': 31,
+ 'ccc': 100,
+ 'ddd': 200,
}),
'eee': related_event_set.RelatedEventSet([{
'stableId': 'fff',
'title': 'ggg',
- 'start': 3,
- 'duration': 4,
+ 'start': 500,
+ 'duration': 600,
}]),
})
-
data = histogram_serializer.Serialize([hist])
- self.assertEqual(data, [
+
+ serializer_objects = data[0]
+ diagnostics = data[1]
+
+ self.assertIn('Breakdown', diagnostics)
+ self.assertIn('bbb', diagnostics['Breakdown'])
+ _, breakdown_indexes = list(
+ diagnostics['Breakdown']['bbb'].items())[0]
+ name_indexes = serializer_objects[breakdown_indexes[1]]
+ self.assertEqual(
[
- 'aaa',
- [1, [1, 1000.0, 20]],
- '',
- 'ccc',
- 'ddd',
- [3, 4],
- 'ggg',
- 'avg', 'count', 'max', 'min', 'std', 'sum',
- 'lorem ipsum',
- 'a:c',
- 'a:d',
+ serializer_objects[breakdown_indexes[0]],
+ [serializer_objects[i] for i in name_indexes],
+ breakdown_indexes[2],
+ breakdown_indexes[3]
],
- {
- 'Breakdown': {'bbb': {5: [2, 5, 11, 31]}},
- 'GenericSet': {
- 'hhh': {0: 6},
- 'statisticsNames': {1: [7, 8, 9, 10, 11, 12]},
- 'description': {3: 13},
- },
- 'RelatedEventSet': {'eee': {4: [['fff', 6, 3, 4]]}},
- 'RelatedNameMap': {'bbb': {2: [5, 14, 15]}},
- },
+ ['', ['ccc', 'ddd'], 100, 200]
+ )
+
+ self.assertIn('GenericSet', diagnostics)
+ self.assertIn('hhh', diagnostics['GenericSet'])
+ _, added_diagnostic = list(
+ diagnostics['GenericSet']['hhh'].items())[0]
+ self.assertEqual(serializer_objects[added_diagnostic], 'ggg')
+ self.assertIn('statisticsNames', diagnostics['GenericSet'])
+ _, stat_indexes = list(
+ diagnostics['GenericSet']['statisticsNames'].items())[0]
+ self.assertEqual(
+ ['avg', 'count', 'max', 'min', 'std', 'sum'],
+ [serializer_objects[i] for i in stat_indexes]
+ )
+ self.assertIn('description', diagnostics['GenericSet'])
+ _, description_index = list(
+ diagnostics['GenericSet']['description'].items())[0]
+ self.assertEqual(serializer_objects[description_index], 'lorem ipsum')
+
+ self.assertIn('RelatedEventSet', diagnostics)
+ self.assertIn('eee', diagnostics['RelatedEventSet'])
+ _, event_set_values = list(
+ diagnostics['RelatedEventSet']['eee'].items())[0]
+ self.assertEqual(
+ [
+ event_set_values[0][0],
+ serializer_objects[event_set_values[0][1]],
+ event_set_values[0][2],
+ event_set_values[0][3]
+ ],
+ ['fff', 'ggg', 500, 600]
+ )
+
+ self.assertIn('RelatedNameMap', diagnostics)
+ self.assertIn('bbb', diagnostics['RelatedNameMap'])
+ _, relative_name_values = list(
+ diagnostics['RelatedNameMap']['bbb'].items())[0]
+ name_indexes = relative_name_values[0]
+ self.assertEqual(
+ [
+ [serializer_objects[i] for i in serializer_objects[name_indexes]],
+ serializer_objects[relative_name_values[1]],
+ serializer_objects[relative_name_values[2]]
+ ],
+ [['ccc', 'ddd'], 'a:c', 'a:d']
+ )
+
+ histograms = data[2:]
+ self.assertEqual(
+ histograms[0],
[
0,
'count+',
@@ -86,4 +128,4 @@ class HistogramSerializerUnittest(unittest.TestCase):
{0: [1, [None, 4, 5]]},
0,
]
- ])
+ )
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_set.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_set.py
index f9c96032ac7..bed920344b0 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram_set.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_set.py
@@ -5,7 +5,7 @@
import collections
from tracing.proto import histogram_proto
-from tracing.value import histogram as histogram
+from tracing.value import histogram
from tracing.value import histogram_deserializer
from tracing.value.diagnostics import all_diagnostics
from tracing.value.diagnostics import diagnostic
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py
index 7d3111490bd..99e413549ad 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py
@@ -4,6 +4,7 @@
import math
import unittest
+import six
from tracing.proto import histogram_proto
from tracing.value import histogram
@@ -11,6 +12,7 @@ from tracing.value import histogram_set
from tracing.value.diagnostics import date_range
from tracing.value.diagnostics import diagnostic_ref
from tracing.value.diagnostics import generic_set
+from six.moves import zip
def _AddHist(hist_set, name=None, unit=None):
@@ -145,7 +147,7 @@ class HistogramSetUnittest(unittest.TestCase):
hists2 = histogram_set.HistogramSet()
hists2.ImportDicts(ds)
self.assertEqual(len(hists2), 1)
- hist2 = [h for h in hists2][0]
+ hist2 = list(hists2)[0]
self.assertIsInstance(
hist2.diagnostics.get('generic'), generic_set.GenericSet)
@@ -280,10 +282,10 @@ class HistogramSetUnittest(unittest.TestCase):
# The order of the histograms isn't guaranteed.
self.assertEqual(len(hists), 2)
- self.assertItemsEqual(
- [hists[0].name, hists[1].name], ['metric1', 'metric2'])
- self.assertItemsEqual(
- [hists[0].unit, hists[1].unit], ['tsMs', 'sigma_biggerIsBetter'])
+ six.assertCountEqual(
+ self, [hists[0].name, hists[1].name], ['metric1', 'metric2'])
+ six.assertCountEqual(
+ self, [hists[0].unit, hists[1].unit], ['tsMs', 'sigma_biggerIsBetter'])
def testSimpleFieldsFromProto(self):
hist_set = histogram_proto.Pb2().HistogramSet()
@@ -428,11 +430,19 @@ class HistogramSetUnittest(unittest.TestCase):
# See the histogram spec in docs/histogram-set-json-format.md.
# Serializing to proto leads to funny rounding errors.
- self.assertEqual(
- parsed_hist.statistics_names,
- set(['pct_099_0000009537', 'pct_089_9999976158', 'pct_094_9999988079',
- 'nans', 'avg', 'geometricMean']),
- msg=str(parsed_hist.statistics_names))
+ # The rounding works different from Python 2 and Python 3.
+ actual_statistics_names = sorted(parsed_hist.statistics_names)
+ expected_statistics_names = sorted(
+ ['pct_099_0000009537', 'pct_089_9999976158', 'pct_094_9999988079',
+ 'nans', 'avg', 'geometricMean']
+ )
+ self.assertTrue(
+ all(actual[:17] == expected[:17]
+ for (actual, expected)
+ in zip(actual_statistics_names, expected_statistics_names)),
+ msg='Statistics names are different. Expected: %s. Actual: %s ' % (
+ expected_statistics_names, actual_statistics_names)
+ )
def testImportSharedDiagnosticsFromProto(self):
guid1 = 'f7f17394-fa4a-481e-86bd-a82cd55935a7'
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_test.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_test.html
index 8b2e9d8c6a4..28ec21885a5 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_test.html
@@ -6,6 +6,7 @@ found in the LICENSE file.
-->
<link rel="import" href="/tracing/base/assert_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/alert_groups.html">
<link rel="import" href="/tracing/value/diagnostics/generic_set.html">
<link rel="import" href="/tracing/value/histogram.html">
@@ -858,5 +859,61 @@ tr.b.unittest.testSuite(function() {
tr.b.assertRangeEquals(
mergedIprs[2], tr.b.math.Range.fromExplicitRange(0.2, 0.8));
});
+
+ test('alertGrouping', function() {
+ const hist0 = new tr.v.Histogram('', unitlessNumber);
+ hist0.setAlertGrouping([tr.v.d.ALERT_GROUPS.CPU_USAGE]);
+ const hist1 = tr.v.Histogram.create('', unitlessNumber, [], {
+ alertGrouping: [tr.v.d.ALERT_GROUPS.LOADING_PAINT]
+ });
+ const hist2 = tr.v.Histogram.create('', unitlessNumber, [], {
+ alertGrouping: [
+ tr.v.d.ALERT_GROUPS.LOADING_PAINT,
+ tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY,
+ ]});
+
+ assert.isTrue(hist0.diagnostics.get('alertGrouping').equals(
+ new tr.v.d.GenericSet([tr.v.d.ALERT_GROUPS.CPU_USAGE])));
+ assert.isTrue(hist1.diagnostics.get('alertGrouping').equals(
+ new tr.v.d.GenericSet([tr.v.d.ALERT_GROUPS.LOADING_PAINT])));
+ assert.isTrue(hist2.diagnostics.get('alertGrouping').equals(
+ new tr.v.d.GenericSet([
+ tr.v.d.ALERT_GROUPS.LOADING_PAINT,
+ tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY])));
+
+ const merged = hist0.clone();
+ merged.addHistogram(hist1);
+ merged.addHistogram(hist2);
+
+ assert.isTrue(merged.diagnostics.get('alertGrouping').equals(
+ new tr.v.d.GenericSet([
+ tr.v.d.ALERT_GROUPS.CPU_USAGE,
+ tr.v.d.ALERT_GROUPS.LOADING_PAINT,
+ tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY])));
+ });
+
+ test('alertGroupingErrors', function() {
+ const hist0 = new tr.v.Histogram('', unitlessNumber);
+
+ // Must be from tr.v.d.ALERT_GROUPS.
+ assert.throws(() => {
+ hist0.setAlertGrouping(['foo']);
+ });
+ assert.throws(() => {
+ tr.v.Histogram.create('', unitlessNumber, [], {
+ alertGrouping: ['foo'],
+ });
+ });
+
+ // Must be an array.
+ assert.throws(() => {
+ hist0.setAlertGrouping(tr.v.d.ALERT_GROUPS.CPU_USAGE);
+ });
+ assert.throws(() => {
+ tr.v.Histogram.create('', unitlessNumber, [], {
+ alertGrouping: tr.v.d.ALERT_GROUPS.CPU_USAGE,
+ });
+ });
+ });
});
</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py
index f7d6578ca29..4b1f2ca102b 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py
@@ -704,8 +704,8 @@ class HistogramUnittest(unittest.TestCase):
self.assertEqual(hist.description, clone.description)
self.assertEqual(len(hist.diagnostics), len(clone.diagnostics))
self.assertEqual(hist.diagnostics['foo'], clone.diagnostics['foo'])
- self.assertEqual(hist.statistics_scalars.keys(),
- clone.statistics_scalars.keys())
+ self.assertEqual(list(hist.statistics_scalars.keys()),
+ list(clone.statistics_scalars.keys()))
self.assertEqual(hist.max_num_sample_values, clone.max_num_sample_values)
class DiagnosticMapUnittest(unittest.TestCase):
@@ -808,4 +808,3 @@ class DiagnosticMapUnittest(unittest.TestCase):
self.assertIs(related_map, diagnostics[1])
self.assertIs(events, diagnostics[2])
self.assertIs(generic2, diagnostics[3])
-
diff --git a/chromium/third_party/catapult/tracing/tracing/value/running_statistics.cc b/chromium/third_party/catapult/tracing/tracing/value/running_statistics.cc
index 786f4765e36..0346def1fdd 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/running_statistics.cc
+++ b/chromium/third_party/catapult/tracing/tracing/value/running_statistics.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <cassert>
+#include <cmath>
namespace catapult {
@@ -16,7 +17,7 @@ void RunningStatistics::Add(double value) {
min_ = std::min(min_, value);
sum_ += value;
- if (value < 0.0) {
+ if (std::islessequal(value, 0.0)) {
meanlogs_valid_ = false;
} else if (meanlogs_valid_) {
meanlogs_ += (std::log(std::abs(value)) - meanlogs_) / count_;
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html
index 71079cdc856..a1d04efa600 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html
@@ -88,7 +88,8 @@ tr.b.unittest.testSuite(function() {
this.addHTMLOutput(span);
});
- test('correlate', function() {
+ // See https://crbug.com/1143376.
+ skipTest('correlate', function() {
const histograms = new tr.v.HistogramSet();
const sample0Breakdown = new tr.v.d.Breakdown();
sample0Breakdown.set('a', 5);
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html
index 741fc07f58e..cb9785e1969 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html
@@ -41,13 +41,7 @@ tr.exportTo('tr.v.ui', function() {
' 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;
+ return typeInfo.metadata.elementName;
}
/**
@@ -61,6 +55,9 @@ tr.exportTo('tr.v.ui', function() {
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;
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html
index 6bddec81aa6..e8632b513d3 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html
@@ -13,7 +13,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
test('link_tuple', function() {
const diagnostic = new tr.v.d.GenericSet([
['label', 'http://example.com/'],
@@ -94,7 +95,7 @@ tr.b.unittest.testSuite(function() {
test('traceUrls', function() {
const urls = [
- 'https://console.developers.google.com/m/cloudstorage/b/chromium-telemetry/o/c.html',
+ 'https://storage.cloud.google.com/chromium-telemetry/c.html',
'file://d/e/f.html',
];
const span = tr.v.ui.createDiagnosticSpan(
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html
index bb4e1e11ed0..96473519609 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html
@@ -28,6 +28,37 @@ tr.b.unittest.testSuite(() => {
return histogram;
}
+ test('importZeroHistogramsEmptyArray', async function() {
+ const loadingEl = document.createElement('div');
+ this.addHTMLOutput(loadingEl);
+ const importer = new tr.v.HistogramImporter(loadingEl);
+
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ view.style.display = 'none';
+ this.addHTMLOutput(view);
+
+ await importer.importHistograms([], view);
+
+ assert.strictEqual('block', view.style.display);
+ assert.strictEqual(undefined, view.histograms);
+ });
+
+ test('importZeroHistogramsEmptyString', async function() {
+ const loadingEl = document.createElement('div');
+ this.addHTMLOutput(loadingEl);
+ const importer = new tr.v.HistogramImporter(loadingEl);
+ const histogramData = '';
+
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ view.style.display = 'none';
+ this.addHTMLOutput(view);
+
+ await importer.importHistograms([histogramData], view);
+
+ assert.strictEqual('block', view.style.display);
+ assert.strictEqual(undefined, view.histograms);
+ });
+
test('importZeroHistograms', async function() {
const loadingEl = document.createElement('div');
this.addHTMLOutput(loadingEl);
@@ -38,7 +69,7 @@ tr.b.unittest.testSuite(() => {
view.style.display = 'none';
this.addHTMLOutput(view);
- await importer.importHistograms(histogramData, view);
+ await importer.importHistograms([histogramData], view);
assert.strictEqual('block', view.style.display);
assert.strictEqual(undefined, view.histograms);
@@ -56,7 +87,7 @@ tr.b.unittest.testSuite(() => {
view.style.display = 'none';
this.addHTMLOutput(view);
- await importer.importHistograms(histogramData, view);
+ await importer.importHistograms([histogramData], view);
assert.strictEqual('none', loadingEl.style.display);
assert.strictEqual('block', view.style.display);
@@ -67,7 +98,31 @@ tr.b.unittest.testSuite(() => {
assert.deepEqual([42], histogram.sampleValues);
});
- test('importNHistogram', async function() {
+ test('importOneHistogramAndEmptyStrings', async function() {
+ const loadingEl = document.createElement('div');
+ this.addHTMLOutput(loadingEl);
+ const importer = new tr.v.HistogramImporter(loadingEl);
+
+ const hist = createHistogram(42);
+ const histogramDataArray = [
+ '', '\n' + JSON.stringify(hist.asDict()) + '\n', '\n', ''];
+
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ view.style.display = 'none';
+ this.addHTMLOutput(view);
+
+ await importer.importHistograms(histogramDataArray, view);
+
+ assert.strictEqual('none', loadingEl.style.display);
+ assert.strictEqual('block', view.style.display);
+ assert.lengthOf(view.histograms, 1);
+ const histogram = view.histograms.getHistogramNamed('name<42>');
+ assert.strictEqual(kHtmlString, tr.b.getOnlyElement(
+ histogram.diagnostics.get('html')));
+ assert.deepEqual([42], histogram.sampleValues);
+ });
+
+ test('importNHistogramsSingleString', async function() {
const loadingEl = document.createElement('div');
this.addHTMLOutput(loadingEl);
const importer = new tr.v.HistogramImporter(loadingEl);
@@ -84,7 +139,39 @@ tr.b.unittest.testSuite(() => {
view.style.display = 'none';
this.addHTMLOutput(view);
- await importer.importHistograms(histogramData, view);
+ await importer.importHistograms([histogramData], view);
+
+ assert.strictEqual('none', loadingEl.style.display);
+ assert.strictEqual('block', view.style.display);
+ assert.lengthOf(view.histograms, kNofHistograms);
+ for (let i = 0; i < kNofHistograms; i++) {
+ const id = kNofHistograms * 100 + i;
+ const histogram = view.histograms.getHistogramNamed('name<' + id + '>');
+ assert.strictEqual(kHtmlString, tr.b.getOnlyElement(
+ histogram.diagnostics.get('html')));
+ assert.deepEqual([id], histogram.sampleValues);
+ }
+ });
+
+ test('importNHistogramsSeparateStrings', async function() {
+ const loadingEl = document.createElement('div');
+ this.addHTMLOutput(loadingEl);
+ const importer = new tr.v.HistogramImporter(loadingEl);
+
+ const kNofHistograms = 1000;
+ let histogramDataArray = ['', '\n' ];
+ for (let i = 0; i < kNofHistograms; i++) {
+ const id = kNofHistograms * 100 + i;
+ const histogram = createHistogram(id);
+ histogramDataArray.push(
+ '\n' + JSON.stringify(histogram.asDict()) + '\n');
+ }
+
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ view.style.display = 'none';
+ this.addHTMLOutput(view);
+
+ await importer.importHistograms(histogramDataArray, view);
assert.strictEqual('none', loadingEl.style.display);
assert.strictEqual('block', view.style.display);
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html
index 9783059ccbe..236a2b337ac 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html
@@ -134,7 +134,8 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(showAll.checked, false);
});
- test('controlShowAll', function() {
+ // See https://crbug.com/1143376.
+ skipTest('controlShowAll', function() {
const controls = buildControls(this);
const showAll = tr.ui.b.findDeepElementMatchingPredicate(
controls, e => e.id === 'show_all');
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html
index b4cb1a54020..68c080876a8 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html
@@ -221,6 +221,9 @@ tr.exportTo('tr.v.ui', function() {
const scalarA = cellA.getStatisticScalar(statisticA, referenceCellA);
if (scalarA) {
valueA = scalarA.value;
+ if (scalarA.unit.unitName == "normalizedPercentageDelta_smallerIsBetter") {
+ valueA = -valueA;
+ }
}
}
@@ -232,6 +235,9 @@ tr.exportTo('tr.v.ui', function() {
const scalarB = cellB.getStatisticScalar(statisticB, referenceCellB);
if (scalarB) {
valueB = scalarB.value;
+ if (scalarB.unit.unitName == "normalizedPercentageDelta_smallerIsBetter") {
+ valueB = -valueB;
+ }
}
}
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html
index f8d76afc72b..480a96dfe7c 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html
@@ -213,7 +213,8 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(baseTable.sortColumnIndex, 1);
});
- test('controlSortColumnIndex', async function() {
+ // See https://crbug.com/1143376.
+ skipTest('controlSortColumnIndex', async function() {
const histograms = new tr.v.HistogramSet();
histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
histograms.createHistogram('b', tr.b.Unit.byName.count, [2]);
@@ -243,7 +244,8 @@ tr.b.unittest.testSuite(function() {
await table.viewState.update({sortDescending: false});
});
- test('controlSortDescending', async function() {
+ // See https://crbug.com/1143376.
+ skipTest('controlSortDescending', async function() {
const histograms = new tr.v.HistogramSet();
histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
histograms.createHistogram('b', tr.b.Unit.byName.count, [2]);
@@ -440,7 +442,8 @@ tr.b.unittest.testSuite(function() {
assert.lengthOf(getTableCells(table), 1);
});
- test('controlRowExpanded', async function() {
+ // See https://crbug.com/1143376.
+ skipTest('controlRowExpanded', async function() {
const histograms = new tr.v.HistogramSet();
const aHist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
aHist.diagnostics.set(tr.v.d.RESERVED_NAMES.STORIES,
@@ -1184,7 +1187,8 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual('-90.0%', barContent.textContent);
});
- test('requestSelectionChange', async function() {
+ // See https://crbug.com/1143376.
+ skipTest('requestSelectionChange', async function() {
const histograms = new tr.v.HistogramSet();
const barHist = histograms.createHistogram(
'bar', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [1], {
@@ -1395,7 +1399,8 @@ tr.b.unittest.testSuite(function() {
table, e => e.textContent === '(missing)'));
});
- test('instantiate_1x1', async function() {
+ // See https://crbug.com/1143376.
+ skipTest('instantiate_1x1', async function() {
const histograms = new tr.v.HistogramSet();
const hist = histograms.createHistogram(
'foo', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html
index 2ca360b3348..5e3b0163744 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html
@@ -241,7 +241,8 @@ tr.b.unittest.testSuite(function() {
this.addHTMLOutput(span);
});
- test('breakdownUnit', async function() {
+ // See https://crbug.com/1143376.
+ skipTest('breakdownUnit', async function() {
const root = new tr.v.Histogram('root', tr.b.Unit.byName.sizeInBytes);
const sampleBreakdown = new tr.v.d.Breakdown();
sampleBreakdown.set('x', 30 << 20);
@@ -266,7 +267,8 @@ tr.b.unittest.testSuite(function() {
span, e => e.textContent === '70.0 MiB'));
});
- test('diagnosticsTabs', async function() {
+ // See https://crbug.com/1143376.
+ skipTest('diagnosticsTabs', async function() {
const span = document.createElement('tr-v-ui-histogram-span');
span.build(tr.v.Histogram.create(
'', tr.b.Unit.byName.count, [
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html
index b0058a3c97b..81c99544388 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html
@@ -12,7 +12,8 @@ found in the LICENSE file.
<script>
'use strict';
-tr.b.unittest.testSuite(function() {
+// See https://crbug.com/1143376.
+tr.b.unittest.skippedTestSuite(function() {
test('instantiate_RelatedEventSet0', function() {
const diagnostic = new tr.v.d.RelatedEventSet();
const span = tr.v.ui.createDiagnosticSpan(diagnostic);
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html
index ccb3f61d6f4..a4fdc85aaac 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html
@@ -29,7 +29,8 @@ tr.b.unittest.testSuite(function() {
is: 'tr-v-ui-scalar-context-controller-mock-host'
});
- test('getScalarContextControllerForElement', function() {
+ // See https://crbug.com/1143376.
+ skipTest('getScalarContextControllerForElement', function() {
const root = document.createElement('div');
Polymer.dom(document.body).appendChild(root);
try {
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html
index 56ca6917d71..403b3cd10c2 100644
--- a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html
@@ -284,7 +284,8 @@ tr.b.unittest.testSuite(function() {
{expectedColor: 'rgb(255, 0, 0)'});
});
- test('createScalarSpan', function() {
+ // See https://crbug.com/1143376.
+ skipTest('createScalarSpan', function() {
// No config.
let span = tr.v.ui.createScalarSpan(
new Scalar(Unit.byName.powerInWatts, 3.14));
@@ -477,7 +478,8 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(rectA.height, rectB.height);
});
- test('respectCurrentDisplayUnit', function() {
+ // See https://crbug.com/1143376.
+ skipTest('respectCurrentDisplayUnit', function() {
try {
Unit.currentTimeDisplayMode = tr.b.TimeDisplayModes.ns;
@@ -514,7 +516,8 @@ tr.b.unittest.testSuite(function() {
expectation.classList || []);
}
- test('customContextRange', function() {
+ // See https://crbug.com/1143376.
+ skipTest('customContextRange', function() {
const div = document.createElement('div');
div.style.width = '101px'; // One extra pixel for sparkline border.
this.addHTMLOutput(div);
@@ -603,7 +606,8 @@ tr.b.unittest.testSuite(function() {
assert.strictEqual(tr.v.ui.createScalarSpan(), '');
});
- test('contextControllerChanges', function() {
+ // See https://crbug.com/1143376.
+ skipTest('contextControllerChanges', function() {
const div = document.createElement('div');
div.style.width = '101px'; // One extra pixel for sparkline border.
this.addHTMLOutput(div);
@@ -721,7 +725,8 @@ tr.b.unittest.testSuite(function() {
checkSparkline(s1, {left: 0, width: 51, classList: ['positive']});
});
- test('deltaSparkline_noImprovementDirection', function() {
+ // See https://crbug.com/1143376.
+ skipTest('deltaSparkline_noImprovementDirection', function() {
const div = document.createElement('div');
div.style.width = '101px'; // One extra pixel for sparkline border.
this.addHTMLOutput(div);
@@ -781,7 +786,8 @@ tr.b.unittest.testSuite(function() {
checkSparkline(span8, {left: 0, width: 26, classList: ['positive']});
});
- test('deltaSparkline_smallerIsBetter', function() {
+ // See https://crbug.com/1143376.
+ skipTest('deltaSparkline_smallerIsBetter', function() {
const div = document.createElement('div');
div.style.width = '101px'; // One extra pixel for sparkline border.
this.addHTMLOutput(div);
@@ -842,7 +848,8 @@ tr.b.unittest.testSuite(function() {
checkSparkline(span8, {left: 0, width: 76, classList: ['better']});
});
- test('deltaSparkline_biggerIsBetter', function() {
+ // See https://crbug.com/1143376.
+ skipTest('deltaSparkline_biggerIsBetter', function() {
const div = document.createElement('div');
div.style.width = '101px'; // One extra pixel for sparkline border.
this.addHTMLOutput(div);
@@ -902,7 +909,8 @@ tr.b.unittest.testSuite(function() {
checkSparkline(span8, {left: 0, width: 101, classList: ['worse']});
});
- test('classListChanges', function() {
+ // See https://crbug.com/1143376.
+ skipTest('classListChanges', function() {
const div = document.createElement('div');
div.style.width = '200px';
this.addHTMLOutput(div);
diff --git a/chromium/third_party/catapult/tracing/tracing_build/check_common.py b/chromium/third_party/catapult/tracing/tracing_build/check_common.py
index 28dd49edc2c..9067fe517dc 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/check_common.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/check_common.py
@@ -42,8 +42,8 @@ Current listing:
Correct listing:
{4}\n\n'''.format(group_name, src_file, mismatch, what_is, what_should_be)
- else:
- return ''
+
+ return ''
def GetKnownFiles():
@@ -55,8 +55,8 @@ def GetKnownFiles():
absolute_filenames = m.GetAllDependentFilenamesRecursive(
include_raw_scripts=False)
- return list(set([os.path.relpath(f, project.tracing_root_path)
- for f in absolute_filenames]))
+ return list({os.path.relpath(f, project.tracing_root_path)
+ for f in absolute_filenames})
def CheckCommon(file_name, listed_files):
diff --git a/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py
index 7ebe3ddc861..0fccf2b7f3e 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py
@@ -4,15 +4,10 @@
import unittest
import shutil
-import sys
import tempfile
-if sys.version_info < (3,):
- from tracing_build import generate_about_tracing_contents
+from tracing_build import generate_about_tracing_contents
-
-@unittest.skipIf(sys.version_info >= (3,),
- 'py_vulcanize is not ported to python3')
class GenerateAboutTracingContentsUnittTest(unittest.TestCase):
def testSmoke(self):
diff --git a/chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html b/chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html
index 054f21b8fc0..a37f35ce515 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html
+++ b/chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html
@@ -59,8 +59,10 @@ ga('set', 'historyImportTask', null);
const view = document.getElementById('histograms');
const locus = new tr.v.ui.HistogramSetLocation();
- const data = jsonData.childNodes[0].textContent;
- await importer.importHistograms(data, view);
+ // Extract all comment nodes inside jsonData.
+ const strings = Array.prototype.map.call(
+ jsonData.childNodes, each => each.textContent);
+ await importer.importHistograms(strings, view);
await locus.build(view.viewState);
// Free the objects and DOM referenced by the importer.
diff --git a/chromium/third_party/catapult/tracing/tracing_build/html2trace.py b/chromium/third_party/catapult/tracing/tracing_build/html2trace.py
index a5b17544e64..6032084edb4 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/html2trace.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/html2trace.py
@@ -55,7 +55,10 @@ def CopyTraceDataFromHTMLFilePath(html_file_handle, trace_path,
saved_path = trace_path if i == 0 else '%s.%d' % (trace_path, i)
saved_paths.append(saved_path)
with open(saved_path, 'wb' if gzipped_output else 'w') as trace_file:
- trace_file.write(trace_data.read())
+ if gzipped_output:
+ trace_file.write(trace_data.read())
+ else:
+ trace_file.write(trace_data.read().decode("utf-8"))
return saved_paths
@@ -83,26 +86,23 @@ def _ExtractTraceDataFromHTMLFile(html_file_handle, unzip_data=True):
if unzip_data:
return list(map(_UnzipFileIfNecessary, decoded_data_list))
- else:
- return list(map(_ZipFileIfNecessary, decoded_data_list))
+ return list(map(_ZipFileIfNecessary, decoded_data_list))
def _UnzipFileIfNecessary(original_file):
if _IsFileZipped(original_file):
return gzip.GzipFile(fileobj=original_file)
- else:
- return original_file
+ return original_file
def _ZipFileIfNecessary(original_file):
if _IsFileZipped(original_file):
return original_file
- else:
- zipped_file = io.BytesIO()
- with gzip.GzipFile(fileobj=zipped_file, mode='wb') as gzip_wrapper:
- gzip_wrapper.write(original_file.read())
- zipped_file.seek(0)
- return zipped_file
+ zipped_file = io.BytesIO()
+ with gzip.GzipFile(fileobj=zipped_file, mode='wb') as gzip_wrapper:
+ gzip_wrapper.write(original_file.read())
+ zipped_file.seek(0)
+ return zipped_file
def _IsFileZipped(f):
diff --git a/chromium/third_party/catapult/tracing/tracing_build/merge_traces.py b/chromium/third_party/catapult/tracing/tracing_build/merge_traces.py
index df1029a8805..5294a7ea412 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/merge_traces.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/merge_traces.py
@@ -10,6 +10,7 @@ import argparse
import codecs
import collections
import gzip
+import io
import itertools
import json
import logging
@@ -93,11 +94,12 @@ class IdMap(object):
assert 'id' not in items # ID is set according to the path.
for key, value in items.items():
value_set = self._items[key]
- if (isinstance(value, collections.Iterable) and
+ if (isinstance(value, collections.abc.Iterable) and
not isinstance(value, StringTypes)):
value_set.update(value)
else:
value_set.add(value)
+ return None
def MapEntry(self, source, path):
"""Map an source-specific entry ID path to a canonical entry ID path.
@@ -288,9 +290,8 @@ class IdMap(object):
cls_name = type(self).__name__
if self._depth == 0:
return '%s root' % cls_name
- else:
- return '%s %s entry(%s)' % (cls_name, self.LEVELS[self._depth - 1].name,
- self._items)
+ return '%s %s entry(%s)' % (cls_name, self.LEVELS[self._depth - 1].name,
+ self._items)
class ProcessIdMap(IdMap):
@@ -310,19 +311,18 @@ def LoadTrace(filename):
logging.info('Loading trace %r...', filename)
if filename.endswith(HTML_FILENAME_SUFFIX):
return LoadHTMLTrace(filename)
- elif filename.endswith(GZIP_FILENAME_SUFFIX):
+ if filename.endswith(GZIP_FILENAME_SUFFIX):
with gzip.open(filename, 'rb') as f:
return json.load(f)
- else:
- with open(filename, 'r') as f:
- return json.load(f)
+ with open(filename, 'r') as f:
+ return json.load(f)
def LoadHTMLTrace(filename):
"""Load a trace from a vulcanized HTML trace file."""
trace_components = collections.defaultdict(list)
- with open(filename) as file_handle:
+ with io.open(filename, 'r', encoding='utf-8') as file_handle:
for sub_trace in html2trace.ReadTracesFromHTMLFile(file_handle):
for name, component in TraceAsDict(sub_trace).items():
trace_components[name].append(component)
@@ -406,8 +406,7 @@ def MergeComponents(component_name, components_by_filename):
"""Merge a component of multiple JSON traces into a single component."""
if component_name == 'traceEvents':
return MergeTraceEvents(components_by_filename)
- else:
- return MergeGenericTraceComponents(component_name, components_by_filename)
+ return MergeGenericTraceComponents(component_name, components_by_filename)
def MergeTraceEvents(events_by_filename):
@@ -645,7 +644,7 @@ def MergeGenericTraceComponents(component_name, components_by_filename):
provided value (in some trace).
"""
components = list(components_by_filename.values())
- first_component = next(components)
+ first_component = next(iter(components))
if not all(c == first_component for c in components):
logging.warning(
'Values of trace component %r differ across the provided traces. '
diff --git a/chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py
index 34e05571112..c2e73eecf4a 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py
@@ -5,21 +5,17 @@
import json
import os
import shutil
-import sys
import tempfile
import unittest
from tracing.trace_data import trace_data
-if sys.version_info < (3,):
- from tracing_build import merge_traces
+from tracing_build import merge_traces
def _FakeDumpEvent(pid, tid):
return {'ph': 'v', 'ts': 100, 'pid': pid, 'tid': tid, 'args': {'dumps': {}}}
-@unittest.skipIf(sys.version_info >= (3,),
- 'py_vulcanize is not ported to python3')
class MergeTracesTest(unittest.TestCase):
def setUp(self):
self.test_dir = tempfile.mkdtemp()
@@ -46,4 +42,4 @@ class MergeTracesTest(unittest.TestCase):
events = json.load(f)['traceEvents']
# Check that both dumps are found in the merged trace.
dump_pids = [e['pid'] for e in events if e['ph'] == 'v']
- self.assertEquals([1, 2], dump_pids)
+ self.assertEqual([1, 2], dump_pids)
diff --git a/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py b/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py
index a5ad91a4e20..62c2089cf3a 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py
@@ -7,7 +7,9 @@ import logging
import re
_DATA_START = '<div id="histogram-json-data" style="display:none;"><!--'
-_DATA_END = '--!></div>'
+_DATA_SEPARATOR = '--><!--'
+_DATA_END_OLD = '--!></div>'
+_DATA_END = '--></div>'
def ExtractJSON(results_html):
@@ -15,18 +17,22 @@ def ExtractJSON(results_html):
flags = re.MULTILINE | re.DOTALL
start = re.search("^%s" % re.escape(_DATA_START), results_html, flags)
if start is None:
- logging.warn('Could not find histogram data start: %s', _DATA_START)
+ logging.warning('Could not find histogram data start: %s', _DATA_START)
return []
- pattern = '^((%s)|(.*?))$' % re.escape(_DATA_END)
+ pattern = '^((%s|%s)|(.*?))$' % (re.escape(_DATA_END_OLD),
+ re.escape(_DATA_END))
# Find newlines and parse each line as separate JSON data.
for match in re.compile(pattern, flags).finditer(results_html, start.end()+1):
try:
# Check if the end tag in group(2) got a match.
if match.group(2):
return results
- results.append(json.loads(match.group(3)))
+ payload = match.group(3)
+ if payload == _DATA_SEPARATOR:
+ continue
+ results.append(json.loads(payload))
except ValueError:
- logging.warn(
+ logging.warning(
'Found existing results json, but failed to parse it: %s',
match.group(1))
return []
@@ -40,12 +46,13 @@ def ReadExistingResults(results_html):
histogram_dicts = ExtractJSON(results_html)
if not histogram_dicts:
- logging.warn('Failed to extract previous results from HTML output')
+ logging.warning('Failed to extract previous results from HTML output')
return histogram_dicts
def RenderHistogramsViewer(histogram_dicts, output_stream, reset_results=False,
- vulcanized_html=''):
+ vulcanized_html='',
+ max_chunk_size_hint_bytes=100000000):
"""Renders a Histograms viewer to output_stream containing histogram_dicts.
Requires a Histograms viewer to have already been vulcanized.
@@ -66,14 +73,22 @@ def RenderHistogramsViewer(histogram_dicts, output_stream, reset_results=False,
output_stream.write(vulcanized_html)
# Put all the serialized histograms nodes inside an html comment to avoid
- # unecessary stress on html parsing and avoid creating throw-away dom nodes.
+ # unnecessary stress on html parsing and avoid creating throw-away dom nodes.
output_stream.write(_DATA_START)
+
+ chunk_size = 0
for histogram in histogram_dicts:
- hist_json = json.dumps(histogram, separators=(',', ':'))
output_stream.write('\n')
# No escaping is necessary since the data is stored inside an html comment.
# This assumes that {hist_json} doesn't contain an html comment itself.
+ hist_json = json.dumps(histogram, separators=(',', ':'))
output_stream.write(hist_json)
+ chunk_size += len(hist_json) + 1
+ # Start a new comment after {max_chunk_size_hint_bytes} to avoid hitting
+ # V8's max string length. Each comment can be read as individual string.
+ if chunk_size > max_chunk_size_hint_bytes:
+ output_stream.write('\n%s' % _DATA_SEPARATOR)
+ chunk_size = 0
output_stream.write('\n%s\n' % _DATA_END)
# If the output file already existed and was longer than the new contents,
diff --git a/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py
index 48c8dcbe33e..acabbd69df7 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py
@@ -9,6 +9,7 @@ import os
import tempfile
from tracing_build import render_histograms_viewer
+from six.moves import range
class ResultsRendererTest(unittest.TestCase):
@@ -52,6 +53,49 @@ class ResultsRendererTest(unittest.TestCase):
render_histograms_viewer.ReadExistingResults(self.output_stream.read()))
self.assertIn(value0_json, self.GetOutputFileContent())
+ def testBasicWithSeparatorOften(self):
+ data_list = [{'foo': i} for i in range(11)]
+ render_histograms_viewer.RenderHistogramsViewer(
+ [], self.output_stream, False)
+ self.output_stream.seek(0)
+ self.assertCountEqual([], render_histograms_viewer.ReadExistingResults(
+ self.output_stream.read()))
+ # Write payload, forcing a new chunk after ever single item
+ render_histograms_viewer.RenderHistogramsViewer(
+ data_list, self.output_stream, False, max_chunk_size_hint_bytes=1)
+ self.output_stream.seek(0)
+ self.assertCountEqual(
+ data_list,
+ render_histograms_viewer.ReadExistingResults(
+ self.output_stream.read()))
+
+ for data in data_list:
+ data_json = json.dumps(data, separators=(',', ':'))
+ self.assertIn(data_json, self.GetOutputFileContent())
+
+ def testBasicWithSeparator(self):
+ data_list = [{'foo': i} for i in range(11)]
+ render_histograms_viewer.RenderHistogramsViewer(
+ [], self.output_stream, False)
+ self.output_stream.seek(0)
+ self.assertCountEqual([], render_histograms_viewer.ReadExistingResults(
+ self.output_stream.read()))
+ # Write payload, forcing a new chunk after a few items
+ item_json = json.dumps(data_list[2], separators=(',', ':'))
+ render_histograms_viewer.RenderHistogramsViewer(
+ data_list,
+ self.output_stream,
+ False,
+ max_chunk_size_hint_bytes=len(item_json) * 3)
+ self.output_stream.seek(0)
+ self.assertCountEqual(
+ data_list,
+ render_histograms_viewer.ReadExistingResults(
+ self.output_stream.read()))
+ for data in data_list:
+ data_json = json.dumps(data, separators=(',', ':'))
+ self.assertIn(data_json, self.GetOutputFileContent())
+
def testExistingResults(self):
value0 = {'foo': 0}
value0_json = json.dumps(value0, separators=(',', ':'))
diff --git a/chromium/third_party/catapult/tracing/tracing_build/snapdragon2trace.py b/chromium/third_party/catapult/tracing/tracing_build/snapdragon2trace.py
index d0016e0f69d..754ae584312 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/snapdragon2trace.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/snapdragon2trace.py
@@ -47,7 +47,7 @@ def LoadTraces(chrome_trace_filename):
with open(chrome_trace_filename, 'r') as f:
traces.append(json.load(f))
else:
- raise Exception('Unknown trace file suffix: %s', chrome_trace_filename)
+ raise Exception('Unknown trace file suffix: %s' % chrome_trace_filename)
return list(map(_ConvertToDictIfNecessary, traces))
@@ -63,7 +63,7 @@ def WriteTraces(output_filename, traces):
with open(output_filename, 'w') as f:
json.dump(_ConcatTraces(traces), f)
else:
- raise Exception('Unknown trace file suffix: %s', output_filename)
+ raise Exception('Unknown trace file suffix: %s' % output_filename)
def LoadCSV(csv_filename):
@@ -147,7 +147,7 @@ def _ConvertToDictIfNecessary(trace):
def _MetadataEvent(pid, name, value):
if name not in TRACE_METADATA_ARG_NAME_MAP:
- raise Exception('Unknown metadata name: %s', name)
+ raise Exception('Unknown metadata name: %s' % name)
arg_name = TRACE_METADATA_ARG_NAME_MAP[name]
return {
'pid': pid,
diff --git a/chromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py b/chromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py
index b4df42f3924..703c8ecf937 100755
--- a/chromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py
@@ -6,6 +6,7 @@
from __future__ import print_function
+from __future__ import absolute_import
import collections
import gzip
import json
@@ -100,3 +101,4 @@ def Main(argv):
json.dump({'traceEvents': out_events}, fout)
num_bytes_written = fout.tell()
print(' (%s written)' % FormatBytes(num_bytes_written))
+ return 0
diff --git a/chromium/third_party/catapult/tracing/tracing_build/trace2html.py b/chromium/third_party/catapult/tracing/tracing_build/trace2html.py
index 1e9d62fa06a..6fd3027b141 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/trace2html.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/trace2html.py
@@ -75,10 +75,10 @@ class ViewerDataScript(generate.ExtraScript):
def WriteToFile(self, output_file):
output_file.write('<script id="viewer-data" type="%s">\n' % self._mime_type)
compressed_trace = io.BytesIO()
- with gzip.GzipFile(fileobj=compressed_trace, mode='w', mtime=0) as f:
- f.write(self._trace_data_string)
+ with gzip.GzipFile(fileobj=compressed_trace, mode='wb', mtime=0) as f:
+ f.write(self._trace_data_string.encode('utf-8'))
b64_content = base64.b64encode(compressed_trace.getvalue())
- output_file.write(b64_content)
+ output_file.write(b64_content.decode('utf-8'))
output_file.write('\n</script>\n')
@@ -118,9 +118,9 @@ def WriteHTMLForTracesToFile(trace_filenames, output_file, title='',
trace_data_list = []
for filename in trace_filenames:
try:
- with gzip.GzipFile(filename, 'r') as f:
+ with gzip.GzipFile(filename, 'rb') as f:
# If filename is not gzipped, then read() will raise IOError.
- trace_data = f.read()
+ trace_data = f.read().decode('utf-8')
except IOError:
with open(filename, 'r') as f:
trace_data = f.read()
diff --git a/chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py
index 5e14ae3f5d1..c09e0c8c8eb 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py
@@ -4,18 +4,14 @@
import codecs
import gzip
+import io
import os
import shutil
-import sys
import tempfile
import unittest
-if sys.version_info < (3,):
- from tracing_build import trace2html
+from tracing_build import trace2html
-
-@unittest.skipIf(sys.version_info >= (3,),
- 'py_vulcanize is not ported to python3')
class Trace2HTMLTests(unittest.TestCase):
SIMPLE_TRACE_PATH = os.path.join(
os.path.dirname(__file__),
@@ -50,15 +46,16 @@ class Trace2HTMLTests(unittest.TestCase):
# Hash the contents of the output file that was generated from an unzipped
# json input file.
- unzipped_hash = hash(open(output_filename).read())
+ unzipped_hash = hash(
+ io.open(output_filename, 'r', encoding='utf-8').read())
os.unlink(output_filename)
# Gzip SIMPLE_TRACE into |input_filename|.
# trace2html should automatically gunzip it and start building the html from
# the same input as if the input weren't gzipped.
- with gzip.GzipFile(input_filename, mode='w') as input_gzipfile:
- input_gzipfile.write(open(self.SIMPLE_TRACE_PATH).read())
+ with gzip.GzipFile(input_filename, mode='wb') as input_gzipfile:
+ input_gzipfile.write(open(self.SIMPLE_TRACE_PATH).read().encode('utf-8'))
# trace2html-ify the zipped version of SIMPLE_TRACE from the same input
# filename as the unzipped version so that the gzipping process is stable.
@@ -67,7 +64,7 @@ class Trace2HTMLTests(unittest.TestCase):
# Hash the contents of the output file that was generated from the zipped
# json input file.
- zipped_hash = hash(open(output_filename).read())
+ zipped_hash = hash(io.open(output_filename, 'r', encoding='utf-8').read())
# Compare the hashes, not the file contents directly so that, if they are
# different, python shouldn't try to print megabytes of html.
diff --git a/chromium/third_party/catapult/tracing/tracing_build/update_gni.py b/chromium/third_party/catapult/tracing/tracing_build/update_gni.py
index e31487831c7..4151ea7a6ac 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/update_gni.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/update_gni.py
@@ -24,7 +24,7 @@ class BuildFile(object):
def __init__(self, text, file_groups):
self._file_groups = file_groups
- self._tokens = [token for token in self._Tokenize(text)]
+ self._tokens = list(self._Tokenize(text))
def _Tokenize(self, text):
rest = text
diff --git a/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py
index 9d57ed06b96..b602388eb4a 100644
--- a/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py
+++ b/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py
@@ -4,16 +4,11 @@
import codecs
import os
-import sys
import unittest
import tempfile
-if sys.version_info < (3,):
- from tracing_build import vulcanize_trace_viewer
+from tracing_build import vulcanize_trace_viewer
-
-@unittest.skipIf(sys.version_info >= (3,),
- 'py_vulcanize is not ported to python3')
class Trace2HTMLTests(unittest.TestCase):
def testWriteHTMLForTracesToFile(self):
diff --git a/chromium/third_party/catapult/tracing/tracing_examples/trace_viewer_embedder.html b/chromium/third_party/catapult/tracing/tracing_examples/trace_viewer_embedder.html
index af6d9ed637c..47bcd733afc 100644
--- a/chromium/third_party/catapult/tracing/tracing_examples/trace_viewer_embedder.html
+++ b/chromium/third_party/catapult/tracing/tracing_examples/trace_viewer_embedder.html
@@ -47,10 +47,6 @@ function onTraceViewerImportFail() {
let url;
let model;
- // You can set this to true if you want to hide the WebComponentsV0 polyfill
- // warning.
- window.__hideTraceViewerPolyfillWarning = false;
-
function load() {
const req = new XMLHttpRequest();
const isBinary = /[.]gz$/.test(url) || /[.]zip$/.test(url);
diff --git a/chromium/third_party/catapult/tracing/tracing_project.py b/chromium/third_party/catapult/tracing/tracing_project.py
index ce198ce7bd3..85c29bd32ac 100644
--- a/chromium/third_party/catapult/tracing/tracing_project.py
+++ b/chromium/third_party/catapult/tracing/tracing_project.py
@@ -25,7 +25,7 @@ def GetDependencyPaths():
p.catapult_path,
p.py_vulcanize_path,
p.vinn_path,
- p.protobuf_path,
+ p.protobuf_py3_path if sys.version_info[0] >= 3 else p.protobuf_path,
os.path.join(p.catapult_third_party_path, 'WebOb'),
os.path.join(p.catapult_third_party_path, 'Paste'),
os.path.join(p.catapult_third_party_path, 'six'),
@@ -82,6 +82,8 @@ class TracingProject(object):
# the gae_ts_mon protobuf lib for its tests, so let's do the same for tracing.
protobuf_path = os.path.join(
catapult_third_party_path, 'gae_ts_mon', 'gae_ts_mon', 'protobuf')
+ protobuf_py3_path = os.path.join(
+ catapult_third_party_path, 'gae_ts_mon', 'gae_ts_mon', 'protobuf-3.20.0')
tracing_third_party_path = os.path.join(tracing_root_path, 'third_party')
py_vulcanize_path = os.path.join(common_root_path, 'py_vulcanize')
@@ -136,7 +138,7 @@ class TracingProject(object):
self.source_paths.append(self.oboe_path)
def CreateVulcanizer(self):
- from py_vulcanize import project as project_module
+ from py_vulcanize import project as project_module # pylint: disable=import-outside-toplevel
return project_module.Project(self.source_paths)
def IsD8CompatibleFile(self, filename):
@@ -214,4 +216,3 @@ class TracingProject(object):
def GetModuleNameForConfigName(self, config_name):
return 'tracing.ui.extras.%s_config' % config_name
-