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

Side by Side Diff: scripts/slave/recipe_modules/perf_try/api.py

Issue 2061893003: Build delegation for perf tryjobs (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Refine request build procedures Created 4 years, 6 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
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """API for the perf try job recipe module. 5 """API for the perf try job recipe module.
6 6
7 This API is meant to enable the perf try job recipe on any chromium-supported 7 This API is meant to enable the perf try job recipe on any chromium-supported
8 platform for any test that can be run via buildbot, perf or otherwise. 8 platform for any test that can be run via buildbot, perf or otherwise.
9 """ 9 """
10 10
11 import re 11 import re
12 import urllib 12 import urllib
13 import uuid
13 14
14 from recipe_engine import recipe_api 15 from recipe_engine import recipe_api
16 from . import build_state
15 17
16 PERF_CONFIG_FILE = 'tools/run-perf-test.cfg' 18 PERF_CONFIG_FILE = 'tools/run-perf-test.cfg'
17 WEBKIT_PERF_CONFIG_FILE = 'third_party/WebKit/Tools/run-perf-test.cfg' 19 WEBKIT_PERF_CONFIG_FILE = 'third_party/WebKit/Tools/run-perf-test.cfg'
18 PERF_BENCHMARKS_PATH = 'tools/perf/benchmarks' 20 PERF_BENCHMARKS_PATH = 'tools/perf/benchmarks'
19 PERF_MEASUREMENTS_PATH = 'tools/perf/measurements' 21 PERF_MEASUREMENTS_PATH = 'tools/perf/measurements'
20 BUILDBOT_BUILDERNAME = 'BUILDBOT_BUILDERNAME' 22 BUILDBOT_BUILDERNAME = 'BUILDBOT_BUILDERNAME'
21 BENCHMARKS_JSON_FILE = 'benchmarks.json' 23 BENCHMARKS_JSON_FILE = 'benchmarks.json'
22 24
23 CLOUD_RESULTS_LINK = (r'\s(?P<VALUES>http://storage.googleapis.com/' 25 CLOUD_RESULTS_LINK = (r'\s(?P<VALUES>http://storage.googleapis.com/'
24 'chromium-telemetry/html-results/results-[a-z0-9-_]+)\s') 26 'chromium-telemetry/html-results/results-[a-z0-9-_]+)\s')
25 PROFILER_RESULTS_LINK = (r'\s(?P<VALUES>https://console.developers.google.com/' 27 PROFILER_RESULTS_LINK = (r'\s(?P<VALUES>https://console.developers.google.com/'
26 'm/cloudstorage/b/[a-z-]+/o/profiler-[a-z0-9-_.]+)\s') 28 'm/cloudstorage/b/[a-z-]+/o/profiler-[a-z0-9-_.]+)\s')
27 RESULTS_BANNER = """ 29 RESULTS_BANNER = """
28 ===== PERF TRY JOB RESULTS ===== 30 ===== PERF TRY JOB RESULTS =====
29 31
30 Test Command: %(command)s 32 Test Command: %(command)s
31 Test Metric: %(metric)s 33 Test Metric: %(metric)s
32 Relative Change: %(relative_change).05f%% 34 Relative Change: %(relative_change).05f%%
33 Standard Error: +- %(std_err).05f delta 35 Standard Error: +- %(std_err).05f delta
34 36
35 %(results)s 37 %(results)s
36 """ 38 """
37 39 SERVICE_ACCOUNT = 'chromium_bisect'
38 40
39 class PerfTryJobApi(recipe_api.RecipeApi): 41 class PerfTryJobApi(recipe_api.RecipeApi):
40 42
41 def __init__(self, *args, **kwargs): 43 def __init__(self, *args, **kwargs):
42 super(PerfTryJobApi, self).__init__(*args, **kwargs) 44 super(PerfTryJobApi, self).__init__(*args, **kwargs)
43 45
44 def start_perf_try_job(self, affected_files, bot_update_step, bot_db): 46 def start_perf_try_job(self, affected_files, bot_update_step, bot_db):
45 """Entry point pert tryjob or CQ tryjob.""" 47 """Entry point pert tryjob or CQ tryjob."""
46 perf_config = self._get_perf_config(affected_files) 48 perf_config = self._get_perf_config(affected_files)
47 if perf_config: 49 if perf_config:
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 overall_success = all(v == 0 for v in retcodes) 211 overall_success = all(v == 0 for v in retcodes)
210 return { 212 return {
211 'results': all_values, 213 'results': all_values,
212 'ret_code': overall_success, 214 'ret_code': overall_success,
213 'output': ''.join(overall_output) 215 'output': ''.join(overall_output)
214 } 216 }
215 217
216 def _build_and_run_tests(self, cfg, update_step, bot_db, revision, 218 def _build_and_run_tests(self, cfg, update_step, bot_db, revision,
217 **kwargs): 219 **kwargs):
218 """Compiles binaries and runs tests for a given a revision.""" 220 """Compiles binaries and runs tests for a given a revision."""
221 with_patch = kwargs.get('name') == 'With Patch'
219 update_step = self._checkout_revision(update_step, bot_db, revision) 222 update_step = self._checkout_revision(update_step, bot_db, revision)
220 self._compile(kwargs['name'], self.m.properties['mastername'], 223 if update_step.presentation.properties:
221 self.m.properties['buildername'], update_step, bot_db) 224 revision = update_step.presentation.properties['got_revision']
222 225 revision = build_state.BuildState(self, revision, with_patch)
RobertoCN 2016/06/24 18:46:37 consider renaming the variables. is revision a has
Ziqi Xiong 2016/06/27 18:47:54 Done.
226 # request build and wait for it only when the build is nonexistent
227 if with_patch or not self._gsutil_file_exists(revision.build_file_path):
228 try:
229 self._request_build(revision, with_patch)
230 self._wait_for(revision)
231 except Exception, e:
232 raise self.m.step.StepFailure('Error occurs when building %s: %s' % (
233 revision.build_id, str(e)))
234 self._download_build(update_step, bot_db, revision)
223 if self.m.chromium.c.TARGET_PLATFORM == 'android': 235 if self.m.chromium.c.TARGET_PLATFORM == 'android':
224 self.m.chromium_android.adb_install_apk('ChromePublic.apk') 236 self.m.chromium_android.adb_install_apk('ChromePublic.apk')
225 237
226 return self._run_test(cfg, **kwargs) 238 return self._run_test(cfg, **kwargs)
227 239
240 def _gsutil_file_exists(self, path):
241 """Returns True if a file exists at the given GS path."""
242 try:
243 self.m.gsutil(['ls', path], name='check.file.exist')
244 except self.m.step.StepFailure: # pragma: no cover
245 return False
246 return True
247
248 # Duplicate code from auto_bisect.revision_state._request_build
249 def _request_build(self, revision, with_patch):
250 if self.m.chromium.c.TARGET_PLATFORM == 'android':
251 self.m.chromium_android.clean_local_files()
252 else:
253 # Removes any chrome temporary files or build.dead directories.
254 self.m.chromium.cleanup_temp()
255 if with_patch:
256 properties = {
257 'parent_got_revision': revision.commit_hash,
258 'clobber': True,
259 'build_archive_url': revision.build_file_path,
260 'issue': self.m.properties['issue'],
261 'patch_storage': self.m.properties['patch_storage'],
262 'patchset': self.m.properties['patchset'],
263 'rietveld': self.m.properties['rietveld']
264 }
265 else:
266 properties = {
267 'parent_got_revision': revision.commit_hash,
268 'clobber': True,
269 'build_archive_url': revision.build_file_path,
270 }
271 bot_name = self.get_builder_bot_for_this_platform()
272 build_details = {
273 'bucket': 'master.' + self.m.properties['mastername'],
274 'parameters': {
275 'buildername': bot_name,
276 'properties': properties
277 },
278 'client_operation_id': uuid.uuid4().hex,
279 'tags':{}
280 }
281 result = self.m.buildbucket.put(
282 [build_details],
283 self.m.service_account.get_json_path(SERVICE_ACCOUNT))
284 revision.build_id = result.stdout['results'][0]['build']['id']
285
286
287 def _wait_for(self, revision):
288 while True:
289 if revision.is_completed():
290 if revision.is_build_archived:
291 break
292 raise self.m.step.StepFailure('Build %s fails' % revision.build_id)
293 else:
294 self.m.python.inline(
295 'sleeping',
296 """
297 import sys
298 import time
299 time.sleep(20*60)
300 sys.exit(0)
301 """)
302
303 # Duplicate code from auto_bisect.api.start_test_run_for_bisect
304 def _download_build(self, update_step, bot_db,
305 revision, run_locally=False,
306 skip_download=False):
307 mastername = self.m.properties.get('mastername')
308 buildername = self.m.properties.get('buildername')
309 bot_config = bot_db.get_bot_config(mastername, buildername)
310 build_archive_url = revision.build_file_path
311 if not skip_download:
312 if self.m.chromium.c.TARGET_PLATFORM == 'android':
313 # The best way to ensure the old build directory is not used is to
314 # remove it.
315 build_dir = self.m.chromium.c.build_dir.join(
316 self.m.chromium.c.build_config_fs)
317 self.m.file.rmtree('build directory', build_dir)
318
319 # The way android builders on tryserver.chromium.perf are archived is
320 # different from builders on chromium.perf. In order to support both
321 # forms of archives, we added this temporary hack until builders are
322 # fixed. See http://crbug.com/535218.
323 zip_dir = self.m.path.join(self.m.path['checkout'], 'full-build-linux')
324 if self.m.path.exists(zip_dir): # pragma: no cover
325 self.m.file.rmtree('full-build-linux directory', zip_dir)
326 gs_bucket = 'gs://%s/' % revision.bucket
327 archive_path = build_archive_url[len(gs_bucket):]
328 self.m.chromium_android.download_build(
329 bucket=bot_config['bucket'],
330 path=archive_path)
331
332 # The way android builders on tryserver.chromium.perf are archived is
333 # different from builders on chromium.perf. In order to support both
334 # forms of archives, we added this temporary hack until builders are
335 # fixed. See http://crbug.com/535218.
336 if self.m.path.exists(zip_dir): # pragma: no cover
337 self.m.python.inline(
338 'moving full-build-linux to out/Release',
339 """
340 import shutil
341 import sys
342 shutil.move(sys.argv[1], sys.argv[2])
343 """,
344 args=[zip_dir, build_dir])
345 else:
346 self.m.chromium_tests.download_and_unzip_build(
347 mastername, buildername, update_step, bot_db,
348 build_archive_url=build_archive_url,
349 build_revision=revision.commit_hash,
350 override_bot_type='tester')
351
352 # Duplicate code from auto_bisect.bisector.get_builder_bot_for_this_platform
353 def get_builder_bot_for_this_platform(self):
354 bot_name = self.m.properties.get('buildername', '')
355 if 'win' in bot_name:
356 if any(b in bot_name for b in ['x64', 'gpu']):
357 return 'winx64_bisect_builder'
358 return 'win_perf_bisect_builder'
359
360 if 'android' in bot_name:
361 if 'nexus9' in bot_name:
362 return 'android_arm64_perf_bisect_builder'
363 return 'android_perf_bisect_builder'
364
365 if 'mac' in bot_name:
366 return 'mac_perf_bisect_builder'
367
368 return 'linux_perf_bisect_builder'
369
228 def _load_config_file(self, name, src_path, **kwargs): 370 def _load_config_file(self, name, src_path, **kwargs):
229 """Attempts to load the specified config file and grab config dict.""" 371 """Attempts to load the specified config file and grab config dict."""
230 step_result = self.m.python( 372 step_result = self.m.python(
231 name, 373 name,
232 self.resource('load_config_to_json.py'), 374 self.resource('load_config_to_json.py'),
233 ['--source', src_path, '--output_json', self.m.json.output()], 375 ['--source', src_path, '--output_json', self.m.json.output()],
234 **kwargs) 376 **kwargs)
235 if not step_result.json.output: # pragma: no cover 377 if not step_result.json.output: # pragma: no cover
236 raise self.m.step.StepFailure('Loading config file failed. [%s]' % 378 raise self.m.step.StepFailure('Loading config file failed. [%s]' %
237 src_path) 379 src_path)
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 653
512 def _prepend_src_to_path_in_command(test_cfg): 654 def _prepend_src_to_path_in_command(test_cfg):
513 command_to_run = [] 655 command_to_run = []
514 for v in test_cfg.get('command').split(): 656 for v in test_cfg.get('command').split():
515 if v in ['./tools/perf/run_benchmark', 657 if v in ['./tools/perf/run_benchmark',
516 'tools/perf/run_benchmark', 658 'tools/perf/run_benchmark',
517 'tools\\perf\\run_benchmark']: 659 'tools\\perf\\run_benchmark']:
518 v = 'src/tools/perf/run_benchmark' 660 v = 'src/tools/perf/run_benchmark'
519 command_to_run.append(v) 661 command_to_run.append(v)
520 test_cfg.update({'command': ' '.join(command_to_run)}) 662 test_cfg.update({'command': ' '.join(command_to_run)})
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698