summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorepenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-18 02:54:00 +0000
committerepenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-18 02:54:00 +0000
commitb8c7eed238ffa4a47f90df3a077f4ee1daf23569 (patch)
tree940ac7b9463ce5ad3c7ed8e6cb8c489baa61ed27
parent64c0acef7a48f5d45f92c1e9e09ab5614ec5d93d (diff)
downloadchromium_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.py6
-rw-r--r--tools/perf/metrics/timeline.py57
-rw-r--r--tools/perf/metrics/timeline_unittest.py13
-rw-r--r--tools/telemetry/telemetry/core/timeline/bounds.py9
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