1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
"""Run all the vbenches in `suite`, and post the results as a json blob to gist
"""
import urllib2
from contextlib import closing
from urllib2 import urlopen
import json
import pandas as pd
WEB_TIMEOUT = 10
def get_travis_data():
"""figure out what worker we're running on, and the number of jobs it's running
"""
import os
jobid = os.environ.get("TRAVIS_JOB_ID")
if not jobid:
return None, None
with closing(urlopen("https://api.travis-ci.org/workers/")) as resp:
workers = json.loads(resp.read())
host = njobs = None
for item in workers:
host = item.get("host")
id = ((item.get("payload") or {}).get("job") or {}).get("id")
if id and str(id) == str(jobid):
break
if host:
njobs = len(
[x for x in workers if host in x['host'] and x['payload']])
return host, njobs
def get_utcdatetime():
try:
from datetime import datetime
return datetime.utcnow().isoformat(" ")
except:
pass
def dump_as_gist(data, desc="The Commit", njobs=None):
host, njobs2 = get_travis_data()[:2]
if njobs: # be slightly more reliable
njobs = max(njobs, njobs2)
content = dict(version="0.1.1",
timings=data,
datetime=get_utcdatetime(), # added in 0.1.1
hostname=host, # added in 0.1.1
njobs=njobs # added in 0.1.1, a measure of load on the travis box
)
payload = dict(description=desc,
public=True,
files={'results.json': dict(content=json.dumps(content))})
try:
with closing(urlopen("https://api.github.com/gists",
json.dumps(payload), timeout=WEB_TIMEOUT)) as r:
if 200 <= r.getcode() < 300:
print("\n\n" + "-" * 80)
gist = json.loads(r.read())
file_raw_url = gist['files'].items()[0][1]['raw_url']
print("[vbench-gist-raw_url] %s" % file_raw_url)
print("[vbench-html-url] %s" % gist['html_url'])
print("[vbench-api-url] %s" % gist['url'])
print("-" * 80 + "\n\n")
else:
print("api.github.com returned status %d" % r.getcode())
except:
print("Error occured while dumping to gist")
def main():
import warnings
from suite import benchmarks
exit_code = 0
warnings.filterwarnings('ignore', category=FutureWarning)
host, njobs = get_travis_data()[:2]
results = []
for b in benchmarks:
try:
d = b.run()
d.update(dict(name=b.name))
results.append(d)
msg = "{name:<40}: {timing:> 10.4f} [ms]"
print(msg.format(name=results[-1]['name'],
timing=results[-1]['timing']))
except Exception as e:
exit_code = 1
if (type(e) == KeyboardInterrupt or
'KeyboardInterrupt' in str(d)):
raise KeyboardInterrupt()
msg = "{name:<40}: ERROR:\n<-------"
print(msg.format(name=b.name))
if isinstance(d, dict):
if d['succeeded']:
print("\nException:\n%s\n" % str(e))
else:
for k, v in sorted(d.iteritems()):
print("{k}: {v}".format(k=k, v=v))
print("------->\n")
dump_as_gist(results, "testing", njobs=njobs)
return exit_code
if __name__ == "__main__":
import sys
sys.exit(main())
#####################################################
# functions for retrieving and processing the results
def get_vbench_log(build_url):
with closing(urllib2.urlopen(build_url)) as r:
if not (200 <= r.getcode() < 300):
return
s = json.loads(r.read())
s = [x for x in s['matrix'] if "VBENCH" in ((x.get('config', {})
or {}).get('env', {}) or {})]
# s=[x for x in s['matrix']]
if not s:
return
id = s[0]['id'] # should be just one for now
with closing(urllib2.urlopen("https://api.travis-ci.org/jobs/%s" % id)) as r2:
if not 200 <= r.getcode() < 300:
return
s2 = json.loads(r2.read())
return s2.get('log')
def get_results_raw_url(build):
"Taks a Travis a build number, retrieves the build log and extracts the gist url"
import re
log = get_vbench_log("https://api.travis-ci.org/builds/%s" % build)
if not log:
return
l = [x.strip(
) for x in log.split("\n") if re.match(".vbench-gist-raw_url", x)]
if l:
s = l[0]
m = re.search("(https://[^\s]+)", s)
if m:
return m.group(0)
def convert_json_to_df(results_url):
"""retrieve json results file from url and return df
df contains timings for all successful vbenchmarks
"""
with closing(urlopen(results_url)) as resp:
res = json.loads(resp.read())
timings = res.get("timings")
if not timings:
return
res = [x for x in timings if x.get('succeeded')]
df = pd.DataFrame(res)
df = df.set_index("name")
return df
def get_build_results(build):
"Returns a df with the results of the VBENCH job associated with the travis build"
r_url = get_results_raw_url(build)
if not r_url:
return
return convert_json_to_df(r_url)
def get_all_results(repo_id=53976): # travis pydata/pandas id
"""Fetches the VBENCH results for all travis builds, and returns a list of result df
unsuccesful individual vbenches are dropped.
"""
from collections import OrderedDict
def get_results_from_builds(builds):
dfs = OrderedDict()
for build in builds:
build_id = build['id']
build_number = build['number']
print(build_number)
res = get_build_results(build_id)
if res is not None:
dfs[build_number] = res
return dfs
base_url = 'https://api.travis-ci.org/builds?url=%2Fbuilds&repository_id={repo_id}'
url = base_url.format(repo_id=repo_id)
url_after = url + '&after_number={after}'
dfs = OrderedDict()
while True:
with closing(urlopen(url)) as r:
if not (200 <= r.getcode() < 300):
break
builds = json.loads(r.read())
res = get_results_from_builds(builds)
if not res:
break
last_build_number = min(res.keys())
dfs.update(res)
url = url_after.format(after=last_build_number)
return dfs
def get_all_results_joined(repo_id=53976):
def mk_unique(df):
for dupe in df.index.get_duplicates():
df = df.ix[df.index != dupe]
return df
dfs = get_all_results(repo_id)
for k in dfs:
dfs[k] = mk_unique(dfs[k])
ss = [pd.Series(v.timing, name=k) for k, v in dfs.iteritems()]
results = pd.concat(reversed(ss), 1)
return results
|