diff options
author | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-18 02:54:00 +0000 |
---|---|---|
committer | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-18 02:54:00 +0000 |
commit | b8c7eed238ffa4a47f90df3a077f4ee1daf23569 (patch) | |
tree | 940ac7b9463ce5ad3c7ed8e6cb8c489baa61ed27 | |
parent | 64c0acef7a48f5d45f92c1e9e09ab5614ec5d93d (diff) | |
download | chromium_src-b8c7eed238ffa4a47f90df3a077f4ee1daf23569.zip chromium_src-b8c7eed238ffa4a47f90df3a077f4ee1daf23569.tar.gz chromium_src-b8c7eed238ffa4a47f90df3a077f4ee1daf23569.tar.bz2 |
Telemetry: Limit timeline to action time ranges.
We don't want to measure other traces that will just add
noise. This filters all traces using the action ranges.
We also reset the metric every iteration to ensure no
stale ranges are left in the metric.
BUG=334520
NOTRY=true
No-try since I just tried it and only changed one line (and tested that locally).
Review URL: https://codereview.chromium.org/141573002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245733 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | tools/perf/measurements/thread_times.py | 6 | ||||
-rw-r--r-- | tools/perf/metrics/timeline.py | 57 | ||||
-rw-r--r-- | tools/perf/metrics/timeline_unittest.py | 13 | ||||
-rw-r--r-- | tools/telemetry/telemetry/core/timeline/bounds.py | 9 |
4 files changed, 69 insertions, 16 deletions
diff --git a/tools/perf/measurements/thread_times.py b/tools/perf/measurements/thread_times.py index 2f72fbf..5575cc1 100644 --- a/tools/perf/measurements/thread_times.py +++ b/tools/perf/measurements/thread_times.py @@ -8,7 +8,7 @@ from telemetry.page import page_measurement class ThreadTimes(page_measurement.PageMeasurement): def __init__(self): super(ThreadTimes, self).__init__('smoothness') - self._metric = timeline.ThreadTimesTimelineMetric() + self._metric = None def AddCommandLineOptions(self, parser): parser.add_option('--report-silk-results', action='store_true', @@ -24,12 +24,16 @@ class ThreadTimes(page_measurement.PageMeasurement): return False def WillRunActions(self, page, tab): + self._metric = timeline.ThreadTimesTimelineMetric() self._metric.Start(page, tab) if self.options.report_silk_results: self._metric.results_to_report = timeline.SilkResults if self.options.report_silk_details: self._metric.details_to_report = timeline.SilkDetails + def DidRunAction(self, page, tab, action): + self._metric.AddActionToIncludeInMetric(action) + def DidRunActions(self, page, tab): self._metric.Stop(page, tab) diff --git a/tools/perf/metrics/timeline.py b/tools/perf/metrics/timeline.py index 834aeeb..01cd130 100644 --- a/tools/perf/metrics/timeline.py +++ b/tools/perf/metrics/timeline.py @@ -2,8 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import collections +import itertools from metrics import Metric +from telemetry.core.timeline import bounds from telemetry.page import page_measurement TRACING_MODE = 'tracing-mode' @@ -23,6 +25,8 @@ class TimelineMetric(Metric): self._mode = mode self._model = None self._renderer_process = None + self._actions = [] + self._action_ranges = [] def Start(self, page, tab): """Starts gathering timeline data. @@ -43,11 +47,19 @@ class TimelineMetric(Metric): trace_result = tab.browser.StopTracing() self._model = trace_result.AsTimelineModel() self._renderer_process = self._model.GetRendererProcessFromTab(tab) + self._action_ranges = [ action.GetActiveRangeOnTimeline(self._model) + for action in self._actions ] + # Make sure no action ranges overlap + for combo in itertools.combinations(self._action_ranges, 2): + assert not combo[0].Intersects(combo[1]) else: tab.StopTimelineRecording() self._model = tab.timeline_model self._renderer_process = self._model.GetAllProcesses()[0] + def AddActionToIncludeInMetric(self, action): + self._actions.append(action) + @property def model(self): return self._model @@ -140,14 +152,14 @@ TimelineThreadCategories = { } MatchBySubString = ["IOThread", "CompositorRasterWorker"] -FastPath = ["GPU", - "browser_main", - "browser_compositor", - "renderer_compositor", - "IO"] AllThreads = TimelineThreadCategories.values() NoThreads = [] +FastPathThreads = ["GPU", + "browser_main", + "browser_compositor", + "renderer_compositor", + "IO"] MainThread = ["renderer_main"] FastPathResults = AllThreads FastPathDetails = NoThreads @@ -174,14 +186,15 @@ def ThreadCpuTimeResultName(thread_category): return "thread_" + thread_category + "_cpu_time_per_frame" def ThreadDetailResultName(thread_category, detail): - return "thread_" + thread_category + "|" + detail + return "thread_" + thread_category + "|" + detail class ResultsForThread(object): - def __init__(self, model, name): + def __init__(self, model, action_ranges, name): self.model = model self.toplevel_slices = [] self.all_slices = [] self.name = name + self.action_ranges = action_ranges @property def clock_time(self): @@ -195,14 +208,26 @@ class ResultsForThread(object): # # A thread_duration of 0 is valid, so this only returns 0 if it is None. if x.thread_duration == None: - return 0 + if not x.duration: + continue + else: + return 0 else: res += x.thread_duration return res + def ActionSlices(self, slices): + slices_in_actions = [] + for event in slices: + for action_range in self.action_ranges: + if action_range.Contains(bounds.Bounds.CreateFromEvent(event)): + slices_in_actions.append(event) + break + return slices_in_actions + def AppendThreadSlices(self, thread): - self.all_slices.extend(thread.all_slices) - self.toplevel_slices.extend(thread.toplevel_slices) + self.all_slices.extend(self.ActionSlices(thread.all_slices)) + self.toplevel_slices.extend(self.ActionSlices(thread.toplevel_slices)) def AddResults(self, num_frames, results): clock_report_name = ThreadTimeResultName(self.name) @@ -224,7 +249,8 @@ class ResultsForThread(object): results.Add(ThreadDetailResultName(self.name, category), 'ms', self_time_result) all_measured_time = sum(all_self_times) - idle_time = max(0, self.model.bounds.bounds - all_measured_time) + all_action_time = sum([action.bounds for action in self.action_ranges]) + idle_time = max(0, all_action_time - all_measured_time) idle_time_result = (float(idle_time) / num_frames) if num_frames else 0 results.Add(ThreadDetailResultName(self.name, "idle"), 'ms', idle_time_result) @@ -243,10 +269,15 @@ class ThreadTimesTimelineMetric(TimelineMetric): return count def AddResults(self, tab, results): + # We need at least one action or we won't count any slices. + assert len(self._action_ranges) > 0 + # Set up each thread category for consistant results. thread_category_results = {} for name in TimelineThreadCategories.values(): - thread_category_results[name] = ResultsForThread(self.model, name) + thread_category_results[name] = ResultsForThread(self._model, + self._action_ranges, + name) # Group the slices by their thread category. for thread in self._model.GetAllThreads(): @@ -259,7 +290,7 @@ class ThreadTimesTimelineMetric(TimelineMetric): # Also group fast-path threads. for thread in self._model.GetAllThreads(): - if ThreadCategoryName(thread.name) in FastPath: + if ThreadCategoryName(thread.name) in FastPathThreads: thread_category_results['total_fast_path'].AppendThreadSlices(thread) # Calculate the number of frames from the CC thread. diff --git a/tools/perf/metrics/timeline_unittest.py b/tools/perf/metrics/timeline_unittest.py index e09177d..6b3c9a00 100644 --- a/tools/perf/metrics/timeline_unittest.py +++ b/tools/perf/metrics/timeline_unittest.py @@ -5,6 +5,7 @@ import unittest from metrics import timeline +from telemetry.core.timeline import bounds from telemetry.core.timeline import model as model_module from telemetry.page import page as page_module from telemetry.page import page_measurement_results @@ -103,15 +104,23 @@ class ThreadTimesTimelineMetricUnittest(unittest.TestCase): cc_main.BeginSlice('cc_cat', timeline.CompositorFrameTraceName, 12, 12) cc_main.EndSlice(13, 13) - # [ X ] + # [ X ] [ Z ] # [ Y ] renderer_main.BeginSlice('cat1', 'X', 10, 0) renderer_main.BeginSlice('cat2', 'Y', 15, 5) - renderer_main.EndSlice(16, 0.5) + renderer_main.EndSlice(16, 5.5) renderer_main.EndSlice(30, 19.5) + renderer_main.BeginSlice('cat1', 'Z', 31, 20) + renderer_main.BeginSlice('cat1', 'Z', 33, 21) model.FinalizeImport() + # Exclude Z using an action-range. + action_range = bounds.Bounds() + action_range.AddValue(10) + action_range.AddValue(30) + metric = timeline.ThreadTimesTimelineMetric() + metric._action_ranges = [action_range] metric.details_to_report = timeline.MainThread results = self.GetResultsForModel(metric, model) diff --git a/tools/telemetry/telemetry/core/timeline/bounds.py b/tools/telemetry/telemetry/core/timeline/bounds.py index 4d3f2a8..14817d7 100644 --- a/tools/telemetry/telemetry/core/timeline/bounds.py +++ b/tools/telemetry/telemetry/core/timeline/bounds.py @@ -47,6 +47,15 @@ class Bounds(object): def center(self): return (self.min_ + self.max_) * 0.5 + def Contains(self, other): + if self.is_empty or other.is_empty: + return False + return self.min <= other.min and self.max >= other.max + + def Intersects(self, other): + if self.is_empty or other.is_empty: + return False + return not (other.max < self.min or other.min > self.max) def Reset(self): self.is_empty_ = True |