1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from telemetry.value import improvement_direction
from telemetry.value import list_of_scalar_values
from telemetry.web_perf.metrics import timeline_based_metric
WRITE_EVENT_NAME = 'Registry::RegisterBlob'
READ_EVENT_NAME = 'BlobRequest'
class BlobTimelineMetric(timeline_based_metric.TimelineBasedMetric):
"""BlobTimelineMetric reports timing information about blob storage.
The following metrics are added to the results:
* blob write times (blob_writes)
* blob read times (blob_reads)
"""
def __init__(self):
super(BlobTimelineMetric, self).__init__()
@staticmethod
def IsWriteEvent(event):
return event.name == WRITE_EVENT_NAME
@staticmethod
def IsReadEvent(event):
return event.name == READ_EVENT_NAME
@staticmethod
def IsEventInInteraction(event, interaction):
return interaction.start <= event.start <= interaction.end
@staticmethod
def ThreadDurationIfPresent(event):
if event.thread_duration:
return event.thread_duration
else:
return event.duration
def AddResults(self, model, renderer_thread, interactions, results):
assert interactions
write_events = []
read_events = []
for event in model.IterAllEvents(
event_predicate=lambda e: self.IsWriteEvent(e) or self.IsReadEvent(e)):
if self.IsReadEvent(event):
read_events.append(event)
else:
write_events.append(event)
# Only these private methods are tested for mocking simplicity.
self._AddWriteResultsInternal(write_events, interactions, results)
self._AddReadResultsInternal(read_events, interactions, results)
def _AddWriteResultsInternal(self, events, interactions, results):
writes = []
for event in events:
if (self.IsWriteEvent(event) and
any(self.IsEventInInteraction(event, interaction)
for interaction in interactions)):
writes.append(self.ThreadDurationIfPresent(event))
if writes:
results.AddValue(list_of_scalar_values.ListOfScalarValues(
page=results.current_page,
tir_label=interactions[0].label,
name='blob-writes',
units='ms',
values=writes,
description='List of durations of blob writes.',
improvement_direction=improvement_direction.DOWN))
else:
results.AddValue(list_of_scalar_values.ListOfScalarValues(
page=results.current_page,
tir_label=interactions[0].label,
name='blob-writes',
units='ms',
values=None,
none_value_reason='No blob write events found for this interaction.',
improvement_direction=improvement_direction.DOWN))
def _AddReadResultsInternal(self, events, interactions, results):
reads = dict()
for event in events:
if (not self.IsReadEvent(event) or
not any(self.IsEventInInteraction(event, interaction)
for interaction in interactions)):
continue
# Every blob has unique UUID. To get the total time for reading
# a blob, we add up the time of all events with the same blob UUID.
uuid = event.args['uuid']
if uuid not in reads:
reads[uuid] = 0
reads[uuid] += self.ThreadDurationIfPresent(event)
if reads:
results.AddValue(list_of_scalar_values.ListOfScalarValues(
page=results.current_page,
tir_label=interactions[0].label,
name='blob-reads',
units='ms',
values=reads.values(),
description='List of read times for blobs.',
improvement_direction=improvement_direction.DOWN))
else:
results.AddValue(list_of_scalar_values.ListOfScalarValues(
page=results.current_page,
tir_label=interactions[0].label,
name='blob-reads',
units='ms',
values=None,
none_value_reason='No blob read events found for this interaction.',
improvement_direction=improvement_direction.DOWN))
|