1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6
7from telemetry.timeline import bounds
8from telemetry.value import scalar
9from telemetry.web_perf import timeline_interaction_record as tir_module
10from telemetry.web_perf.metrics import timeline_based_metric
11from telemetry.web_perf.metrics import v8_stats as v8_stats_module
12
13
14class FastMetric(timeline_based_metric.TimelineBasedMetric):
15  def __init__(self):
16    super(FastMetric, self).__init__()
17
18  def AddResults(self, model, renderer_thread, interaction_records, results):
19    """Add 11 results: duration, cpu_time, and idle_time,
20                       incremental_marking, incremental_marking_outside_idle,
21                       scavenger, scavenger_outside_idle,
22                       mark_compactor, mark_compactor_outside_idle,
23                       total_garbage_collection,
24                       total_garbage_collection_outside_idle
25
26    duration is the total wall time for |interaction_records|.
27    cpu_time is the renderer thread time that intersects |interaction_records|.
28    idle time is wall time for |interaction_records| for which renderer slices
29        do not overlap. Note that unscheduled renderer thread time is not
30        counted. Idle time is time for which there was nothing to do.
31    incremental_marking is the total thread duration spent in incremental
32        marking steps.
33    incremental_marking_outside_idle is the thread duration spent in incremental
34        marking steps outside of idle notifications.
35    scavenger is the total thread duration spent in scavenges.
36    scavenger_outside_idle is the thread duration spent in scavenges outside of
37        idle notifications.
38    mark_compactor is the total thread duration spent in mark-sweep-compactor.
39    mark_compactor_outside_idle is the thread duration spent in
40        mark-sweep-compactor outside of idle notifications.
41    total_garbage_collection is the total thread duration spend in garbage
42        collection
43    total_garbage_collection_outside_idle is the total thread duration spend in
44        garbage collection outside of idle notification.
45
46    Args:
47      model: a TimelineModule instance
48      renderer_thread: a telemetry.timeline.thread.Thread() instance
49      interaction_records: an iterable of TimelineInteractionRecord instances
50      results: an instance of page.PageTestResults
51    """
52    self.VerifyNonOverlappedRecords(interaction_records)
53
54    duration = sum(r.end - r.start for r in interaction_records)
55    results.AddValue(scalar.ScalarValue(
56        results.current_page, 'fast-duration', 'ms', duration))
57
58    try:
59      cpu_time = sum(
60          r.GetOverlappedThreadTimeForSlice(s)
61          for r in interaction_records
62          for s in renderer_thread.toplevel_slices)
63    except tir_module.NoThreadTimeDataException:
64      logging.warning(
65          'Main thread cpu_time cannot be computed for records %s since '
66          'trace does not contain thread time data.',
67          repr(interaction_records))
68    else:
69      results.AddValue(scalar.ScalarValue(
70          results.current_page, 'fast-cpu_time', 'ms', cpu_time))
71
72    idle_time = duration - sum(
73        bounds.Bounds.GetOverlap(r.start, r.end, s.start, s.end)
74        for r in interaction_records
75        for s in renderer_thread.toplevel_slices)
76    results.AddValue(scalar.ScalarValue(
77        results.current_page, 'fast-idle_time', 'ms', idle_time))
78
79    v8_stats = v8_stats_module.V8Stats(renderer_thread, interaction_records)
80
81    for event_stats in v8_stats.all_event_stats:
82      results.AddValue(scalar.ScalarValue(
83          results.current_page, 'fast-' + event_stats.result_name, 'ms',
84          event_stats.thread_duration,
85          event_stats.result_description))
86      results.AddValue(scalar.ScalarValue(
87          results.current_page,
88          'fast-' + event_stats.result_name + '_outside_idle', 'ms',
89          event_stats.thread_duration_outside_idle,
90          event_stats.result_description + 'outside of idle notifications'))
91
92    results.AddValue(scalar.ScalarValue(
93        results.current_page, 'fast-total_garbage_collection', 'ms',
94        v8_stats.total_gc_thread_duration,
95        'Total thread duration of all garbage collection events'))
96
97    results.AddValue(scalar.ScalarValue(
98        results.current_page, 'fast-total_garbage_collection_outside_idle',
99        'ms', v8_stats.total_gc_thread_duration_outside_idle,
100        'Total thread duration of all garbage collection events outside of idle'
101        'notifications'))
102