diff options
author | epenner <epenner@chromium.org> | 2014-10-20 16:08:51 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-20 23:09:13 +0000 |
commit | dddb7ae7a29cc6e9b14e155b50deebf2bc9e13f2 (patch) | |
tree | 224ce0294d4762f5943ac857731c472eb3537b15 | |
parent | e3159f0995c1a21e0d97edce19ca3048b314a9cb (diff) | |
download | chromium_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.py | 53 | ||||
-rw-r--r-- | tools/perf/metrics/timeline_unittest.py | 23 | ||||
-rw-r--r-- | tools/telemetry/telemetry/util/statistics.py | 5 |
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): |