Commit 2cd4e23b authored by slamm's avatar slamm Committed by Commit bot

Make discarding the first result possible through...

Make discarding the first result possible through Benchmark.ValueCanBeAddedPredicate (add a "is_first_result" arg to it).

The main motivation here is to eliminate special cases for PageTest methods/attributes in user_story_runner.Run.

BUG=440101

Review URL: https://codereview.chromium.org/962793004

Cr-Commit-Position: refs/heads/master@{#319140}
parent 2d1b61e4
...@@ -22,7 +22,7 @@ class _GPUTimes(benchmark.Benchmark): ...@@ -22,7 +22,7 @@ class _GPUTimes(benchmark.Benchmark):
overhead_level=cat_filter) overhead_level=cat_filter)
@classmethod @classmethod
def ValueCanBeAddedPredicate(cls, value): def ValueCanBeAddedPredicate(cls, value, _):
return (isinstance(value, gpu_timeline.GPUTimelineListOfValues) or return (isinstance(value, gpu_timeline.GPUTimelineListOfValues) or
isinstance(value, gpu_timeline.GPUTimelineValue)) isinstance(value, gpu_timeline.GPUTimelineValue))
......
...@@ -9,6 +9,7 @@ from telemetry import benchmark ...@@ -9,6 +9,7 @@ from telemetry import benchmark
class _PageCycler(benchmark.Benchmark): class _PageCycler(benchmark.Benchmark):
options = {'pageset_repeat': 6} options = {'pageset_repeat': 6}
cold_load_percent = 50 # % of page visits for which a cold load is forced
@classmethod @classmethod
def Name(cls): def Name(cls):
...@@ -20,14 +21,15 @@ class _PageCycler(benchmark.Benchmark): ...@@ -20,14 +21,15 @@ class _PageCycler(benchmark.Benchmark):
action='store_true', action='store_true',
help='Enable the speed index metric.') help='Enable the speed index metric.')
parser.add_option('--cold-load-percent', type='int', default=50, @classmethod
help='%d of page visits for which a cold load is forced') def ValueCanBeAddedPredicate(cls, _, is_first_result):
return cls.cold_load_percent > 0 or not is_first_result
def CreatePageTest(self, options): def CreatePageTest(self, options):
return page_cycler.PageCycler( return page_cycler.PageCycler(
page_repeat = options.page_repeat, page_repeat = options.page_repeat,
pageset_repeat = options.pageset_repeat, pageset_repeat = options.pageset_repeat,
cold_load_percent = options.cold_load_percent, cold_load_percent = self.cold_load_percent,
report_speed_index = options.report_speed_index) report_speed_index = options.report_speed_index)
...@@ -139,10 +141,10 @@ class PageCyclerNetsimTop10(_PageCycler): ...@@ -139,10 +141,10 @@ class PageCyclerNetsimTop10(_PageCycler):
tag = 'netsim' tag = 'netsim'
page_set = page_sets.Top10PageSet page_set = page_sets.Top10PageSet
options = { options = {
'cold_load_percent': 100,
'extra_wpr_args_as_string': '--shaping_type=proxy --net=cable', 'extra_wpr_args_as_string': '--shaping_type=proxy --net=cable',
'pageset_repeat': 6, 'pageset_repeat': 6,
} }
cold_load_percent = 100
@classmethod @classmethod
def Name(cls): def Name(cls):
...@@ -152,7 +154,7 @@ class PageCyclerNetsimTop10(_PageCycler): ...@@ -152,7 +154,7 @@ class PageCyclerNetsimTop10(_PageCycler):
return page_cycler.PageCycler( return page_cycler.PageCycler(
page_repeat = options.page_repeat, page_repeat = options.page_repeat,
pageset_repeat = options.pageset_repeat, pageset_repeat = options.pageset_repeat,
cold_load_percent = options.cold_load_percent, cold_load_percent = self.cold_load_percent,
report_speed_index = options.report_speed_index, report_speed_index = options.report_speed_index,
clear_cache_before_each_run = True) clear_cache_before_each_run = True)
......
...@@ -23,6 +23,7 @@ class _SessionRestoreTypical25(benchmark.Benchmark): ...@@ -23,6 +23,7 @@ class _SessionRestoreTypical25(benchmark.Benchmark):
TODO(slamm): Make SmallProfileCreator and this use the same page_set ref. TODO(slamm): Make SmallProfileCreator and this use the same page_set ref.
""" """
page_set = page_sets.Typical25PageSet page_set = page_sets.Typical25PageSet
tag = None # override with 'warm' or 'cold'
@classmethod @classmethod
def Name(cls): def Name(cls):
...@@ -48,6 +49,10 @@ class _SessionRestoreTypical25(benchmark.Benchmark): ...@@ -48,6 +49,10 @@ class _SessionRestoreTypical25(benchmark.Benchmark):
small_profile_creator.SmallProfileCreator, profile_type, new_args) small_profile_creator.SmallProfileCreator, profile_type, new_args)
args.browser_options.profile_dir = profile_dir args.browser_options.profile_dir = profile_dir
@classmethod
def ValueCanBeAddedPredicate(cls, _, is_first_result):
return cls.tag == 'cold' or not is_first_result
def CreateUserStorySet(self, _): def CreateUserStorySet(self, _):
"""Return a user story set that only has the first user story. """Return a user story set that only has the first user story.
......
...@@ -27,6 +27,10 @@ class _StartupWarm(benchmark.Benchmark): ...@@ -27,6 +27,10 @@ class _StartupWarm(benchmark.Benchmark):
def Name(cls): def Name(cls):
return 'startup' return 'startup'
@classmethod
def ValueCanBeAddedPredicate(cls, _, is_first_result):
return not is_first_result
def CreatePageTest(self, options): def CreatePageTest(self, options):
return startup.Startup(cold=False) return startup.Startup(cold=False)
......
...@@ -61,8 +61,6 @@ class PageCycler(page_test.PageTest): ...@@ -61,8 +61,6 @@ class PageCycler(page_test.PageTest):
(int(pageset_repeat) - 1) * (100 - cold_load_percent) / 100) (int(pageset_repeat) - 1) * (100 - cold_load_percent) / 100)
number_warm_runs = number_warm_pageset_runs * page_repeat number_warm_runs = number_warm_pageset_runs * page_repeat
self._cold_run_start_index = number_warm_runs + page_repeat self._cold_run_start_index = number_warm_runs + page_repeat
self._discard_first_result = (not cold_load_percent or
self._discard_first_result)
else: else:
self._cold_run_start_index = pageset_repeat * page_repeat self._cold_run_start_index = pageset_repeat * page_repeat
......
...@@ -24,9 +24,6 @@ class Startup(page_test.PageTest): ...@@ -24,9 +24,6 @@ class Startup(page_test.PageTest):
def CustomizeBrowserOptions(self, options): def CustomizeBrowserOptions(self, options):
if self._cold: if self._cold:
options.clear_sytem_cache_for_browser_and_profile_on_start = True options.clear_sytem_cache_for_browser_and_profile_on_start = True
else:
self.discard_first_result = True
options.AppendExtraBrowserArgs([ options.AppendExtraBrowserArgs([
'--enable-stats-collection-bindings' '--enable-stats-collection-bindings'
]) ])
......
...@@ -138,17 +138,22 @@ class Benchmark(command_line.Command): ...@@ -138,17 +138,22 @@ class Benchmark(command_line.Command):
def ProcessCommandLineArgs(cls, parser, args): def ProcessCommandLineArgs(cls, parser, args):
pass pass
# pylint: disable=unused-argument
@classmethod @classmethod
def ValueCanBeAddedPredicate(cls, value): # pylint: disable=unused-argument def ValueCanBeAddedPredicate(cls, value, is_first_result):
""" Returns whether |value| can be added to the test results. """Returns whether |value| can be added to the test results.
Override this method to customize the logic of adding values to test Override this method to customize the logic of adding values to test
results. results.
Args: Args:
value: a value.Value instance. value: a value.Value instance.
is_first_result: True if |value| is the first result for its
corresponding user story.
Returns: a boolean. True if value should be added to the test results and Returns:
False otherwise. True if |value| should be added to the test results.
Otherwise, it returns False.
""" """
return True return True
......
...@@ -132,7 +132,7 @@ class BenchmarkTest(unittest.TestCase): ...@@ -132,7 +132,7 @@ class BenchmarkTest(unittest.TestCase):
def testBenchmarkPredicate(self): def testBenchmarkPredicate(self):
class PredicateBenchmark(TestBenchmark): class PredicateBenchmark(TestBenchmark):
@classmethod @classmethod
def ValueCanBeAddedPredicate(cls, value): def ValueCanBeAddedPredicate(cls, value, is_first_result):
return False return False
original_run_fn = user_story_runner.Run original_run_fn = user_story_runner.Run
......
...@@ -23,7 +23,7 @@ from telemetry.value import trace ...@@ -23,7 +23,7 @@ from telemetry.value import trace
class PageTestResults(object): class PageTestResults(object):
def __init__(self, output_stream=None, output_formatters=None, def __init__(self, output_stream=None, output_formatters=None,
progress_reporter=None, trace_tag='', output_dir=None, progress_reporter=None, trace_tag='', output_dir=None,
value_can_be_added_predicate=lambda v: True): value_can_be_added_predicate=lambda v, is_first: True):
""" """
Args: Args:
output_stream: The output stream to use to write test results. output_stream: The output stream to use to write test results.
...@@ -36,9 +36,10 @@ class PageTestResults(object): ...@@ -36,9 +36,10 @@ class PageTestResults(object):
used for buildbot. used for buildbot.
output_dir: A string specified the directory where to store the test output_dir: A string specified the directory where to store the test
artifacts, e.g: trace, videos,... artifacts, e.g: trace, videos,...
value_can_be_added_predicate: A function that takes an value.Value value_can_be_added_predicate: A function that takes two arguments:
instance as input. It returns True if the value can be added to the a value.Value instance and a boolean (True when the value is part
test results and False otherwise. of the first result for the user story). It returns True if the value
can be added to the test results and False otherwise.
""" """
# TODO(chrishenry): Figure out if trace_tag is still necessary. # TODO(chrishenry): Figure out if trace_tag is still necessary.
...@@ -55,6 +56,7 @@ class PageTestResults(object): ...@@ -55,6 +56,7 @@ class PageTestResults(object):
self._current_page_run = None self._current_page_run = None
self._all_page_runs = [] self._all_page_runs = []
self._all_user_stories = set()
self._representative_value_for_each_value_name = {} self._representative_value_for_each_value_name = {}
self._all_summary_values = [] self._all_summary_values = []
self._serialized_trace_file_ids_to_paths = {} self._serialized_trace_file_ids_to_paths = {}
...@@ -153,23 +155,23 @@ class PageTestResults(object): ...@@ -153,23 +155,23 @@ class PageTestResults(object):
self._current_page_run = user_story_run.UserStoryRun(page) self._current_page_run = user_story_run.UserStoryRun(page)
self._progress_reporter.WillRunPage(self) self._progress_reporter.WillRunPage(self)
def DidRunPage(self, page, discard_run=False): # pylint: disable=W0613 def DidRunPage(self, page): # pylint: disable=W0613
""" """
Args: Args:
page: The current page under test. page: The current page under test.
discard_run: Whether to discard the entire run and all of its
associated results.
""" """
assert self._current_page_run, 'Did not call WillRunPage.' assert self._current_page_run, 'Did not call WillRunPage.'
self._progress_reporter.DidRunPage(self) self._progress_reporter.DidRunPage(self)
if not discard_run:
self._all_page_runs.append(self._current_page_run) self._all_page_runs.append(self._current_page_run)
self._all_user_stories.add(self._current_page_run.user_story)
self._current_page_run = None self._current_page_run = None
def AddValue(self, value): def AddValue(self, value):
assert self._current_page_run, 'Not currently running test.' assert self._current_page_run, 'Not currently running test.'
self._ValidateValue(value) self._ValidateValue(value)
if not self._value_can_be_added_predicate(value): is_first_result = (
self._current_page_run.user_story not in self._all_user_stories)
if not self._value_can_be_added_predicate(value, is_first_result):
return return
# TODO(eakuefner/chrishenry): Add only one skip per pagerun assert here # TODO(eakuefner/chrishenry): Add only one skip per pagerun assert here
self._current_page_run.AddValue(value) self._current_page_run.AddValue(value)
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# found in the LICENSE file. # found in the LICENSE file.
import os import os
import unittest
from telemetry import page as page_module from telemetry import page as page_module
from telemetry.page import page_set from telemetry.page import page_set
...@@ -44,7 +45,6 @@ class PageTestResultsTest(base_test_results_unittest.BaseTestResultsUnittest): ...@@ -44,7 +45,6 @@ class PageTestResultsTest(base_test_results_unittest.BaseTestResultsUnittest):
self.assertTrue(results.all_page_runs[0].failed) self.assertTrue(results.all_page_runs[0].failed)
self.assertTrue(results.all_page_runs[1].ok) self.assertTrue(results.all_page_runs[1].ok)
def testSkips(self): def testSkips(self):
results = page_test_results.PageTestResults() results = page_test_results.PageTestResults()
results.WillRunPage(self.pages[0]) results.WillRunPage(self.pages[0])
...@@ -84,38 +84,6 @@ class PageTestResultsTest(base_test_results_unittest.BaseTestResultsUnittest): ...@@ -84,38 +84,6 @@ class PageTestResultsTest(base_test_results_unittest.BaseTestResultsUnittest):
values = results.FindAllPageSpecificValuesNamed('a') values = results.FindAllPageSpecificValuesNamed('a')
assert len(values) == 2 assert len(values) == 2
def testResultsFiltering(self):
def AcceptValueNamed_a(value):
return value.name == 'a'
results = page_test_results.PageTestResults(
value_can_be_added_predicate=AcceptValueNamed_a)
results.WillRunPage(self.pages[0])
results.AddValue(scalar.ScalarValue(self.pages[0], 'a', 'seconds', 3))
results.AddValue(scalar.ScalarValue(self.pages[0], 'b', 'seconds', 3))
results.DidRunPage(self.pages[0])
results.WillRunPage(self.pages[1])
results.AddValue(scalar.ScalarValue(self.pages[1], 'a', 'seconds', 3))
results.AddValue(scalar.ScalarValue(self.pages[1], 'd', 'seconds', 3))
results.DidRunPage(self.pages[1])
results.PrintSummary()
values = results.FindPageSpecificValuesForPage(self.pages[0], 'a')
self.assertEquals(1, len(values))
v = values[0]
self.assertEquals(v.name, 'a')
self.assertEquals(v.page, self.pages[0])
values = results.FindPageSpecificValuesForPage(self.pages[0], 'b')
self.assertEquals(0, len(values))
values = results.FindAllPageSpecificValuesNamed('a')
self.assertEquals(len(values), 2)
values = results.all_page_specific_values
self.assertEquals(len(values), 2)
def testUrlIsInvalidValue(self): def testUrlIsInvalidValue(self):
results = page_test_results.PageTestResults() results = page_test_results.PageTestResults()
results.WillRunPage(self.pages[0]) results.WillRunPage(self.pages[0])
...@@ -266,3 +234,69 @@ class PageTestResultsTest(base_test_results_unittest.BaseTestResultsUnittest): ...@@ -266,3 +234,69 @@ class PageTestResultsTest(base_test_results_unittest.BaseTestResultsUnittest):
results.CleanUp() results.CleanUp()
self.assertFalse(results.FindAllTraceValues()) self.assertFalse(results.FindAllTraceValues())
class PageTestResultsFilterTest(unittest.TestCase):
def setUp(self):
ps = page_set.PageSet(file_path=os.path.dirname(__file__))
ps.AddUserStory(page_module.Page('http://www.foo.com/', ps, ps.base_dir))
ps.AddUserStory(page_module.Page('http://www.bar.com/', ps, ps.base_dir))
self.page_set = ps
@property
def pages(self):
return self.page_set.pages
def testFilterValue(self):
def AcceptValueNamed_a(value, _):
return value.name == 'a'
results = page_test_results.PageTestResults(
value_can_be_added_predicate=AcceptValueNamed_a)
results.WillRunPage(self.pages[0])
results.AddValue(scalar.ScalarValue(self.pages[0], 'a', 'seconds', 3))
results.AddValue(scalar.ScalarValue(self.pages[0], 'b', 'seconds', 3))
results.DidRunPage(self.pages[0])
results.WillRunPage(self.pages[1])
results.AddValue(scalar.ScalarValue(self.pages[1], 'a', 'seconds', 3))
results.AddValue(scalar.ScalarValue(self.pages[1], 'd', 'seconds', 3))
results.DidRunPage(self.pages[1])
results.PrintSummary()
self.assertEquals(
[('a', 'http://www.foo.com/'), ('a', 'http://www.bar.com/')],
[(v.name, v.page.url) for v in results.all_page_specific_values])
def testFilterIsFirstResult(self):
def AcceptSecondValues(_, is_first_result):
return not is_first_result
results = page_test_results.PageTestResults(
value_can_be_added_predicate=AcceptSecondValues)
# First results (filtered out)
results.WillRunPage(self.pages[0])
results.AddValue(scalar.ScalarValue(self.pages[0], 'a', 'seconds', 7))
results.AddValue(scalar.ScalarValue(self.pages[0], 'b', 'seconds', 8))
results.DidRunPage(self.pages[0])
results.WillRunPage(self.pages[1])
results.AddValue(scalar.ScalarValue(self.pages[1], 'a', 'seconds', 5))
results.AddValue(scalar.ScalarValue(self.pages[1], 'd', 'seconds', 6))
results.DidRunPage(self.pages[1])
# Second results
results.WillRunPage(self.pages[0])
results.AddValue(scalar.ScalarValue(self.pages[0], 'a', 'seconds', 3))
results.AddValue(scalar.ScalarValue(self.pages[0], 'b', 'seconds', 4))
results.DidRunPage(self.pages[0])
results.WillRunPage(self.pages[1])
results.AddValue(scalar.ScalarValue(self.pages[1], 'a', 'seconds', 1))
results.AddValue(scalar.ScalarValue(self.pages[1], 'd', 'seconds', 2))
results.DidRunPage(self.pages[1])
results.PrintSummary()
expected_values = [
('a', 'http://www.foo.com/', 3),
('b', 'http://www.foo.com/', 4),
('a', 'http://www.bar.com/', 1),
('d', 'http://www.bar.com/', 2)]
actual_values = [(v.name, v.page.url, v.value)
for v in results.all_page_specific_values]
self.assertEquals(expected_values, actual_values)
...@@ -108,7 +108,7 @@ def _GetProgressReporter(output_skipped_tests_summary, suppress_gtest_report): ...@@ -108,7 +108,7 @@ def _GetProgressReporter(output_skipped_tests_summary, suppress_gtest_report):
def CreateResults(benchmark_metadata, options, def CreateResults(benchmark_metadata, options,
value_can_be_added_predicate=lambda v: True): value_can_be_added_predicate=lambda v, is_first: True):
""" """
Args: Args:
options: Contains the options specified in AddResultsOptions. options: Contains the options specified in AddResultsOptions.
......
...@@ -218,7 +218,6 @@ def Run(test, user_story_set, expectations, finder_options, results, ...@@ -218,7 +218,6 @@ def Run(test, user_story_set, expectations, finder_options, results,
user_story_groups = GetUserStoryGroupsWithSameSharedUserStoryClass( user_story_groups = GetUserStoryGroupsWithSameSharedUserStoryClass(
user_stories) user_stories)
user_story_with_discarded_first_results = set()
for group in user_story_groups: for group in user_story_groups:
state = None state = None
...@@ -250,14 +249,7 @@ def Run(test, user_story_set, expectations, finder_options, results, ...@@ -250,14 +249,7 @@ def Run(test, user_story_set, expectations, finder_options, results,
try: try:
if state: if state:
_CheckThermalThrottling(state.platform) _CheckThermalThrottling(state.platform)
# TODO(slamm): Make discard_first_result part of user_story API. results.DidRunPage(user_story)
# https://crbug.com/440101
discard_current_run = (
getattr(test, 'discard_first_result', False) and
user_story not in user_story_with_discarded_first_results)
if discard_current_run:
user_story_with_discarded_first_results.add(user_story)
results.DidRunPage(user_story, discard_run=discard_current_run)
except Exception: except Exception:
if not has_existing_exception: if not has_existing_exception:
raise raise
......
...@@ -355,61 +355,6 @@ class UserStoryRunnerTest(unittest.TestCase): ...@@ -355,61 +355,6 @@ class UserStoryRunnerTest(unittest.TestCase):
# The AppCrashException gets added as a failure. # The AppCrashException gets added as a failure.
self.assertEquals(1, len(self.results.failures)) self.assertEquals(1, len(self.results.failures))
def testDiscardFirstResult(self):
us = user_story_set.UserStorySet()
us.AddUserStory(DummyLocalUserStory(TestSharedPageState))
us.AddUserStory(DummyLocalUserStory(TestSharedPageState))
class Measurement(page_test.PageTest):
@property
def discard_first_result(self):
return True
def RunPage(self, page, _, results):
results.AddValue(string.StringValue(page, 'test', 't', page.name))
def ValidateAndMeasurePage(self, page, tab, results):
pass
results = results_options.CreateResults(
EmptyMetadataForTest(), self.options)
user_story_runner.Run(
Measurement(), us, self.expectations, self.options, results)
self.assertEquals(0, GetNumberOfSuccessfulPageRuns(results))
self.assertEquals(0, len(results.failures))
self.assertEquals(0, len(results.all_page_specific_values))
results = results_options.CreateResults(
EmptyMetadataForTest(), self.options)
self.options.page_repeat = 1
self.options.pageset_repeat = 2
user_story_runner.Run(
Measurement(), us, self.expectations, self.options, results)
self.assertEquals(2, GetNumberOfSuccessfulPageRuns(results))
self.assertEquals(0, len(results.failures))
self.assertEquals(2, len(results.all_page_specific_values))
results = results_options.CreateResults(
EmptyMetadataForTest(), self.options)
self.options.page_repeat = 2
self.options.pageset_repeat = 1
user_story_runner.Run(
Measurement(), us, self.expectations, self.options, results)
self.assertEquals(2, GetNumberOfSuccessfulPageRuns(results))
self.assertEquals(0, len(results.failures))
self.assertEquals(2, len(results.all_page_specific_values))
results = results_options.CreateResults(
EmptyMetadataForTest(), self.options)
self.options.page_repeat = 1
self.options.pageset_repeat = 1
user_story_runner.Run(
Measurement(), us, self.expectations, self.options, results)
self.assertEquals(0, GetNumberOfSuccessfulPageRuns(results))
self.assertEquals(0, len(results.failures))
self.assertEquals(0, len(results.all_page_specific_values))
def testPagesetRepeat(self): def testPagesetRepeat(self):
us = user_story_set.UserStorySet() us = user_story_set.UserStorySet()
us.AddUserStory(DummyLocalUserStory(TestSharedPageState, name='blank')) us.AddUserStory(DummyLocalUserStory(TestSharedPageState, name='blank'))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment