140 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
#!/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)
 |