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