| #!/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() |