Index: tools/perf/metrics/timeline.py |
diff --git a/tools/perf/metrics/timeline.py b/tools/perf/metrics/timeline.py |
index 1a1ca25e219edde5f445920118c05da1725b3db6..984707d825b5cf3fc198a1ffea35d046069c732f 100644 |
--- a/tools/perf/metrics/timeline.py |
+++ b/tools/perf/metrics/timeline.py |
@@ -101,6 +101,8 @@ OverheadTraceName = "overhead" |
FrameTraceName = "::SwapBuffers" |
FrameTraceThreadName = "renderer_compositor" |
+IntervalNames = ["frame", "ms"] |
+ |
def Rate(numerator, denominator): |
return DivideIfPossibleOrZero(numerator, denominator) |
@@ -127,19 +129,40 @@ def ThreadCategoryName(thread_name): |
thread_category = TimelineThreadCategories[thread_name] |
return thread_category |
-def ThreadCpuTimeResultName(thread_category): |
+def ThreadCpuTimeResultName(thread_category, interval_name): |
# 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" |
+ return "thread_" + thread_category + "_cpu_time_per_" + interval_name |
-def ThreadTasksResultName(thread_category): |
- return "tasks_per_frame_" + thread_category |
+def ThreadTasksResultName(thread_category, interval_name): |
+ return "tasks_per_" + interval_name + "_" + thread_category |
def ThreadMeanFrameTimeResultName(thread_category): |
return "mean_frame_time_" + thread_category |
-def ThreadDetailResultName(thread_category, detail): |
+def ThreadDetailResultName(thread_category, interval_name, detail): |
detail_sanitized = detail.replace('.','_') |
- return "thread_" + thread_category + "|" + detail_sanitized |
+ interval_sanitized = "" |
+ # Special-case per-frame detail names to preserve continuity. |
+ if interval_name == "frame": |
+ interval_sanitized = "" |
+ else: |
+ interval_sanitized = "_per_" + interval_name |
+ return ( |
+ "thread_" + thread_category + interval_sanitized + "|" + detail_sanitized) |
+ |
+def _ReportCpuTimePerIntervalAsPercent(interval_name): |
+ # When measuring ms of CPU time per ms of system time, report a %. |
+ return interval_name == "ms" |
+ |
+def ThreadCpuTimeUnits(interval_name): |
+ if _ReportCpuTimePerIntervalAsPercent(interval_name): |
+ return "%" |
+ return "ms" |
+ |
+def ThreadCpuTimeValue(cpu_time_per_interval, interval_name): |
+ if _ReportCpuTimePerIntervalAsPercent(interval_name): |
+ return cpu_time_per_interval * 100.0 |
+ return cpu_time_per_interval |
class ResultsForThread(object): |
@@ -188,28 +211,21 @@ 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 = Rate(self.cpu_time, num_frames) |
- tasks_per_frame = Rate(len(self.toplevel_slices), num_frames) |
+ # Reports cpu-time per interval and tasks per interval. |
+ def AddResults(self, num_intervals, interval_name, results): |
+ cpu_per_interval = Rate(self.cpu_time, num_intervals) |
+ tasks_per_interval = Rate(len(self.toplevel_slices), num_intervals) |
results.AddValue(scalar.ScalarValue( |
- results.current_page, ThreadCpuTimeResultName(self.name), |
- 'ms', cpu_per_frame)) |
+ results.current_page, |
+ ThreadCpuTimeResultName(self.name, interval_name), |
+ ThreadCpuTimeUnits(interval_name), |
+ ThreadCpuTimeValue(cpu_per_interval, interval_name))) |
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)) |
+ results.current_page, |
+ ThreadTasksResultName(self.name, interval_name), |
+ 'tasks', tasks_per_interval)) |
- def AddDetailedResults(self, num_frames, results): |
+ def AddDetailedResults(self, num_intervals, interval_name, results): |
slices_by_category = collections.defaultdict(list) |
for s in self.all_slices: |
slices_by_category[s.category].append(s) |
@@ -217,16 +233,20 @@ class ResultsForThread(object): |
for category, slices_in_category in slices_by_category.iteritems(): |
self_time = sum([x.self_time for x in slices_in_category]) |
all_self_times.append(self_time) |
- self_time_result = (float(self_time) / num_frames) if num_frames else 0 |
+ self_time_per_interval = Rate(self_time, num_intervals) |
results.AddValue(scalar.ScalarValue( |
- results.current_page, ThreadDetailResultName(self.name, category), |
- 'ms', self_time_result)) |
+ results.current_page, |
+ ThreadDetailResultName(self.name, interval_name, category), |
+ ThreadCpuTimeUnits(interval_name), |
+ ThreadCpuTimeValue(self_time_per_interval, interval_name))) |
all_measured_time = sum(all_self_times) |
idle_time = max(0, self.all_action_time - all_measured_time) |
- idle_time_result = (float(idle_time) / num_frames) if num_frames else 0 |
+ idle_time_per_interval = Rate(idle_time, num_intervals) |
results.AddValue(scalar.ScalarValue( |
- results.current_page, ThreadDetailResultName(self.name, "idle"), |
- 'ms', idle_time_result)) |
+ results.current_page, |
+ ThreadDetailResultName(self.name, interval_name, "idle"), |
+ ThreadCpuTimeUnits(interval_name), |
+ ThreadCpuTimeValue(idle_time_per_interval, interval_name))) |
def CountTracesWithName(self, substring): |
count = 0 |
@@ -235,6 +255,7 @@ class ResultsForThread(object): |
count += 1 |
return count |
+ |
class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric): |
def __init__(self): |
super(ThreadTimesTimelineMetric, self).__init__() |
@@ -247,7 +268,7 @@ class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric): |
thread_category_results = {} |
for name in TimelineThreadCategories.values(): |
thread_category_results[name] = ResultsForThread( |
- model, [r.GetBounds() for r in interaction_records], name) |
+ model, [r.GetBounds() for r in interaction_records], name) |
# Group the slices by their thread category. |
for thread in model.GetAllThreads(): |
@@ -263,15 +284,30 @@ class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric): |
if ThreadCategoryName(thread.name) in FastPathThreads: |
thread_category_results['total_fast_path'].AppendThreadSlices(thread) |
- # Calculate the number of frames. |
+ # Calculate the interaction's number of frames. |
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(): |
- if thread_results.name in self.results_to_report: |
- thread_results.AddResults(num_frames, results) |
- # TOOD(nduca): When generic results objects are done, this special case |
- # can be replaced with a generic UI feature. |
- if thread_results.name in self.details_to_report: |
- thread_results.AddDetailedResults(num_frames, results) |
+ # Calculate the interaction's duration. |
+ all_threads = thread_category_results['total_all'] |
+ num_ms = all_threads.all_action_time |
+ |
+ # Report the desired results and details for each interval type. |
+ intervals = [('frame', num_frames), ('ms', num_ms)] |
+ for (interval_name, num_intervals) in intervals: |
+ for thread_results in thread_category_results.values(): |
+ if thread_results.name in self.results_to_report: |
+ thread_results.AddResults(num_intervals, interval_name, results) |
+ # TOOD(nduca): When generic results objects are done, this special case |
+ # can be replaced with a generic UI feature. |
+ if thread_results.name in self.details_to_report: |
+ thread_results.AddDetailedResults( |
+ num_intervals, interval_name, results) |
+ |
+ # Report mean frame time for the frame rate thread. We could report other |
+ # frame rates (eg. renderer_main) but this might get confusing. |
+ mean_frame_time = Rate(frame_rate_thread.all_action_time, num_frames) |
+ results.AddValue(scalar.ScalarValue( |
+ results.current_page, |
+ ThreadMeanFrameTimeResultName(FrameTraceThreadName), |
+ 'ms', mean_frame_time)) |