summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorepenner <epenner@chromium.org>2014-10-20 16:08:51 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-20 23:09:13 +0000
commitdddb7ae7a29cc6e9b14e155b50deebf2bc9e13f2 (patch)
tree224ce0294d4762f5943ac857731c472eb3537b15
parente3159f0995c1a21e0d97edce19ca3048b314a9cb (diff)
downloadchromium_src-dddb7ae7a29cc6e9b14e155b50deebf2bc9e13f2.zip
chromium_src-dddb7ae7a29cc6e9b14e155b50deebf2bc9e13f2.tar.gz
chromium_src-dddb7ae7a29cc6e9b14e155b50deebf2bc9e13f2.tar.bz2
Telemetry: Add mean-frame-time and tasks-per-frame
Mean frame time is in other benchmarks, but it's a good sanity check for understanding performance changes. So is tasks-per-frame on each thread, so that is also added in this patch. BUG=None Review URL: https://codereview.chromium.org/643343002 Cr-Commit-Position: refs/heads/master@{#300373}
-rw-r--r--tools/perf/metrics/timeline.py53
-rw-r--r--tools/perf/metrics/timeline_unittest.py23
-rw-r--r--tools/telemetry/telemetry/util/statistics.py5
3 files changed, 51 insertions, 30 deletions
diff --git a/tools/perf/metrics/timeline.py b/tools/perf/metrics/timeline.py
index 211015d..f1c4d9a 100644
--- a/tools/perf/metrics/timeline.py
+++ b/tools/perf/metrics/timeline.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.
import collections
+from telemetry.util.statistics import DivideIfPossibleOrZero
from telemetry.web_perf.metrics import timeline_based_metric
from telemetry.value import scalar
@@ -100,6 +101,8 @@ OverheadTraceName = "overhead"
FrameTraceName = "::SwapBuffers"
FrameTraceThreadName = "renderer_compositor"
+def Rate(numerator, denominator):
+ return DivideIfPossibleOrZero(numerator, denominator)
def ClockOverheadForEvent(event):
if (event.category == OverheadTraceCategory and
@@ -124,12 +127,16 @@ def ThreadCategoryName(thread_name):
thread_category = TimelineThreadCategories[thread_name]
return thread_category
-def ThreadTimeResultName(thread_category):
- return "thread_" + thread_category + "_clock_time_per_frame"
-
def ThreadCpuTimeResultName(thread_category):
+ # This isn't a good name, but I don't want to change it and lose continuity.
return "thread_" + thread_category + "_cpu_time_per_frame"
+def ThreadTasksResultName(thread_category):
+ return "tasks_per_frame_" + thread_category
+
+def ThreadMeanFrameTimeResultName(thread_category):
+ return "mean_frame_time_" + thread_category
+
def ThreadDetailResultName(thread_category, detail):
detail_sanitized = detail.replace('.','_')
return "thread_" + thread_category + "|" + detail_sanitized
@@ -142,6 +149,8 @@ class ResultsForThread(object):
self.all_slices = []
self.name = name
self.record_ranges = record_ranges
+ self.all_action_time = \
+ sum([record_range.bounds for record_range in self.record_ranges])
@property
def clock_time(self):
@@ -179,11 +188,26 @@ class ResultsForThread(object):
self.all_slices.extend(self.SlicesInActions(thread.all_slices))
self.toplevel_slices.extend(self.SlicesInActions(thread.toplevel_slices))
+ # Currently we report cpu-time per frame, tasks per frame, and possibly
+ # the mean frame (if there is a trace specified to find it).
def AddResults(self, num_frames, results):
- cpu_per_frame = (float(self.cpu_time) / num_frames) if num_frames else 0
+ cpu_per_frame = Rate(self.cpu_time, num_frames)
+ tasks_per_frame = Rate(len(self.toplevel_slices), num_frames)
results.AddValue(scalar.ScalarValue(
results.current_page, ThreadCpuTimeResultName(self.name),
'ms', cpu_per_frame))
+ results.AddValue(scalar.ScalarValue(
+ results.current_page, ThreadTasksResultName(self.name),
+ 'tasks', tasks_per_frame))
+ # Report mean frame time if this is the thread we are using for normalizing
+ # other results. We could report other frame rates (eg. renderer_main) but
+ # this might get confusing.
+ if self.name == FrameTraceThreadName:
+ num_frames = self.CountTracesWithName(FrameTraceName)
+ mean_frame_time = Rate(self.all_action_time, num_frames)
+ results.AddValue(scalar.ScalarValue(
+ results.current_page, ThreadMeanFrameTimeResultName(self.name),
+ 'ms', mean_frame_time))
def AddDetailedResults(self, num_frames, results):
slices_by_category = collections.defaultdict(list)
@@ -198,14 +222,18 @@ class ResultsForThread(object):
results.current_page, ThreadDetailResultName(self.name, category),
'ms', self_time_result))
all_measured_time = sum(all_self_times)
- all_action_time = \
- sum([record_range.bounds for record_range in self.record_ranges])
- idle_time = max(0, all_action_time - all_measured_time)
+ idle_time = max(0, self.all_action_time - all_measured_time)
idle_time_result = (float(idle_time) / num_frames) if num_frames else 0
results.AddValue(scalar.ScalarValue(
results.current_page, ThreadDetailResultName(self.name, "idle"),
'ms', idle_time_result))
+ def CountTracesWithName(self, substring):
+ count = 0
+ for event in self.all_slices:
+ if substring in event.name:
+ count += 1
+ return count
class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric):
def __init__(self):
@@ -214,13 +242,6 @@ class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric):
self.results_to_report = AllThreads
self.details_to_report = NoThreads
- def CountSlices(self, slices, substring):
- count = 0
- for event in slices:
- if substring in event.name:
- count += 1
- return count
-
def AddResults(self, model, _, interaction_records, results):
# Set up each thread category for consistant results.
thread_category_results = {}
@@ -243,8 +264,8 @@ class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric):
thread_category_results['total_fast_path'].AppendThreadSlices(thread)
# Calculate the number of frames.
- frame_slices = thread_category_results[FrameTraceThreadName].all_slices
- num_frames = self.CountSlices(frame_slices, FrameTraceName)
+ frame_rate_thread = thread_category_results[FrameTraceThreadName]
+ num_frames = frame_rate_thread.CountTracesWithName(FrameTraceName)
# Report the desired results and details.
for thread_results in thread_category_results.values():
diff --git a/tools/perf/metrics/timeline_unittest.py b/tools/perf/metrics/timeline_unittest.py
index 01c0547..b6a26fd 100644
--- a/tools/perf/metrics/timeline_unittest.py
+++ b/tools/perf/metrics/timeline_unittest.py
@@ -138,16 +138,19 @@ class ThreadTimesTimelineMetricUnittest(unittest.TestCase):
results = self.GetResults(metric, model, renderer_main.parent,
[_GetInteractionRecord(10, 30)])
-
- # Test a couple specific results.
- assert_results = {
- timeline.ThreadCpuTimeResultName('renderer_main') : 9.75,
- timeline.ThreadDetailResultName('renderer_main','cat1') : 9.5,
- timeline.ThreadDetailResultName('renderer_main','cat2') : 0.5,
- timeline.ThreadDetailResultName('renderer_main','idle') : 0
- }
- for name, value in assert_results.iteritems():
- results.AssertHasPageSpecificScalarValue(name, 'ms', value)
+ # Test for the results we expect.
+ main_thread = "renderer_main"
+ cc_thread = 'renderer_compositor'
+ assert_results = [
+ (timeline.ThreadCpuTimeResultName(main_thread), 'ms', 9.75),
+ (timeline.ThreadTasksResultName(main_thread), 'tasks', 0.5),
+ (timeline.ThreadMeanFrameTimeResultName(cc_thread), 'ms', 10.0),
+ (timeline.ThreadDetailResultName(main_thread,'cat1'), 'ms', 9.5),
+ (timeline.ThreadDetailResultName(main_thread,'cat2'), 'ms', 0.5),
+ (timeline.ThreadDetailResultName(main_thread,'idle'), 'ms', 0)
+ ]
+ for name, unit, value in assert_results:
+ results.AssertHasPageSpecificScalarValue(name, unit, value)
def testOverheadIsRemoved(self):
model = model_module.TimelineModel()
diff --git a/tools/telemetry/telemetry/util/statistics.py b/tools/telemetry/telemetry/util/statistics.py
index 5308b51..9867f45 100644
--- a/tools/telemetry/telemetry/util/statistics.py
+++ b/tools/telemetry/telemetry/util/statistics.py
@@ -262,10 +262,7 @@ def Total(data):
def DivideIfPossibleOrZero(numerator, denominator):
"""Returns the quotient, or zero if the denominator is zero."""
- if not denominator:
- return 0.0
- else:
- return numerator / denominator
+ return (float(numerator) / float(denominator)) if denominator else 0
def GeneralizedMean(values, exponent):