|  | #!/usr/bin/env python | 
|  | # | 
|  | # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | # See https://llvm.org/LICENSE.txt for license information. | 
|  | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | # | 
|  | # ==------------------------------------------------------------------------==# | 
|  |  | 
|  | import os | 
|  | import glob | 
|  | import re | 
|  | import subprocess | 
|  | import json | 
|  | import datetime | 
|  | import argparse | 
|  | try: | 
|  | from urllib.parse import urlencode | 
|  | from urllib.request import urlopen, Request | 
|  | except ImportError: | 
|  | from urllib import urlencode | 
|  | from urllib2 import urlopen, Request | 
|  |  | 
|  |  | 
|  | parser = argparse.ArgumentParser() | 
|  | parser.add_argument('benchmark_directory') | 
|  | parser.add_argument('--runs', type=int, default=10) | 
|  | parser.add_argument('--wrapper', default='') | 
|  | parser.add_argument('--machine', required=True) | 
|  | parser.add_argument('--revision', required=True) | 
|  | parser.add_argument('--threads', action='store_true') | 
|  | parser.add_argument('--url', help='The lnt server url to send the results to', | 
|  | default='http://localhost:8000/db_default/v4/link/submitRun') | 
|  | args = parser.parse_args() | 
|  |  | 
|  | class Bench: | 
|  | def __init__(self, directory, variant): | 
|  | self.directory = directory | 
|  | self.variant = variant | 
|  | def __str__(self): | 
|  | if not self.variant: | 
|  | return self.directory | 
|  | return '%s-%s' % (self.directory, self.variant) | 
|  |  | 
|  | def getBenchmarks(): | 
|  | ret = [] | 
|  | for i in glob.glob('*/response*.txt'): | 
|  | m = re.match('response-(.*)\.txt', os.path.basename(i)) | 
|  | variant = m.groups()[0] if m else None | 
|  | ret.append(Bench(os.path.dirname(i), variant)) | 
|  | return ret | 
|  |  | 
|  | def parsePerfNum(num): | 
|  | num = num.replace(b',',b'') | 
|  | try: | 
|  | return int(num) | 
|  | except ValueError: | 
|  | return float(num) | 
|  |  | 
|  | def parsePerfLine(line): | 
|  | ret = {} | 
|  | line = line.split(b'#')[0].strip() | 
|  | if len(line) != 0: | 
|  | p = line.split() | 
|  | ret[p[1].strip().decode('ascii')] = parsePerfNum(p[0]) | 
|  | return ret | 
|  |  | 
|  | def parsePerf(output): | 
|  | ret = {} | 
|  | lines = [x.strip() for x in output.split(b'\n')] | 
|  |  | 
|  | seconds = [x for x in lines if b'seconds time elapsed' in x][0] | 
|  | seconds = seconds.strip().split()[0].strip() | 
|  | ret['seconds-elapsed'] = parsePerfNum(seconds) | 
|  |  | 
|  | measurement_lines = [x for x in lines if b'#' in x] | 
|  | for l in measurement_lines: | 
|  | ret.update(parsePerfLine(l)) | 
|  | return ret | 
|  |  | 
|  | def run(cmd): | 
|  | try: | 
|  | return subprocess.check_output(cmd, stderr=subprocess.STDOUT) | 
|  | except subprocess.CalledProcessError as e: | 
|  | print(e.output) | 
|  | raise e | 
|  |  | 
|  | def combinePerfRun(acc, d): | 
|  | for k,v in d.items(): | 
|  | a = acc.get(k, []) | 
|  | a.append(v) | 
|  | acc[k] = a | 
|  |  | 
|  | def perf(cmd): | 
|  | # Discard the first run to warm up any system cache. | 
|  | run(cmd) | 
|  |  | 
|  | ret = {} | 
|  | wrapper_args = [x for x in args.wrapper.split(',') if x] | 
|  | for i in range(args.runs): | 
|  | os.unlink('t') | 
|  | out = run(wrapper_args + ['perf', 'stat'] + cmd) | 
|  | r = parsePerf(out) | 
|  | combinePerfRun(ret, r) | 
|  | os.unlink('t') | 
|  | return ret | 
|  |  | 
|  | def runBench(bench): | 
|  | thread_arg = [] if args.threads else ['--no-threads'] | 
|  | os.chdir(bench.directory) | 
|  | suffix = '-%s' % bench.variant if bench.variant else '' | 
|  | response = 'response' + suffix + '.txt' | 
|  | ret = perf(['../ld.lld', '@' + response, '-o', 't'] + thread_arg) | 
|  | ret['name'] = str(bench) | 
|  | os.chdir('..') | 
|  | return ret | 
|  |  | 
|  | def buildLntJson(benchmarks): | 
|  | start = datetime.datetime.utcnow().isoformat() | 
|  | tests = [runBench(b) for b in benchmarks] | 
|  | end = datetime.datetime.utcnow().isoformat() | 
|  | ret = { | 
|  | 'format_version' : 2, | 
|  | 'machine' : { 'name' : args.machine }, | 
|  | 'run' : { | 
|  | 'end_time' : start, | 
|  | 'start_time' : end, | 
|  | 'llvm_project_revision': args.revision | 
|  | }, | 
|  | 'tests' : tests | 
|  | } | 
|  | return json.dumps(ret, sort_keys=True, indent=4) | 
|  |  | 
|  | def submitToServer(data): | 
|  | data2 = urlencode({ 'input_data' : data }).encode('ascii') | 
|  | urlopen(Request(args.url, data2)) | 
|  |  | 
|  | os.chdir(args.benchmark_directory) | 
|  | data = buildLntJson(getBenchmarks()) | 
|  | submitToServer(data) |