blob: 363bde4b959c18427cb3d53cf9dae2017563eda3 [file] [log] [blame]
#!/usr/bin/python2
"""Records stats on an event injected by a benchmark test."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import c_val_names
import tv_testcase_util
class EventRecorderOptions(object):
"""Contains all of the parameters needed by EventRecorder."""
def __init__(self, test, event_name, event_type):
"""Initializes the event recorder options.
Args:
test: specific benchmark test being run
event_name: name of the event being recorded
event_type: type of event being recorded (tv_testcase_util.py)
"""
self.test = test
self.event_name = event_name
self.event_type = event_type
self.record_animations = True
self.record_video = False
class EventRecorder(object):
"""Records stats on an event injected by a benchmark test.
Handles collecting event data over all of the instances of a specific event
injected by a benchmark test and records statistics on the data when the test
ends. The specific event types that can be injected are listed within
tv_testcase_util.py.
Both rasterize animations and video start delay data can potentially be
recorded, depending on the |record_animations| and |record_video| option
flags.
"""
def __init__(self, options):
"""Initializes the event recorder.
Handles setting up this event recorder, including creating all of its
recorders, based upon the passed in options.
Args:
options: the settings to use in creating this event recorder
"""
self.test = options.test
self.event_name = options.event_name
self.event_type = options.event_type
self.render_tree_failure_count = 0
# Each entry in the list contains a tuple with a key and value recorder.
self.value_dictionary_recorders = []
# Optional animations recorders
self.animations_recorder = None
self.animations_start_delay_recorder = None
self.animations_end_delay_recorder = None
# Optional video recorders
self.video_delay_recorder = None
# Count record strategies
count_record_strategies = []
count_record_strategies.append(tv_testcase_util.RecordStrategyMean())
count_record_strategies.append(tv_testcase_util.RecordStrategyMedian())
count_record_strategies.append(tv_testcase_util.RecordStrategyMax())
# Duration record strategies
duration_record_strategies = []
duration_record_strategies.append(tv_testcase_util.RecordStrategyMean())
duration_record_strategies.append(
tv_testcase_util.RecordStrategyPercentile(25))
duration_record_strategies.append(
tv_testcase_util.RecordStrategyPercentile(50))
duration_record_strategies.append(
tv_testcase_util.RecordStrategyPercentile(75))
duration_record_strategies.append(
tv_testcase_util.RecordStrategyPercentile(95))
# Video delay record strategies
video_delay_record_strategies = []
video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMean())
video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMin())
video_delay_record_strategies.append(
tv_testcase_util.RecordStrategyPercentile(25))
video_delay_record_strategies.append(
tv_testcase_util.RecordStrategyPercentile(50))
video_delay_record_strategies.append(
tv_testcase_util.RecordStrategyPercentile(75))
video_delay_record_strategies.append(
tv_testcase_util.RecordStrategyPercentile(95))
video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMax())
video_delay_record_strategies.append(
tv_testcase_util.RecordStrategyStandardDeviation())
# Dictionary count recorders
self._add_value_dictionary_recorder("CntDomEventListeners",
count_record_strategies)
self._add_value_dictionary_recorder("CntDomNodes", count_record_strategies)
self._add_value_dictionary_recorder("CntDomHtmlElements",
count_record_strategies)
self._add_value_dictionary_recorder("CntDomDocumentHtmlElements",
count_record_strategies)
self._add_value_dictionary_recorder("CntDomHtmlElementsCreated",
count_record_strategies)
self._add_value_dictionary_recorder("CntDomUpdateMatchingRules",
count_record_strategies)
self._add_value_dictionary_recorder("CntDomUpdateComputedStyle",
count_record_strategies)
self._add_value_dictionary_recorder("CntDomGenerateHtmlComputedStyle",
count_record_strategies)
self._add_value_dictionary_recorder("CntDomGeneratePseudoComputedStyle",
count_record_strategies)
self._add_value_dictionary_recorder("CntLayoutBoxes",
count_record_strategies)
self._add_value_dictionary_recorder("CntLayoutBoxesCreated",
count_record_strategies)
self._add_value_dictionary_recorder("CntLayoutUpdateSize",
count_record_strategies)
self._add_value_dictionary_recorder("CntLayoutRenderAndAnimate",
count_record_strategies)
self._add_value_dictionary_recorder("CntLayoutUpdateCrossReferences",
count_record_strategies)
# Dictionary duration recorders
self._add_value_dictionary_recorder("DurTotalUs",
duration_record_strategies)
self._add_value_dictionary_recorder("DurDomInjectEventUs",
duration_record_strategies)
self._add_value_dictionary_recorder("DurDomRunAnimationFrameCallbacksUs",
duration_record_strategies)
self._add_value_dictionary_recorder("DurDomUpdateComputedStyleUs",
duration_record_strategies)
self._add_value_dictionary_recorder("DurLayoutBoxTreeUs",
duration_record_strategies)
self._add_value_dictionary_recorder("DurLayoutBoxTreeBoxGenerationUs",
duration_record_strategies)
self._add_value_dictionary_recorder("DurLayoutBoxTreeUpdateUsedSizesUs",
duration_record_strategies)
self._add_value_dictionary_recorder("DurLayoutRenderAndAnimateUs",
duration_record_strategies)
self.count_render_trees_recorder = tv_testcase_util.ResultsRecorder(
self.event_name + "CntRenderTrees", count_record_strategies)
self.count_requested_images_recorder = tv_testcase_util.ResultsRecorder(
self.event_name + "CntRequestedImages", count_record_strategies)
# Optional animations recorder
if options.record_animations:
self.animations_recorder = tv_testcase_util.ResultsRecorder(
self.event_name + "DurRasterizeAnimationsUs",
duration_record_strategies)
self.animations_start_delay_recorder = tv_testcase_util.ResultsRecorder(
self.event_name + "DurAnimationsStartDelayUs",
duration_record_strategies)
self.animations_end_delay_recorder = tv_testcase_util.ResultsRecorder(
self.event_name + "DurAnimationsEndDelayUs",
duration_record_strategies)
self.final_render_tree_delay_recorder = tv_testcase_util.ResultsRecorder(
self.event_name + "DurFinalRenderTreeDelayUs",
duration_record_strategies)
# Optional video recorder
if options.record_video:
self.video_delay_recorder = tv_testcase_util.ResultsRecorder(
self.event_name + "DurVideoStartDelayUs",
video_delay_record_strategies)
def _add_value_dictionary_recorder(self, key, record_strategies):
recorder = tv_testcase_util.ResultsRecorder(self.event_name + key,
record_strategies)
self.value_dictionary_recorders.append((key, recorder))
def on_start_event(self):
"""Handles logic related to the start of the event instance."""
self.count_render_trees_start = self.test.get_cval(
c_val_names.count_rasterize_new_render_tree())
self.count_requested_images_start = self.test.get_cval(
c_val_names.count_image_cache_requested_resources())
def on_end_event(self):
"""Handles logic related to the end of the event instance."""
value_dictionary = self.test.get_cval(
c_val_names.event_value_dictionary(self.event_type))
# If the event failed to produce a render tree, then its data is not
# collected. Log the failure and return.
if not value_dictionary or not value_dictionary.get("ProducedRenderTree"):
self.render_tree_failure_count += 1
print("{} event failed to produce render tree! {} events failed.".format(
self.event_name, self.render_tree_failure_count))
return
event_start_time = value_dictionary.get("StartTime")
# Record all of the values from the event.
for value_dictionary_recorder in self.value_dictionary_recorders:
value = value_dictionary.get(value_dictionary_recorder[0])
if value is not None:
value_dictionary_recorder[1].collect_value(value)
self.count_render_trees_end = self.test.get_cval(
c_val_names.count_rasterize_new_render_tree())
self.count_render_trees_recorder.collect_value(
self.count_render_trees_end - self.count_render_trees_start)
self.count_requested_images_end = self.test.get_cval(
c_val_names.count_image_cache_requested_resources())
self.count_requested_images_recorder.collect_value(
self.count_requested_images_end - self.count_requested_images_start)
if self.animations_recorder:
animation_entries = self.test.get_cval(
c_val_names.rasterize_animations_entry_list())
for value in animation_entries:
self.animations_recorder.collect_value(value)
animations_start_time = self.test.get_cval(
c_val_names.time_rasterize_animations_start())
self.animations_start_delay_recorder.collect_value(
animations_start_time - event_start_time)
animations_end_time = self.test.get_cval(
c_val_names.time_rasterize_animations_end())
self.animations_end_delay_recorder.collect_value(animations_end_time -
event_start_time)
final_render_tree_time = self.test.get_cval(
c_val_names.time_rasterize_new_render_tree())
self.final_render_tree_delay_recorder.collect_value(final_render_tree_time -
event_start_time)
if self.video_delay_recorder:
self.video_delay_recorder.collect_value(
self.test.get_cval(
c_val_names.event_duration_dom_video_start_delay()))
def on_end_test(self):
"""Handles logic related to the end of the test."""
for value_dictionary_recorder in self.value_dictionary_recorders:
value_dictionary_recorder[1].on_end_test()
self.count_render_trees_recorder.on_end_test()
self.count_requested_images_recorder.on_end_test()
if self.animations_recorder:
self.animations_recorder.on_end_test()
self.animations_start_delay_recorder.on_end_test()
self.animations_end_delay_recorder.on_end_test()
self.final_render_tree_delay_recorder.on_end_test()
if self.video_delay_recorder:
self.video_delay_recorder.on_end_test()