1# Copyright 2015 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
5from telemetry import value
6from telemetry.web_perf.metrics import timeline_based_metric
7
8_PROCESS_CREATION = 'Startup.BrowserProcessCreation'
9_MAIN_ENTRY_POINT = 'Startup.BrowserMainEntryPoint'
10
11# A dictionary that maps metric names to a value, which can be either of
12# the two:
13#  1. A tuple of one event name if the event itself contains reported duration
14#  2. A tuple of two event names if the value to report is the time difference
15#     between starting these events
16_METRICS = {
17  'messageloop_start_time':
18      ('Startup.BrowserMessageLoopStartTimeFromMainEntry',),
19
20  'window_display_time':
21      ('Startup.BrowserWindowDisplay',),
22
23  'open_tabs_time':
24      ('Startup.BrowserOpenTabs',),
25
26  'first_non_empty_paint_time':
27      ('Startup.FirstWebContents.NonEmptyPaint2',),
28
29  'first_main_frame_load_time':
30      ('Startup.FirstWebContents.MainFrameLoad2',),
31
32  'foreground_tab_load_complete':
33      (_MAIN_ENTRY_POINT, 'loadEventEnd'),
34
35  'foreground_tab_request_start':
36      (_MAIN_ENTRY_POINT, 'requestStart'),
37}
38
39_TRACKED_EVENT_NAMES = set()
40for i in _METRICS.values():
41  _TRACKED_EVENT_NAMES.add(i[0])
42  if len(i) == 2:
43    _TRACKED_EVENT_NAMES.add(i[1])
44
45
46class StartupTimelineMetric(timeline_based_metric.TimelineBasedMetric):
47  """Reports summary stats from important startup events."""
48
49  def __init__(self):
50    super(StartupTimelineMetric, self).__init__()
51
52  def AddResults(self, model, _renderer_thread, interactions, results):
53    pass
54
55  def AddWholeTraceResults(self, model, results):
56    browser = model.browser_process
57
58    if not browser:
59      return
60
61    # Produce a map of events to track.
62    tracked_events = {}
63    for event in browser.parent.IterAllEvents(
64      event_predicate=lambda event: event.name in _TRACKED_EVENT_NAMES):
65      # In case of a begin/end trace event, only track the begin that contain
66      # the duration.
67      if event.name in tracked_events:
68        continue
69
70      tracked_events[event.name] = event
71
72    # Generate the metric values according to the tracked events.
73    for display_name, event_names in _METRICS.iteritems():
74      if event_names[0] not in tracked_events:
75        continue
76
77      duration = None
78      if len(event_names) == 1:
79        # The single event contains the duration to report.
80        duration = tracked_events[event_names[0]].duration
81
82      elif len(event_names) == 2:
83        # The duration is defined as the difference between two event starts.
84        if event_names[1] not in tracked_events:
85          continue
86
87        duration = (tracked_events[event_names[1]].start -
88            tracked_events[event_names[0]].start)
89
90      results.AddValue(value.scalar.ScalarValue(
91        page=results.current_page,
92        name=display_name,
93        units='ms',
94        value=duration,
95        improvement_direction=value.improvement_direction.DOWN))
96