• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4# See https://llvm.org/LICENSE.txt for license information.
5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6#
7# ==------------------------------------------------------------------------==#
8
9import os
10import glob
11import re
12import subprocess
13import json
14import datetime
15import argparse
16try:
17    from urllib.parse import urlencode
18    from urllib.request import urlopen, Request
19except ImportError:
20    from urllib import urlencode
21    from urllib2 import urlopen, Request
22
23
24parser = argparse.ArgumentParser()
25parser.add_argument('benchmark_directory')
26parser.add_argument('--runs', type=int, default=10)
27parser.add_argument('--wrapper', default='')
28parser.add_argument('--machine', required=True)
29parser.add_argument('--revision', required=True)
30parser.add_argument('--threads', action='store_true')
31parser.add_argument('--url', help='The lnt server url to send the results to',
32                    default='http://localhost:8000/db_default/v4/link/submitRun')
33args = parser.parse_args()
34
35class Bench:
36    def __init__(self, directory, variant):
37        self.directory = directory
38        self.variant = variant
39    def __str__(self):
40        if not self.variant:
41            return self.directory
42        return '%s-%s' % (self.directory, self.variant)
43
44def getBenchmarks():
45    ret = []
46    for i in glob.glob('*/response*.txt'):
47        m = re.match('response-(.*)\.txt', os.path.basename(i))
48        variant = m.groups()[0] if m else None
49        ret.append(Bench(os.path.dirname(i), variant))
50    return ret
51
52def parsePerfNum(num):
53    num = num.replace(b',',b'')
54    try:
55        return int(num)
56    except ValueError:
57        return float(num)
58
59def parsePerfLine(line):
60    ret = {}
61    line = line.split(b'#')[0].strip()
62    if len(line) != 0:
63        p = line.split()
64        ret[p[1].strip().decode('ascii')] = parsePerfNum(p[0])
65    return ret
66
67def parsePerf(output):
68    ret = {}
69    lines = [x.strip() for x in output.split(b'\n')]
70
71    seconds = [x for x in lines if b'seconds time elapsed' in x][0]
72    seconds = seconds.strip().split()[0].strip()
73    ret['seconds-elapsed'] = parsePerfNum(seconds)
74
75    measurement_lines = [x for x in lines if b'#' in x]
76    for l in measurement_lines:
77        ret.update(parsePerfLine(l))
78    return ret
79
80def run(cmd):
81    try:
82        return subprocess.check_output(cmd, stderr=subprocess.STDOUT)
83    except subprocess.CalledProcessError as e:
84        print(e.output)
85        raise e
86
87def combinePerfRun(acc, d):
88    for k,v in d.items():
89        a = acc.get(k, [])
90        a.append(v)
91        acc[k] = a
92
93def perf(cmd):
94    # Discard the first run to warm up any system cache.
95    run(cmd)
96
97    ret = {}
98    wrapper_args = [x for x in args.wrapper.split(',') if x]
99    for i in range(args.runs):
100        os.unlink('t')
101        out = run(wrapper_args + ['perf', 'stat'] + cmd)
102        r = parsePerf(out)
103        combinePerfRun(ret, r)
104    os.unlink('t')
105    return ret
106
107def runBench(bench):
108    thread_arg = [] if args.threads else ['--no-threads']
109    os.chdir(bench.directory)
110    suffix = '-%s' % bench.variant if bench.variant else ''
111    response = 'response' + suffix + '.txt'
112    ret = perf(['../ld.lld', '@' + response, '-o', 't'] + thread_arg)
113    ret['name'] = str(bench)
114    os.chdir('..')
115    return ret
116
117def buildLntJson(benchmarks):
118    start = datetime.datetime.utcnow().isoformat()
119    tests = [runBench(b) for b in benchmarks]
120    end = datetime.datetime.utcnow().isoformat()
121    ret = {
122        'format_version' : 2,
123        'machine' : { 'name' : args.machine },
124        'run' : {
125            'end_time' : start,
126            'start_time' : end,
127            'llvm_project_revision': args.revision
128        },
129        'tests' : tests
130    }
131    return json.dumps(ret, sort_keys=True, indent=4)
132
133def submitToServer(data):
134    data2 = urlencode({ 'input_data' : data }).encode('ascii')
135    urlopen(Request(args.url, data2))
136
137os.chdir(args.benchmark_directory)
138data = buildLntJson(getBenchmarks())
139submitToServer(data)
140