Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: tools/android/loading/sandwich_tasks.py

Issue 1872313002: sandwich: Implement SandwichTaskBuilder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 logging
8 import os
9 import re
10 import shutil
11
12 import chrome_cache
13 import emulation
14 import loading_trace
15 import loading_trace_analyzer
16 import sandwich_metrics
17 import sandwich_misc
18 from sandwich_runner import SandwichRunner
19 import task_manager
20
21
22 def NoRunnerModification(runner):
pasko 2016/04/11 14:54:08 This would be a NoOpTransformer, but actually I wo
gabadie 2016/04/13 09:53:44 Done.
23 """Callback that don't modify a sandwich runner.
24
25 Args:
26 runner: A SandwichRunner to modify.
27 """
28 assert isinstance(runner, SandwichRunner)
29
30
31 def EmulateNetworkModifier(network_condition):
pasko 2016/04/11 14:54:08 As mentioned before, NetworkSimulationTransformer
gabadie 2016/04/13 09:53:44 Done.
32 """Factory that create callbacks to modify a sandwich runner for a specific
pasko 2016/04/11 14:54:08 Creates a function that accepts a SandwichRunner a
gabadie 2016/04/13 09:53:44 Done.
33 browser sided network emulation.
34
35 Args:
36 network_condition: The network condition to apply to the sandwich runner.
37
38 Returns:
39 A callback modifying the runner given in argument accordingly
pasko 2016/04/11 14:54:08 needs to mention |SandwichRunner|
gabadie 2016/04/13 09:53:44 Done.
40 """
41 assert network_condition in emulation.NETWORK_CONDITIONS
42 def RunnerModifier(runner):
pasko 2016/04/11 14:54:09 s/runner/sandwich_runner/
gabadie 2016/04/13 09:53:44 Done.
43 runner.network_condition = network_condition
pasko 2016/04/11 14:54:08 assert isinstance(sandwich_runner, SandwichRunner)
gabadie 2016/04/13 09:53:45 Done.
44 return RunnerModifier
45
46
47 class SandwichTaskBuilder(task_manager.Builder):
48 """Sandwich's tasks builder."""
pasko 2016/04/11 14:54:09 Needs more documentation. Something like: """A bu
gabadie 2016/04/13 09:53:44 Done.
49
50 def __init__(self, output_directory, job_path, url_repeat):
51 """Constructor.
52
53 Args:
54 output_directory: Output directory where the dynamic tasks will be
pasko 2016/04/11 14:54:09 output_directory: As in task_manager.Builder.__ini
gabadie 2016/04/13 09:53:44 Oups... Done!
55 generated to.
56 """
57 task_manager.Builder.__init__(self, output_directory)
58 self._job_path = job_path
59 self._url_repeat = url_repeat
60 self.default_final_tasks = []
pasko 2016/04/11 14:54:08 we want to avoid callers of this class from modify
gabadie 2016/04/13 09:53:44 used a @proprety. Done.
pasko 2016/04/14 12:34:42 did you want to allow users of the object to overw
gabadie 2016/04/14 15:43:32 Sorry, I still don't see the issue with a simple g
61
62 def __enter__(self):
pasko 2016/04/11 14:54:08 not needed?
gabadie 2016/04/13 09:53:44 My bad. Done
63 return self
64
65 def __exit__(self, exc_type, exc_val, exc_tb):
pasko 2016/04/11 14:54:08 not needed any more?
gabadie 2016/04/13 09:53:44 Done.
66 pass
67
68 def _CreateRunner(self):
pasko 2016/04/11 14:54:08 This methd is called only once, it is preferable t
gabadie 2016/04/13 09:53:44 Done.
69 """Create a runner that may be used for benchmark purposes."""
70 runner = self._CreateNonBenchmarkRunner()
71 runner.record_video = True
72 runner.job_repeat = self._url_repeat
73 return runner
74
75 def _CreateNonBenchmarkRunner(self):
pasko 2016/04/11 14:54:09 _CreateSandwichRunner to be clearer
gabadie 2016/04/13 09:53:45 Done.
76 """Create a runner for non benchmark purposes."""
77 runner = SandwichRunner()
78 runner.LoadJob(self._job_path)
79 return runner
80
81 def SetOriginalWprPath(self, original_wpr_path):
pasko 2016/04/11 14:54:08 It is not clear what 'original' refers to. It woul
gabadie 2016/04/13 09:53:45 Done.
82 """Sets the original WPR archive path's to be used.
83
84 Args:
85 original_wpr_path: Path of the original WPR archive to be used.
86 """
87 return self.CreateStaticTask('webpages.wpr', original_wpr_path)
pasko 2016/04/11 14:54:09 'webpages.wpr' -> _WPR_ARCHIVE_NAME as a constant
gabadie 2016/04/13 09:53:44 Done.
88
89 def PopulateWPRRecordingTask(self):
pasko 2016/04/11 14:54:09 naming: s/WPR/Wpr/
gabadie 2016/04/13 09:53:45 Done.
90 """Records the original WPR archive."""
91 @self.RegisterTask('webpages.wpr')
92 def BuildOriginalWpr():
93 runner = self._CreateNonBenchmarkRunner()
94 runner.wpr_archive_path = BuildOriginalWpr.path
95 runner.wpr_record = True
96 runner.Run()
97
98 return BuildOriginalWpr
99
100 def PopulateCommonPipelines(self):
101 """Populates the pipeline that create the reference cache archive and list
pasko 2016/04/11 14:54:08 It makes sense to explain in each Populate* what s
gabadie 2016/04/13 09:53:45 Done.
102 of sub-resources per urls.
103
104 Returns:
105 The last task of the pipeline.
106 """
107 original_wpr_task = self.tasks['webpages.wpr']
108
109 @self.RegisterTask('webpages-patched.wpr', [original_wpr_task])
110 def BuildPatchedWpr():
111 shutil.copyfile(original_wpr_task.path, BuildPatchedWpr.path)
112 sandwich_misc.PatchWpr(BuildPatchedWpr.path)
113
114 @self.RegisterTask('cache-ref.zip', [BuildPatchedWpr])
115 def BuildReferenceCache():
116 runner = self._CreateNonBenchmarkRunner()
117 runner.wpr_archive_path = BuildPatchedWpr.path
118 runner.cache_archive_path = BuildReferenceCache.path
119 runner.cache_operation = 'save'
120 runner.Run()
121
122 # TODO(gabadie): It could be possible to generate the traces in the
123 # cache-ref.zip run, but we would need to implement an octopus dynamic
124 # task that can generate several files at a time.
pasko 2016/04/11 14:54:09 It is not clear what this TODO proposes, maybe rem
gabadie 2016/04/13 09:53:44 Done.
125 @self.RegisterTask('urls-resources-run/', [original_wpr_task])
126 def UrlsResourcesRun():
127 runner = self._CreateNonBenchmarkRunner()
128 runner.wpr_archive_path = original_wpr_task.path
129 runner.cache_operation = 'clear'
130 runner.trace_output_directory = UrlsResourcesRun.path
131 runner.Run()
132
133 @self.RegisterTask('urls-resources.json', [UrlsResourcesRun])
pasko 2016/04/11 14:54:08 subresources-for-urls.json would wake it clear whe
gabadie 2016/04/13 09:53:44 Done.
134 def ListUrlsResources():
135 json_content = sandwich_misc.ListResourcesUrls(UrlsResourcesRun.path)
136 with open(ListUrlsResources.path, 'w') as output:
137 json.dump(json_content, output)
138
139 @self.RegisterTask('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.default_final_tasks.append(ValidateReferenceCache)
150 return ValidateReferenceCache
151
152 def PopulateBenchmarkPipeline(self, setup_task, runner_modifier,
153 benchmark_name):
154 """Populate the a benchmark's pipeline from it's setup tasks.
155
156 Args:
157 setup_task: The benchmark's setup task.
158 runner_modifier: A callback to modify the sandwich runner.
159 benchmark_name: The benchmark's name for that runner modifier.
160
161 Returns:
162 The last task of the pipeline.
163 """
164 assert setup_task.name.endswith('-setup.json'), \
165 'Task \'{}\' is not a benchmark setup.'.format(setup_task.name)
166 benchmark_familly_name = setup_task.name[:-len('-setup.json')]
167 patched_wpr_task = self.tasks['webpages-patched.wpr']
168 reference_cache_task = self.tasks['cache-ref.zip']
169
170 @self.RegisterTask(benchmark_familly_name + '-cache.zip',
171 dependencies=[setup_task, reference_cache_task],
172 merge=True)
173 def BuildBenchmarkCacheArchive():
174 setup = json.load(open(setup_task.path))
175 chrome_cache.ApplyUrlWhitelistToCacheArchive(
176 cache_archive_path=reference_cache_task.path,
177 whitelisted_urls=setup['cache_whitelist'],
178 output_cache_archive_path=BuildBenchmarkCacheArchive.path)
179
180 @self.RegisterTask(benchmark_name + '-run/',
181 dependencies=[BuildBenchmarkCacheArchive])
182 def RunBenchmark():
183 runner = self._CreateRunner()
184 runner_modifier(runner)
185 runner.wpr_archive_path = patched_wpr_task.path
186 runner.wpr_out_log_path = os.path.join(RunBenchmark.path, 'wpr.log')
187 runner.cache_archive_path = BuildBenchmarkCacheArchive.path
188 runner.cache_operation = 'push'
189 runner.trace_output_directory = RunBenchmark.path
190 runner.Run()
191
192 @self.RegisterTask(benchmark_name + '-metrics.csv',
193 dependencies=[RunBenchmark])
194 def ExtractMetrics():
195 sandwich_misc.VerifyBenchmarkOutputDirectory(
196 setup_task.path, RunBenchmark.path)
197 trace_metrics_list = sandwich_metrics.PullMetricsFromOutputDirectory(
198 RunBenchmark.path)
199 trace_metrics_list.sort(key=lambda e: e['id'])
200 with open(ExtractMetrics.path, 'w') as csv_file:
201 writer = csv.DictWriter(csv_file,
202 fieldnames=sandwich_metrics.CSV_FIELD_NAMES)
203 writer.writeheader()
204 for trace_metrics in trace_metrics_list:
205 writer.writerow(trace_metrics)
206
207 self.default_final_tasks.append(ExtractMetrics)
208 return ExtractMetrics
209
210 def PopulateFullCacheLoadBenchmark(self, benchmark_name='fullcache',
211 runner_modifier=NoRunnerModification):
212 """Populates the full cache load benchmark's pipeline.
213
214 Args:
pasko 2016/04/11 14:54:08 need args here
gabadie 2016/04/13 09:53:44 My bad. Done.
215
216 Returns:
217 The last task of the pipeline.
218 """
219 urls_resources_task = self.tasks['urls-resources.json']
220
221 @self.RegisterTask('fullcache-setup.json',
222 dependencies=[urls_resources_task],
223 merge=True)
224 def SetupBenchmark():
225 urls_resources = json.load(open(urls_resources_task.path))
226 assert len(urls_resources) == 1, \
227 "This recipe is not ready for multiple urls."
228 url = urls_resources.keys()[0]
229 url_resources = urls_resources[url]
230 with open(SetupBenchmark.path, 'w') as output:
231 json.dump({
232 'cache_whitelist': url_resources,
233 'url_resources': url_resources,
234 }, output)
235
236
237 return self.PopulateBenchmarkPipeline(
238 SetupBenchmark, runner_modifier, benchmark_name)
239
240 def PopulateClearCacheLoadBenchmark(self, benchmark_name='clearcache',
241 runner_modifier=NoRunnerModification):
242 """Populates the clear cache load benchmark's pipeline.
243
244 Returns:
245 The last task of the pipeline.
246 """
247 urls_resources_task = self.tasks['urls-resources.json']
248
249 @self.RegisterTask('clearcache-setup.json',
250 dependencies=[urls_resources_task],
251 merge=True)
252 def SetupBenchmark():
253 urls_resources = json.load(open(urls_resources_task.path))
254 assert len(urls_resources) == 1, \
255 "This recipe is not ready for multiple urls."
256 url = urls_resources.keys()[0]
257 url_resources = urls_resources[url]
258 with open(SetupBenchmark.path, 'w') as output:
259 json.dump({
260 'cache_whitelist': [],
261 'url_resources': url_resources,
262 }, output)
263
264 return self.PopulateBenchmarkPipeline(
265 SetupBenchmark, runner_modifier, benchmark_name)
266
267 def PopulateNoStatePrefetchLoadBenchmark(self, benchmark_name='prefetch',
268 runner_modifier=NoRunnerModification):
269 """Populates the NoState-Prefetch load benchmark's pipeline.
270
271 Returns:
272 The last task of the pipeline.
273 """
274 # TODO(gabadie): make it generic for the different sub-resource discoverer.
275 urls_resources_run_task = self.tasks['urls-resources-run/']
pasko 2016/04/11 14:54:08 urls-resources-run/ and urls-resources.json are us
gabadie 2016/04/13 09:53:44 Done.
276 urls_resources_task = self.tasks['urls-resources.json']
277
278 @self.RegisterTask('prefetch-setup.json',
279 dependencies=[urls_resources_task],
280 merge=True)
281 def SetupBenchmark():
282 trace_path = os.path.join(urls_resources_run_task.path, '0/trace.json')
283 whitelisted_urls = sandwich_misc.ExtractDiscoverableUrls(
284 trace_path, sandwich_misc.HTML_PRELOAD_SCANNER_DISCOVERER)
285
286 urls_resources = json.load(open(urls_resources_task.path))
287 assert len(urls_resources) == 1, \
288 "This recipe is not ready for multiple urls."
289 url = urls_resources.keys()[0]
290 url_resources = urls_resources[url]
291 with open(SetupBenchmark.path, 'w') as output:
292 json.dump({
293 'cache_whitelist': [url for url in whitelisted_urls],
294 'url_resources': url_resources,
295 }, output)
296
297 return self.PopulateBenchmarkPipeline(
298 SetupBenchmark, runner_modifier, benchmark_name)
OLDNEW
« tools/android/loading/sandwich.py ('K') | « tools/android/loading/sandwich_misc.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698