| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2016 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 import csv |
| 6 import json |
| 7 import os |
| 8 import shutil |
| 9 |
| 10 import chrome_cache |
| 11 import common_util |
| 12 import emulation |
| 13 import sandwich_metrics |
| 14 import sandwich_misc |
| 15 import sandwich_runner |
| 16 import task_manager |
| 17 |
| 18 |
| 19 def NetworkSimulationTransformer(network_condition): |
| 20 """Creates a function that accepts a SandwichRunner as a parameter and sets |
| 21 network emulation options on it. |
| 22 |
| 23 Args: |
| 24 network_condition: The network condition to apply to the sandwich runner. |
| 25 |
| 26 Returns: |
| 27 A callback transforming the SandwichRunner given in argument accordingly |
| 28 """ |
| 29 assert network_condition in emulation.NETWORK_CONDITIONS |
| 30 def Transformer(runner): |
| 31 assert isinstance(runner, sandwich_runner.SandwichRunner) |
| 32 runner.network_condition = network_condition |
| 33 return Transformer |
| 34 |
| 35 |
| 36 class SandwichTaskBuilder(task_manager.Builder): |
| 37 """A builder for a graph of tasks, each prepares or invokes a SandwichRunner. |
| 38 """ |
| 39 |
| 40 def __init__(self, output_directory, job_path, url_repeat): |
| 41 """Constructor. |
| 42 |
| 43 Args: |
| 44 output_directory: As in task_manager.Builder.__init__ |
| 45 job_path: Path of the sandwich's job. |
| 46 url_repeat: Non null integer controlling how many times the URLs should be |
| 47 repeated in the benchmarks. |
| 48 """ |
| 49 task_manager.Builder.__init__(self, output_directory) |
| 50 self._job_path = job_path |
| 51 self._url_repeat = url_repeat |
| 52 self._default_final_tasks = [] |
| 53 |
| 54 self._original_wpr_task = None |
| 55 self._patched_wpr_task = None |
| 56 self._reference_cache_task = None |
| 57 self._subresources_for_urls_run_task = None |
| 58 self._subresources_for_urls_task = None |
| 59 |
| 60 @property |
| 61 def default_final_tasks(self): |
| 62 return self._default_final_tasks |
| 63 |
| 64 def _CreateSandwichRunner(self): |
| 65 """Create a runner for non benchmark purposes.""" |
| 66 runner = sandwich_runner.SandwichRunner() |
| 67 runner.LoadJob(self._job_path) |
| 68 return runner |
| 69 |
| 70 def OverridePathToWprArchive(self, original_wpr_path): |
| 71 """Sets the original WPR archive path's to be used. |
| 72 |
| 73 Args: |
| 74 original_wpr_path: Path of the original WPR archive to be used. |
| 75 """ |
| 76 self._original_wpr_task = \ |
| 77 self.CreateStaticTask('common/webpages.wpr', original_wpr_path) |
| 78 |
| 79 def PopulateWprRecordingTask(self): |
| 80 """Records the original WPR archive.""" |
| 81 @self.RegisterTask('common/webpages.wpr') |
| 82 def BuildOriginalWpr(): |
| 83 common_util.EnsureParentDirectoryExists(BuildOriginalWpr.path) |
| 84 runner = self._CreateSandwichRunner() |
| 85 runner.wpr_archive_path = BuildOriginalWpr.path |
| 86 runner.wpr_record = True |
| 87 runner.Run() |
| 88 |
| 89 self._original_wpr_task = BuildOriginalWpr |
| 90 |
| 91 def PopulateCommonPipelines(self): |
| 92 """Creates necessary tasks to produce initial cache archive. |
| 93 |
| 94 Also creates a task for producing a json file with a mapping of URLs to |
| 95 subresources (urls-resources.json). |
| 96 |
| 97 Here is the full dependency tree for the returned task: |
| 98 common/cache-ref-validation.log |
| 99 depends on: common/cache-ref.zip |
| 100 depends on: common/webpages-patched.wpr |
| 101 depends on: common/webpages.wpr |
| 102 depends on: common/urls-resources.json |
| 103 depends on: common/urls-resources-run/ |
| 104 depends on: common/webpages.wpr |
| 105 |
| 106 Returns: |
| 107 The last task of the pipeline. |
| 108 """ |
| 109 @self.RegisterTask('common/webpages-patched.wpr', [self._original_wpr_task]) |
| 110 def BuildPatchedWpr(): |
| 111 common_util.EnsureParentDirectoryExists(BuildPatchedWpr.path) |
| 112 shutil.copyfile(self._original_wpr_task.path, BuildPatchedWpr.path) |
| 113 sandwich_misc.PatchWpr(BuildPatchedWpr.path) |
| 114 |
| 115 @self.RegisterTask('common/cache-ref.zip', [BuildPatchedWpr]) |
| 116 def BuildReferenceCache(): |
| 117 runner = self._CreateSandwichRunner() |
| 118 runner.wpr_archive_path = BuildPatchedWpr.path |
| 119 runner.cache_archive_path = BuildReferenceCache.path |
| 120 runner.cache_operation = 'save' |
| 121 runner.Run() |
| 122 |
| 123 @self.RegisterTask('common/subresources-for-urls-run/', |
| 124 dependencies=[self._original_wpr_task]) |
| 125 def UrlsResourcesRun(): |
| 126 runner = self._CreateSandwichRunner() |
| 127 runner.wpr_archive_path = self._original_wpr_task.path |
| 128 runner.cache_operation = 'clear' |
| 129 runner.trace_output_directory = UrlsResourcesRun.path |
| 130 runner.Run() |
| 131 |
| 132 @self.RegisterTask('common/subresources-for-urls.json', [UrlsResourcesRun]) |
| 133 def ListUrlsResources(): |
| 134 json_content = sandwich_misc.ReadSubresourceMapFromBenchmarkOutput( |
| 135 UrlsResourcesRun.path) |
| 136 with open(ListUrlsResources.path, 'w') as output: |
| 137 json.dump(json_content, output) |
| 138 |
| 139 @self.RegisterTask('common/cache-ref-validation.log', |
| 140 [BuildReferenceCache, ListUrlsResources]) |
| 141 def ValidateReferenceCache(): |
| 142 json_content = json.load(open(ListUrlsResources.path)) |
| 143 ref_urls = set() |
| 144 for urls in json_content.values(): |
| 145 ref_urls.update(set(urls)) |
| 146 sandwich_misc.ValidateCacheArchiveContent( |
| 147 ref_urls, BuildReferenceCache.path) |
| 148 |
| 149 self._patched_wpr_task = BuildPatchedWpr |
| 150 self._reference_cache_task = BuildReferenceCache |
| 151 self._subresources_for_urls_run_task = UrlsResourcesRun |
| 152 self._subresources_for_urls_task = ListUrlsResources |
| 153 |
| 154 self._default_final_tasks.append(ValidateReferenceCache) |
| 155 return ValidateReferenceCache |
| 156 |
| 157 def PopulateLoadBenchmark(self, subresource_discoverer, |
| 158 runner_transformer_name, runner_transformer): |
| 159 """Populate benchmarking tasks from its setup tasks. |
| 160 |
| 161 Args: |
| 162 subresource_discoverer: Name of a subresources discoverer. |
| 163 runner_transformer: A function that takes an instance of SandwichRunner as |
| 164 parameter, would be applied immediately before SandwichRunner.Run(). |
| 165 runner_transformer_name: Name of the runner transformer used to generate |
| 166 task names. |
| 167 benchmark_name: The benchmark's name for that runner modifier. |
| 168 |
| 169 Here is the full dependency of the added tree for the returned task: |
| 170 <runner_transformer_name>/<subresource_discoverer>-metrics.csv |
| 171 depends on: <runner_transformer_name>/<subresource_discoverer>-run/ |
| 172 depends on: common/<subresource_discoverer>-cache.zip |
| 173 depends on: some tasks saved by PopulateCommonPipelines() |
| 174 depends on: common/<subresource_discoverer>-setup.json |
| 175 depends on: some tasks saved by PopulateCommonPipelines() |
| 176 |
| 177 Returns: |
| 178 task_manager.Task for |
| 179 <runner_transformer_name>/<subresource_discoverer>-metrics.csv |
| 180 """ |
| 181 assert subresource_discoverer in sandwich_misc.SUBRESOURCE_DISCOVERERS |
| 182 assert 'common' not in sandwich_misc.SUBRESOURCE_DISCOVERERS |
| 183 shared_task_prefix = os.path.join('common', subresource_discoverer) |
| 184 task_prefix = os.path.join(runner_transformer_name, subresource_discoverer) |
| 185 |
| 186 @self.RegisterTask(shared_task_prefix + '-setup.json', merge=True, |
| 187 dependencies=[self._subresources_for_urls_task]) |
| 188 def SetupBenchmark(): |
| 189 trace_path = os.path.join(self._subresources_for_urls_run_task.path, '0', |
| 190 sandwich_runner.TRACE_FILENAME) |
| 191 whitelisted_urls = sandwich_misc.ExtractDiscoverableUrls( |
| 192 trace_path, subresource_discoverer) |
| 193 |
| 194 urls_resources = json.load(open(self._subresources_for_urls_task.path)) |
| 195 # TODO(gabadie): Implement support for multiple URLs in this Task. |
| 196 assert len(urls_resources) == 1 |
| 197 url = urls_resources.keys()[0] |
| 198 url_resources = urls_resources[url] |
| 199 common_util.EnsureParentDirectoryExists(SetupBenchmark.path) |
| 200 with open(SetupBenchmark.path, 'w') as output: |
| 201 json.dump({ |
| 202 'cache_whitelist': [url for url in whitelisted_urls], |
| 203 'url_resources': url_resources, |
| 204 }, output) |
| 205 |
| 206 @self.RegisterTask(shared_task_prefix + '-cache.zip', merge=True, |
| 207 dependencies=[ |
| 208 SetupBenchmark, self._reference_cache_task]) |
| 209 def BuildBenchmarkCacheArchive(): |
| 210 setup = json.load(open(SetupBenchmark.path)) |
| 211 chrome_cache.ApplyUrlWhitelistToCacheArchive( |
| 212 cache_archive_path=self._reference_cache_task.path, |
| 213 whitelisted_urls=setup['cache_whitelist'], |
| 214 output_cache_archive_path=BuildBenchmarkCacheArchive.path) |
| 215 |
| 216 @self.RegisterTask(task_prefix + '-run/', |
| 217 dependencies=[BuildBenchmarkCacheArchive]) |
| 218 def RunBenchmark(): |
| 219 runner = self._CreateSandwichRunner() |
| 220 # runner.record_video = True |
| 221 runner.job_repeat = self._url_repeat |
| 222 runner_transformer(runner) |
| 223 runner.wpr_archive_path = self._patched_wpr_task.path |
| 224 runner.wpr_out_log_path = os.path.join(RunBenchmark.path, 'wpr.log') |
| 225 runner.cache_archive_path = BuildBenchmarkCacheArchive.path |
| 226 runner.cache_operation = 'push' |
| 227 runner.trace_output_directory = RunBenchmark.path |
| 228 runner.Run() |
| 229 |
| 230 @self.RegisterTask(task_prefix + '-metrics.csv', |
| 231 dependencies=[RunBenchmark]) |
| 232 def ExtractMetrics(): |
| 233 sandwich_misc.VerifyBenchmarkOutputDirectory( |
| 234 SetupBenchmark.path, RunBenchmark.path) |
| 235 trace_metrics_list = sandwich_metrics.PullMetricsFromOutputDirectory( |
| 236 RunBenchmark.path) |
| 237 trace_metrics_list.sort(key=lambda e: e['id']) |
| 238 with open(ExtractMetrics.path, 'w') as csv_file: |
| 239 writer = csv.DictWriter(csv_file, |
| 240 fieldnames=sandwich_metrics.CSV_FIELD_NAMES) |
| 241 writer.writeheader() |
| 242 for trace_metrics in trace_metrics_list: |
| 243 writer.writerow(trace_metrics) |
| 244 |
| 245 self._default_final_tasks.append(ExtractMetrics) |
| 246 return ExtractMetrics |
| OLD | NEW |