Skip to content

Commit c79de33

Browse files
authored
Merge pull request #52 from mattip/multiple-exes
Allow multiple exes, baselines
2 parents abc817f + af1854d commit c79de33

6 files changed

Lines changed: 97 additions & 60 deletions

File tree

codespeed/commits/git.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ def getlogs(endrev, startrev):
6464
p, stdout, stderr = execute_command(cmd, working_copy)
6565

6666
if p.returncode != 0:
67-
raise CommitLogError("%s returned %s: %s" % (
68-
" ".join(cmd), p.returncode, stderr))
67+
raise CommitLogError(f"'%s' in '%s' returned %s: %s" % (
68+
" ".join(cmd), working_copy, p.returncode, stderr))
6969
logs = []
7070
for log in filter(None, stdout.split('\x1e')):
7171
(short_commit_id, commit_id, date_t, author_name, author_email,

codespeed/results.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def save_result(data, update_repo=True):
7373
b.save()
7474

7575
try:
76-
rev = branch.revisions.get(commitid=data['commitid'])
76+
rev = branch.revisions.get(commitid=data['commitid'].split(":")[-1])
7777
except Revision.DoesNotExist:
7878
rev_date = data.get("revision_date")
7979
# "None" (as string) can happen when we urlencode the POST data

codespeed/views.py

Lines changed: 67 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,17 @@ def get_context_data(self, **kwargs):
6969
context = super(HomeView, self).get_context_data(**kwargs)
7070
context['show_reports'] = settings.SHOW_REPORTS
7171
context['show_historical'] = settings.SHOW_HISTORICAL
72-
historical_settings = ['SHOW_HISTORICAL', 'DEF_BASELINE', 'DEF_EXECUTABLE']
72+
historical_settings = ['SHOW_HISTORICAL', 'DEF_BASELINES', 'DEF_EXECUTABLES']
7373
if not all(getattr(settings, var) for var in historical_settings):
7474
context['show_historical'] = False
7575
return context
7676

7777
try:
7878
baseline_exe = Executable.objects.get(
79-
name=settings.DEF_BASELINE['executable'])
79+
name=settings.DEF_BASELINES[0]['executable'])
8080
context['baseline'] = baseline_exe
81-
def_name = settings.DEF_EXECUTABLE['name']
82-
def_project = Project.objects.get(name=settings.DEF_EXECUTABLE['project'])
81+
def_name = settings.DEF_EXECUTABLES[0]['name']
82+
def_project = Project.objects.get(name=settings.DEF_EXECUTABLES[0]['project'])
8383
default_exe = Executable.objects.get(name=def_name,
8484
project=def_project,
8585
)
@@ -101,44 +101,55 @@ def gethistoricaldata(request):
101101
env = env.first()
102102

103103
# Fetch Baseline data, filter by executable
104-
baseline_exe = Executable.objects.get(
105-
name=settings.DEF_BASELINE['executable'])
106-
baseline_revs = Revision.objects.filter(
107-
branch__project=baseline_exe.project).order_by('-date')
108-
baseline_lastrev = baseline_revs[0]
109-
for rev in baseline_revs:
110-
baseline_results = Result.objects.filter(
111-
executable=baseline_exe, revision=rev, environment=env)
112-
if baseline_results:
113-
baseline_lastrev = rev
114-
break
115-
if len(baseline_results) == 0:
116-
logger.error('Could not find results for {} rev="{}" env="{}"'.format(
117-
baseline_exe, baseline_lastrev, env))
118-
data['baseline'] = '{} {}'.format(
119-
settings.DEF_BASELINE['executable'], baseline_lastrev.tag)
120-
121-
def_name = settings.DEF_EXECUTABLE['name']
122-
def_project = Project.objects.get(name=settings.DEF_EXECUTABLE['project'])
123-
default_exe = Executable.objects.get(name=def_name, project=def_project)
124-
default_branch = Branch.objects.get(
125-
name=default_exe.project.default_branch,
126-
project=default_exe.project)
104+
baseline_results = []
105+
for b in settings.DEF_BASELINES:
106+
baseline_exe = Executable.objects.get(
107+
name=b['executable'])
108+
tag=b['revision']
109+
rev = Revision.objects.filter(branch__project=baseline_exe.project, tag=tag)
110+
if len(rev) < 1:
111+
return HttpResponse(json.dumps(
112+
f"Could not find {tag=} for {b['executable']} in database")
113+
)
114+
rev0 = rev[0]
115+
resname = '{} {}'.format(b['executable'], rev0.tag)
116+
baseline_results.append((resname, Result.objects.filter(
117+
executable=baseline_exe, revision=rev0, environment=env)))
118+
if not baseline_results[-1][1]:
119+
logger.error('Could not find results for {} rev="{}" env="{}"'.format(
120+
baseline_exe, rev0, env))
127121

128-
# Fetch tagged revisions for executable
129-
default_taggedrevs = Revision.objects.filter(
130-
branch=default_branch
131-
).exclude(tag="").order_by('date')
132122
default_results = {}
133-
for rev in default_taggedrevs:
134-
res = Result.objects.filter(
135-
executable=default_exe, revision=rev, environment=env)
136-
if not res:
137-
logger.info('no results for %s %s %s' % (str(default_exe), str(rev), str(env)))
138-
continue
139-
default_results[rev.tag] = res
140-
data['tagged_revs'] = [rev.tag for rev in default_taggedrevs if rev.tag in default_results]
123+
all_taggedrevs = []
124+
for executable in settings.DEF_EXECUTABLES:
125+
_def_name = executable['name']
126+
_def_project = Project.objects.get(name=executable['project'])
127+
_default_exe = Executable.objects.get(name=_def_name, project=_def_project)
128+
_default_branch = Branch.objects.get(
129+
name=_default_exe.project.default_branch,
130+
project=_default_exe.project)
131+
132+
# Fetch tagged revisions for executable
133+
default_taggedrevs = Revision.objects.filter(
134+
branch=_default_branch
135+
).exclude(tag="").order_by('date')
136+
all_taggedrevs += default_taggedrevs
137+
for rev in default_taggedrevs:
138+
res = Result.objects.filter(
139+
executable=_default_exe, revision=rev, environment=env)
140+
if not res:
141+
logger.info("no results for '%s' '%s' '%s'" % (str(_default_exe), str(rev), str(env)))
142+
continue
143+
default_results[rev.tag] = res
144+
data['tagged_revs'] = [rev.tag for rev in all_taggedrevs if rev.tag in default_results]
141145
# Fetch data for latest results
146+
executable = settings.DEF_EXECUTABLES[0]
147+
def_name = executable['name']
148+
def_project = Project.objects.get(name=executable['project'])
149+
default_exe = Executable.objects.get(name=def_name, project=def_project)
150+
default_branch = Branch.objects.get(
151+
name=default_exe.project.default_branch,
152+
project=default_exe.project)
142153
revs = Revision.objects.filter(
143154
branch=default_branch).order_by('-date')[:100]
144155
default_lastrev = None
@@ -153,17 +164,30 @@ def gethistoricaldata(request):
153164

154165
# Collect data
155166
benchmarks = []
156-
for res in baseline_results:
167+
# Collate first baseline and all the default_results
168+
resset = baseline_results[0][1]
169+
resname = baseline_results[0][0]
170+
data['baseline'] = resname
171+
for res in resset:
157172
if res == 0:
158173
continue
159174
benchmarks.append(res.benchmark.name)
160-
data['results'][res.benchmark.name] = {data['baseline']: res.value}
175+
data['results'][res.benchmark.name] = {resname: res.value}
161176
for rev_name in default_results:
162177
val = 0
163178
for default_res in default_results[rev_name]:
164179
if default_res.benchmark.name == res.benchmark.name:
165180
val = default_res.value
166-
data['results'][res.benchmark.name][rev_name] = val
181+
data['results'][res.benchmark.name][rev_name] = val
182+
# Collate other baseline
183+
for resname, resset in baseline_results[1:]:
184+
for res in resset:
185+
if res == 0:
186+
continue
187+
if not res.benchmark.name in data['results']:
188+
continue
189+
data['results'][res.benchmark.name][resname] = res.value
190+
data['tagged_revs'].insert(0, resname)
167191
benchmarks.sort()
168192
data['benchmarks'] = benchmarks
169193
return HttpResponse(json.dumps(data))
@@ -896,7 +920,7 @@ def displaylogs(request):
896920
log['commit_browse_url'] = project.commit_browsing_url.format(**log)
897921

898922
return render(
899-
request,
923+
request,
900924
'codespeed/changes_logs.html',
901925
{
902926
'error': error, 'logs': logs,

codespeed/views_data.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ def getbaselineexecutables(include_tags=None):
8383
'name': name,
8484
})
8585
# move default to first place
86-
if hasattr(settings, 'DEF_BASELINE') and settings.DEF_BASELINE is not None:
86+
if hasattr(settings, 'DEF_BASELINES') and settings.DEF_BASELINES is not None:
8787
try:
88-
exename = settings.DEF_BASELINE['executable']
89-
commitid = settings.DEF_BASELINE['revision']
88+
exename = settings.DEF_BASELINES[0]['executable']
89+
commitid = settings.DEF_BASELINES[0]['revision']
9090
for base in baseline:
9191
if base['key'] == "none":
9292
continue
@@ -104,11 +104,11 @@ def getbaselineexecutables(include_tags=None):
104104

105105
def getdefaultexecutable():
106106
default = None
107-
if (hasattr(settings, 'DEF_EXECUTABLE') and
108-
settings.DEF_EXECUTABLE is not None):
107+
if (hasattr(settings, 'DEF_EXECUTABLES') and
108+
settings.DEF_EXECUTABLES is not None):
109109
try:
110-
def_name = settings.DEF_EXECUTABLE['name']
111-
def_project = Project.objects.get(name=settings.DEF_EXECUTABLE['project'])
110+
def_name = settings.DEF_EXECUTABLES[0]['name']
111+
def_project = Project.objects.get(name=settings.DEF_EXECUTABLES[0]['project'])
112112
default = Executable.objects.get(name=def_name, project=def_project)
113113
except Executable.DoesNotExist:
114114
pass

speed_pypy/settings.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,14 @@
8989

9090
SHOW_REPORTS = False
9191
SHOW_HISTORICAL = True
92-
DEF_BASELINE = {'executable': 'cpython', 'revision': '3.6.8'}
93-
DEF_EXECUTABLE = {'name': 'pypy3.9-jit-64', 'project': 'PyPy3.9'}
92+
DEF_BASELINES = [
93+
{'executable': 'cpython', 'revision': '3.7.19'},
94+
{'executable': 'cpython', 'revision': '3.11.9'},
95+
]
96+
DEF_EXECUTABLES = [
97+
{'name': 'pypy3.10-jit-64', 'project': 'PyPy3.10'},
98+
{'name': 'pypy3.9-jit-64', 'project': 'PyPy3.9'},
99+
]
94100
DEF_ENVIRONMENT = 'benchmarker'
95101

96102

speed_pypy/templates/home.html

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ <h3>How fast is {{ default_exe.project }}?</h3>
3333
<p class="plot-caption">Plot 1: The above plot represents {{ default_exe.project }} ({{ default_exe }}) benchmark times normalized to {{ baseline }}. Smaller is better.</p>
3434
<p>It depends greatly on the type of task being performed. The geometric average of all benchmarks is <span id="geomean"></span> or <strong id="geofaster"></strong> times <em>faster</em> than {{ baseline }}</p>
3535

36-
<h3>How has {{ default_exe.project }} performance evolved over time?</h3>
36+
<h3>How has PyPy performance evolved over time?</h3>
3737
<div id="historical-plot"></div>
3838
<p class="plot-caption">Plot 2: Speedup compared to {{ baseline }}, using the inverse of the geometric average of normalized times, out of <span id="num_of_benchs"></span> benchmarks (see <a href="http://dl.acm.org/citation.cfm?id=5673" title="How not to lie with statistics: the correct way to summarize benchmark results">paper</a> on why the geometric mean is better for normalized results).</p>
3939
</div>
@@ -81,6 +81,10 @@ <h3>How has {{ default_exe.project }} performance evolved over time?</h3>
8181
$("#baseline-comparison-plot").html(getLoadText('Error retrieving data', 0));
8282
return 1;
8383
}
84+
if (typeof data === 'string' || data instanceof String) {
85+
$("#baseline-comparison-plot").html(getLoadText('Error retrieving data ' + data, 0));
86+
return 1;
87+
}
8488
var trunk_geomean = 1;
8589
var tagged_data = new Array();
8690
for (i in data['tagged_revs']) {
@@ -108,7 +112,7 @@ <h3>How has {{ default_exe.project }} performance evolved over time?</h3>
108112
plotdata[0].push(relative_value);
109113
plotdata[1].push(1.0);
110114
labels.push(relative_value.toFixed(2));
111-
if (relative_value > 0) {
115+
if (relative_value > 0 && !isNaN(relative_value)) {
112116
trunk_geomean *= relative_value;
113117
}
114118
}
@@ -158,7 +162,10 @@ <h3>How has {{ default_exe.project }} performance evolved over time?</h3>
158162
num_of_benchs = tagged_data[i].length;
159163
var tempgeo = 1;
160164
for (var j in tagged_data[i]) {
161-
tempgeo *= tagged_data[i][j];
165+
value = tagged_data[i][j];
166+
if (value > 0 && !isNaN(value)) {
167+
tempgeo *= value;
168+
}
162169
}
163170
tempgeo = Math.pow(tempgeo, 1/tagged_data[i].length);
164171
tempgeo = 1/tempgeo;
@@ -169,7 +176,7 @@ <h3>How has {{ default_exe.project }} performance evolved over time?</h3>
169176
for (var i in data['tagged_revs']) {
170177
ticks.push(data['tagged_revs'][i]);
171178
}
172-
ticks.push('latest');
179+
ticks.push('latest {{ default_exe.project }}');
173180
var geolabels = new Array();
174181
for (var i in geomeans) {
175182
geolabels.push(geomeans[i].toFixed(2) + "x");
@@ -197,7 +204,7 @@ <h3>How has {{ default_exe.project }} performance evolved over time?</h3>
197204
},
198205
yaxis:{
199206
min: 0,
200-
tickOptions:{formatString:'%.2f'}
207+
tickOptions:{formatString:'%.1f'}
201208
}
202209
}
203210
};

0 commit comments

Comments
 (0)