|  | #!/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) |