Home | History | Annotate | Download | only in recipes
      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
      3 # found in the LICENSE file.
      4 
      5 
      6 import math
      7 
      8 
      9 DEPS = [
     10   'core',
     11   'ct',
     12   'depot_tools/gsutil',
     13   'flavor',
     14   'recipe_engine/context',
     15   'recipe_engine/file',
     16   'recipe_engine/json',
     17   'recipe_engine/path',
     18   'recipe_engine/properties',
     19   'recipe_engine/step',
     20   'recipe_engine/time',
     21   'run',
     22   'skia_swarming',
     23   'vars',
     24 ]
     25 
     26 
     27 SKPS_VERSION_FILE = 'skps_version'
     28 CT_SKPS_ISOLATE = 'ct_skps.isolate'
     29 
     30 # Do not batch archive more slaves than this value. This is used to prevent
     31 # no output timeouts in the 'isolate tests' step.
     32 MAX_SLAVES_TO_BATCHARCHIVE = 100
     33 
     34 TOOL_TO_DEFAULT_SKPS_PER_SLAVE = {
     35     'dm': 10000,
     36     'nanobench': 1000,
     37     'get_images_from_skps': 10000,
     38 }
     39 
     40 # The SKP repository to use.
     41 DEFAULT_SKPS_CHROMIUM_BUILD = 'c37e844a6f8708-eee762104c75bd'
     42 
     43 
     44 def RunSteps(api):
     45   # Figure out which repository to use.
     46   buildername = api.properties['buildername']
     47   if '1k' in buildername:
     48     ct_page_type = '10k'
     49     num_pages = 1000
     50   elif '10k' in buildername:
     51     ct_page_type = '10k'
     52     num_pages = 10000
     53   elif '100k' in buildername:
     54     ct_page_type = '100k'
     55     num_pages = 100000
     56   elif '1m' in buildername:
     57     ct_page_type = 'All'
     58     num_pages = 1000000
     59   else:
     60     raise Exception('Do not recognise the buildername %s.' % buildername)
     61 
     62   # Figure out which tool to use.
     63   if 'DM' in buildername:
     64     skia_tool = 'dm'
     65     build_target = 'dm'
     66   elif 'BENCH' in buildername:
     67     skia_tool = 'nanobench'
     68     build_target = 'nanobench'
     69   elif 'IMG_DECODE' in buildername:
     70     skia_tool = 'get_images_from_skps'
     71     build_target = 'tools'
     72   else:
     73     raise Exception('Do not recognise the buildername %s.' % buildername)
     74 
     75   api.core.setup()
     76   api.flavor.compile(build_target)
     77 
     78   # Required paths.
     79   infrabots_dir = api.vars.skia_dir.join('infra', 'bots')
     80   isolate_dir = infrabots_dir.join('ct')
     81   isolate_path = isolate_dir.join(CT_SKPS_ISOLATE)
     82 
     83   api.run.copy_build_products(
     84       api.flavor.out_dir,
     85       isolate_dir)
     86   api.skia_swarming.setup(
     87       infrabots_dir.join('tools', 'luci-go'),
     88       swarming_rev='')
     89 
     90   skps_chromium_build = api.properties.get(
     91       'skps_chromium_build', DEFAULT_SKPS_CHROMIUM_BUILD)
     92 
     93   # Set build properties to make finding SKPs convenient.
     94   webpage_rankings_link = (
     95       'https://storage.cloud.google.com/%s/csv/top-1m.csv'
     96           % api.ct.CT_GS_BUCKET)
     97   api.step.active_result.presentation.properties['Webpage rankings'] = (
     98       webpage_rankings_link)
     99   download_skps_link = (
    100       'https://pantheon.corp.google.com/storage/browser/%s/swarming/skps/%s/%s/'
    101           % (api.ct.CT_GS_BUCKET, ct_page_type, skps_chromium_build))
    102   api.step.active_result.presentation.properties['Download SKPs by rank'] = (
    103       download_skps_link)
    104 
    105   # Delete swarming_temp_dir to ensure it starts from a clean slate.
    106   api.run.rmtree(api.skia_swarming.swarming_temp_dir)
    107 
    108   num_per_slave = api.properties.get(
    109       'num_per_slave',
    110       min(TOOL_TO_DEFAULT_SKPS_PER_SLAVE[skia_tool], num_pages))
    111   ct_num_slaves = api.properties.get(
    112       'ct_num_slaves',
    113       int(math.ceil(float(num_pages) / num_per_slave)))
    114 
    115   # Try to figure out if the SKPs we are going to isolate already exist
    116   # locally by reading the SKPS_VERSION_FILE.
    117   download_skps = True
    118   expected_version_contents = {
    119       "chromium_build": skps_chromium_build,
    120       "page_type": ct_page_type,
    121       "num_slaves": ct_num_slaves,
    122   }
    123   skps_dir = api.vars.checkout_root.join('skps', buildername)
    124   version_file = skps_dir.join(SKPS_VERSION_FILE)
    125   if api.path.exists(version_file):  # pragma: nocover
    126     version_file_contents = api.file.read_text(
    127         "Read %s" % version_file,
    128         version_file,
    129         test_data=expected_version_contents)
    130     actual_version_contents = api.json.loads(version_file_contents)
    131     differences = (set(expected_version_contents.items()) ^
    132                    set(actual_version_contents.items()))
    133     download_skps = len(differences) != 0
    134     if download_skps:
    135       # Delete and recreate the skps dir.
    136       api.run.rmtree(skps_dir)
    137       api.file.ensure_directory(
    138           'makedirs %s' % api.path.basename(skps_dir), skps_dir)
    139 
    140   # If a blacklist file exists then specify SKPs to be blacklisted.
    141   blacklists_dir = api.vars.skia_dir.join('infra', 'bots', 'ct', 'blacklists')
    142   blacklist_file = blacklists_dir.join(
    143       '%s_%s_%s.json' % (skia_tool, ct_page_type, skps_chromium_build))
    144   blacklist_skps = []
    145   if api.path.exists(blacklist_file):  # pragma: nocover
    146     blacklist_file_contents = api.file.read_text(
    147         "Read %s" % blacklist_file,
    148         blacklist_file)
    149     blacklist_skps = api.json.loads(blacklist_file_contents)['blacklisted_skps']
    150 
    151   for slave_num in range(1, ct_num_slaves + 1):
    152     if download_skps:
    153       # Download SKPs.
    154       api.ct.download_swarming_skps(
    155           ct_page_type, slave_num, skps_chromium_build,
    156           skps_dir,
    157           start_range=((slave_num-1)*num_per_slave) + 1,
    158           num_skps=num_per_slave)
    159 
    160     # Create this slave's isolated.gen.json file to use for batcharchiving.
    161     extra_variables = {
    162         'SLAVE_NUM': str(slave_num),
    163         'TOOL_NAME': skia_tool,
    164         'GIT_HASH': api.vars.got_revision,
    165         'CONFIGURATION': api.vars.configuration,
    166         'BUILDER': buildername,
    167     }
    168     api.skia_swarming.create_isolated_gen_json(
    169         isolate_path, isolate_dir, 'linux', 'ct-%s-%s' % (skia_tool, slave_num),
    170         extra_variables, blacklist=blacklist_skps)
    171 
    172   if download_skps:
    173     # Since we had to download SKPs create an updated version file.
    174     api.file.write_text("Create %s" % version_file,
    175                         version_file,
    176                         api.json.dumps(expected_version_contents))
    177 
    178   # Batcharchive everything on the isolate server for efficiency.
    179   max_slaves_to_batcharchive = MAX_SLAVES_TO_BATCHARCHIVE
    180   if '1m' in buildername:
    181     # Break up the "isolate tests" step into batches with <100k files due to
    182     # https://github.com/luci/luci-go/issues/9
    183     max_slaves_to_batcharchive = 5
    184   tasks_to_swarm_hashes = []
    185   for slave_start_num in xrange(1, ct_num_slaves+1, max_slaves_to_batcharchive):
    186     m = min(max_slaves_to_batcharchive, ct_num_slaves)
    187     batcharchive_output = api.skia_swarming.batcharchive(
    188         targets=['ct-' + skia_tool + '-%s' % num for num in range(
    189             slave_start_num, slave_start_num + m)])
    190     tasks_to_swarm_hashes.extend(batcharchive_output)
    191   # Sort the list to go through tasks in order.
    192   tasks_to_swarm_hashes.sort()
    193 
    194   # Trigger all swarming tasks.
    195   dimensions={'os': 'Ubuntu-14.04', 'cpu': 'x86-64', 'pool': 'Chrome'}
    196   if 'GPU' in buildername:
    197     dimensions['gpu'] = '10de:104a'
    198   tasks = api.skia_swarming.trigger_swarming_tasks(
    199       tasks_to_swarm_hashes, dimensions=dimensions, io_timeout=40*60)
    200 
    201   # Now collect all tasks.
    202   env = {'AWS_CREDENTIAL_FILE': None, 'BOTO_CONFIG': None}
    203   failed_tasks = []
    204   for task in tasks:
    205     try:
    206       api.skia_swarming.collect_swarming_task(task)
    207 
    208       if skia_tool == 'nanobench':
    209         output_dir = api.skia_swarming.tasks_output_dir.join(
    210             task.title).join('0')
    211         utc = api.time.utcnow()
    212         gs_dest_dir = 'ct/%s/%d/%02d/%02d/%02d/' % (
    213             ct_page_type, utc.year, utc.month, utc.day, utc.hour)
    214         for json_output in api.file.listdir(
    215             'listdir output dir', output_dir, test_data=['file 1', 'file 2']):
    216           with api.context(env=env):
    217             api.gsutil.upload(
    218                 name='upload json output',
    219                 source=json_output,
    220                 bucket='skia-perf',
    221                 dest=gs_dest_dir,
    222                 args=['-R']
    223             )
    224 
    225     except api.step.StepFailure as e:
    226       # Add SKP links for convenience.
    227       api.step.active_result.presentation.links['Webpage rankings'] = (
    228           webpage_rankings_link)
    229       api.step.active_result.presentation.links['Download SKPs by rank'] = (
    230           download_skps_link)
    231       failed_tasks.append(e)
    232 
    233   if failed_tasks:
    234     raise api.step.StepFailure(
    235         'Failed steps: %s' % ', '.join([f.name for f in failed_tasks]))
    236 
    237 
    238 def GenTests(api):
    239   ct_num_slaves = 5
    240   num_per_slave = 10
    241   skia_revision = 'abc123'
    242   path_config = 'kitchen'
    243 
    244   yield(
    245     api.test('CT_DM_10k_SKPs') +
    246     api.properties(
    247         buildername='Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_DM_10k_SKPs',
    248         path_config=path_config,
    249         swarm_out_dir='[SWARM_OUT_DIR]',
    250         ct_num_slaves=ct_num_slaves,
    251         num_per_slave=num_per_slave,
    252         repository='https://skia.googlesource.com/skia.git',
    253         revision=skia_revision,
    254     )
    255   )
    256 
    257   yield(
    258     api.test('CT_IMG_DECODE_10k_SKPs') +
    259     api.properties(
    260         buildername='Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_IMG_DECODE_'
    261                     '10k_SKPs',
    262         path_config=path_config,
    263         swarm_out_dir='[SWARM_OUT_DIR]',
    264         ct_num_slaves=ct_num_slaves,
    265         num_per_slave=num_per_slave,
    266         repository='https://skia.googlesource.com/skia.git',
    267         revision=skia_revision,
    268     )
    269   )
    270 
    271   yield(
    272     api.test('CT_DM_100k_SKPs') +
    273     api.properties(
    274         buildername='Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_DM_100k_SKPs',
    275         path_config=path_config,
    276         swarm_out_dir='[SWARM_OUT_DIR]',
    277         ct_num_slaves=ct_num_slaves,
    278         num_per_slave=num_per_slave,
    279         repository='https://skia.googlesource.com/skia.git',
    280         revision=skia_revision,
    281     )
    282   )
    283 
    284   yield(
    285     api.test('CT_IMG_DECODE_100k_SKPs') +
    286     api.properties(
    287         buildername='Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_IMG_DECODE_'
    288                     '100k_SKPs',
    289         path_config=path_config,
    290         swarm_out_dir='[SWARM_OUT_DIR]',
    291         ct_num_slaves=ct_num_slaves,
    292         num_per_slave=num_per_slave,
    293         repository='https://skia.googlesource.com/skia.git',
    294         revision=skia_revision,
    295     )
    296   )
    297 
    298   yield(
    299     api.test('CT_GPU_BENCH_1k_SKPs') +
    300     api.properties(
    301         buildername=
    302             'Perf-Ubuntu-GCC-Golo-GPU-GT610-x86_64-Release-CT_BENCH_1k_SKPs',
    303         path_config=path_config,
    304         swarm_out_dir='[SWARM_OUT_DIR]',
    305         ct_num_slaves=ct_num_slaves,
    306         num_per_slave=num_per_slave,
    307         repository='https://skia.googlesource.com/skia.git',
    308         revision=skia_revision,
    309     ) +
    310     api.path.exists(
    311         api.path['start_dir'].join('skia'),
    312         api.path['start_dir'].join('src')
    313     )
    314   )
    315 
    316   yield(
    317     api.test('CT_CPU_BENCH_10k_SKPs') +
    318     api.properties(
    319         buildername=
    320             'Perf-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-CT_BENCH_10k_SKPs',
    321         path_config=path_config,
    322         swarm_out_dir='[SWARM_OUT_DIR]',
    323         ct_num_slaves=ct_num_slaves,
    324         num_per_slave=num_per_slave,
    325         repository='https://skia.googlesource.com/skia.git',
    326         revision=skia_revision,
    327     ) +
    328     api.path.exists(
    329         api.path['start_dir'].join('skia'),
    330         api.path['start_dir'].join('src')
    331     )
    332   )
    333 
    334   yield(
    335     api.test('CT_GPU_BENCH_10k_SKPs') +
    336     api.properties(
    337         buildername=
    338             'Perf-Ubuntu-GCC-Golo-GPU-GT610-x86_64-Release-CT_BENCH_10k_SKPs',
    339         path_config=path_config,
    340         swarm_out_dir='[SWARM_OUT_DIR]',
    341         ct_num_slaves=ct_num_slaves,
    342         num_per_slave=num_per_slave,
    343         repository='https://skia.googlesource.com/skia.git',
    344         revision=skia_revision,
    345     ) +
    346     api.path.exists(
    347         api.path['start_dir'].join('skia'),
    348         api.path['start_dir'].join('src')
    349     )
    350   )
    351 
    352   yield(
    353     api.test('CT_DM_1m_SKPs') +
    354     api.properties(
    355         buildername='Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_DM_1m_SKPs',
    356         path_config=path_config,
    357         swarm_out_dir='[SWARM_OUT_DIR]',
    358         ct_num_slaves=ct_num_slaves,
    359         num_per_slave=num_per_slave,
    360         repository='https://skia.googlesource.com/skia.git',
    361         revision=skia_revision,
    362     )
    363   )
    364 
    365   yield (
    366     api.test('CT_DM_SKPs_UnknownBuilder') +
    367     api.properties(
    368         buildername=
    369             'Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_DM_UnknownRepo_SKPs',
    370         path_config=path_config,
    371         swarm_out_dir='[SWARM_OUT_DIR]',
    372         ct_num_slaves=ct_num_slaves,
    373         num_per_slave=num_per_slave,
    374         repository='https://skia.googlesource.com/skia.git',
    375         revision=skia_revision,
    376     ) +
    377     api.expect_exception('Exception')
    378   )
    379 
    380   yield (
    381     api.test('CT_10k_SKPs_UnknownBuilder') +
    382     api.properties(
    383         buildername=
    384             'Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_UnknownTool_10k_SKPs',
    385         path_config=path_config,
    386         swarm_out_dir='[SWARM_OUT_DIR]',
    387         ct_num_slaves=ct_num_slaves,
    388         num_per_slave=num_per_slave,
    389         repository='https://skia.googlesource.com/skia.git',
    390         revision=skia_revision,
    391     ) +
    392     api.expect_exception('Exception')
    393   )
    394 
    395   yield(
    396     api.test('CT_DM_1m_SKPs_slave3_failure') +
    397     api.step_data('ct-dm-3', retcode=1) +
    398     api.properties(
    399         buildername='Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_DM_1m_SKPs',
    400         path_config=path_config,
    401         swarm_out_dir='[SWARM_OUT_DIR]',
    402         ct_num_slaves=ct_num_slaves,
    403         num_per_slave=num_per_slave,
    404         repository='https://skia.googlesource.com/skia.git',
    405         revision=skia_revision,
    406     )
    407   )
    408 
    409   yield(
    410     api.test('CT_DM_1m_SKPs_2slaves_failure') +
    411     api.step_data('ct-dm-1', retcode=1) +
    412     api.step_data('ct-dm-3', retcode=1) +
    413     api.properties(
    414         buildername='Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_DM_1m_SKPs',
    415         path_config=path_config,
    416         swarm_out_dir='[SWARM_OUT_DIR]',
    417         ct_num_slaves=ct_num_slaves,
    418         num_per_slave=num_per_slave,
    419         repository='https://skia.googlesource.com/skia.git',
    420         revision=skia_revision,
    421     )
    422   )
    423 
    424   builder = 'Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_DM_10k_SKPs'
    425   yield(
    426     api.test('CT_DM_10k_SKPs_Trybot') +
    427     api.properties(
    428         buildername=builder,
    429         path_config=path_config,
    430         swarm_out_dir='[SWARM_OUT_DIR]',
    431         ct_num_slaves=ct_num_slaves,
    432         num_per_slave=num_per_slave,
    433         repository='https://skia.googlesource.com/skia.git',
    434         patch_storage='gerrit') +
    435     api.properties.tryserver(
    436         buildername=builder,
    437         gerrit_project='skia',
    438         gerrit_url='https://skia-review.googlesource.com/',
    439     )
    440   )
    441 
    442   builder = ('Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-CT_IMG_DECODE_'
    443              '10k_SKPs')
    444   yield(
    445     api.test('CT_IMG_DECODE_10k_SKPs_Trybot') +
    446     api.properties(
    447         buildername=builder,
    448         path_config=path_config,
    449         swarm_out_dir='[SWARM_OUT_DIR]',
    450         ct_num_slaves=ct_num_slaves,
    451         num_per_slave=num_per_slave,
    452         repository='https://skia.googlesource.com/skia.git',
    453         revision=skia_revision,
    454         patch_storage='gerrit') +
    455     api.properties.tryserver(
    456         buildername=builder,
    457         gerrit_project='skia',
    458         gerrit_url='https://skia-review.googlesource.com/',
    459     )
    460   )
    461