From 753d53cd64fbb8bfcb7592029680e4139541b69b Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 14:16:08 +0200 Subject: [PATCH 01/60] Custom PyPy about.html --- example/templates/about.html | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/example/templates/about.html b/example/templates/about.html index 931cf62b..51c1d4ad 100644 --- a/example/templates/about.html +++ b/example/templates/about.html @@ -1,22 +1,26 @@ -{% extends "base.html" %} +{% extends "site_base.html" %} {% block title %}{{ block.super }}: About this site{% endblock %} {% block body %}

About this site

-

<description of site and what benchmarks that are run>

+

We have nightly benchmark runs of pypy-c-jit and pypy-c, together with cpython 2.6.2 data for comparison.

This site runs on top of Django and Codespeed

About the benchmarks

-

The code can be found here.

-

About MyProject

-

<Description of the main project>

-

Main website: MySite

+

The code can be found here and here.

+

About PyPy

+

PyPy is a very compliant implementation of the Python language.

+

Main website: pypy.org

+ +

Blog: morepypy.blogspot.com

About Codespeed

Codespeed is a web application to monitor and analyze the performance of your code.

Code: github.com/tobami/codespeed

Wiki: wiki.github.com/tobami/codespeed/

Contact

-

For problems or suggestions about this website write to...

+

For problems or suggestions about this website write to

+

the pypy-dev mailing list or directly to Miquel Torres (tobami at googlemail dot com)

+
{% endblock %} From a7aaa6427a2a33ab97377138853cc123f9368382 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:18:20 +0200 Subject: [PATCH 02/60] Custom PyPy settings --- example/settings.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/example/settings.py b/example/settings.py index 3b251f0c..8d7efaa3 100644 --- a/example/settings.py +++ b/example/settings.py @@ -124,7 +124,7 @@ def process_exception(self, request, exception): #DEF_ENVIRONMENT = None #Name of the environment which should be selected as default -#DEF_BASELINE = None # Which executable + revision should be default as a baseline +DEF_BASELINE = {'executable': 'cpython', 'revision': '100'} # Which executable + revision should be default as a baseline # Given as the name of the executable and commitid of the revision # Example: defaultbaseline = {'executable': 'myexe', 'revision': '21'} @@ -132,11 +132,11 @@ def process_exception(self, request, exception): # Used by reports for the latest runs and changes view # Threshold that determines when a performance change over the last result is significant -#CHANGE_THRESHOLD = 3.0 +CHANGE_THRESHOLD = 5.0 # Threshold that determines when a performance change # over a number of revisions is significant -#TREND_THRESHOLD = 5.0 +TREND_THRESHOLD = 6.0 ## Changes view options ## #DEF_EXECUTABLE = None # Executable that should be chosen as default in the changes view @@ -156,14 +156,14 @@ def process_exception(self, request, exception): ## Comparison view options ## #CHART_TYPE = 'normal bars' # The options are 'normal bars', 'stacked bars' and 'relative bars' -#NORMALIZATION = False # True will enable normalization as the default selection +NORMALIZATION = True # True will enable normalization as the default selection # in the Comparison view. The default normalization can be # chosen in the defaultbaseline setting #CHART_ORIENTATION = 'vertical' # 'vertical' or 'horizontal can be chosen as # default chart orientation -#COMP_EXECUTABLES = None # Which executable + revision should be checked as default +COMP_EXECUTABLES = [('pypy-c-jit', 'L'), ('pypy-c', 'L')] # Which executable + revision should be checked as default # Given as a list of tuples containing the # name of an executable + commitid of a revision # An 'L' denotes the last revision From a6b36a06804dffd9127417c7ab3de0d8ab74cc9b Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:42:07 +0200 Subject: [PATCH 03/60] Add custom PyPy homepage --- codespeed/views.py | 45 +++++++++++ example/settings.py | 2 +- example/templates/home.html | 146 +++++++++++++++++++++++++++++++++++- example/urls.py | 4 +- 4 files changed, 191 insertions(+), 6 deletions(-) diff --git a/codespeed/views.py b/codespeed/views.py index b0e1a778..51f7de27 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -927,3 +927,48 @@ def add_json_results(request): logging.debug("add_json_results: completed") return HttpResponse("All result data saved successfully", status=202) + + +def get_home_data(request): + if request.method != 'GET': + return HttpResponseNotAllowed('GET') + data = {'results': {}, 'benchmarks': []} + env = Environment.objects.get(name='tannit') + # Fetch CPython data + cp_exe = Executable.objects.get(name="cpython") + cp_lastrev = Revision.objects.filter( + branch__project=cp_exe.project).order_by('-date')[0] + cp_results = Result.objects.filter( + executable=cp_exe, revision=cp_lastrev, environment=env) + # Fetch PyPy trunk data + pp_exe = Executable.objects.get(name="pypy-c-jit") + pp_branch = Branch.objects.get(name="default", project=pp_exe.project) + pp_lastrev = Revision.objects.filter(branch=pp_branch).order_by('-date')[0] + pp_results = Result.objects.filter( + executable=pp_exe, revision=pp_lastrev, environment=env) + # Fetch PyPy tagged revisions + pp_taggedrevs = Revision.objects.filter( + project=pp_exe.project + ).exclude(tag="").order_by('date') + data['tagged_revs'] = [rev.tag for rev in pp_taggedrevs] + pp_results = {'PyPy trunk': pp_results} + for rev in pp_taggedrevs: + pp_results[rev.tag] = Result.objects.filter( + executable=pp_exe, revision=rev, environment=env) + # Save data + benchmarks = [] + for res in cp_results: + if res == 0: + continue + benchmarks.append(res.benchmark.name) + key = 'CPython ' + cp_lastrev.tag + data['results'][res.benchmark.name] = {key: res.value} + for rev_name in pp_results: + val = 0 + for pp_res in pp_results[rev_name]: + if pp_res.benchmark.name == res.benchmark.name: + val = pp_res.value + data['results'][res.benchmark.name][rev_name] = val + benchmarks.sort() + data['benchmarks'] = benchmarks + return HttpResponse(json.dumps( data )) diff --git a/example/settings.py b/example/settings.py index 8d7efaa3..73027dcf 100644 --- a/example/settings.py +++ b/example/settings.py @@ -119,7 +119,7 @@ def process_exception(self, request, exception): # Codespeed settings that can be overwritten here. ## General default options ## -#WEBSITE_NAME = "MySpeedSite" # This name will be used in the reports RSS feed +WEBSITE_NAME = "PyPy Speed Center" # This name will be used in the reports RSS feed #DEF_ENVIRONMENT = None #Name of the environment which should be selected as default diff --git a/example/templates/home.html b/example/templates/home.html index 30a553a5..168fbd1e 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -2,7 +2,137 @@ {% block extra_head %} {{ block.super }} + + + + + + + + + {% endblock %} @@ -50,6 +181,15 @@

Comparison

Compare different executables and revisions


-
+ +
+

How fast is PyPy?

+
+

Plot 1: The above plot represents PyPy trunk (with JIT) benchmark times normalized to CPython. Smaller is better.

+

While it depends greately on the type of taks being performed, currently PyPy takes % of the time that CPython needs to complete an average given task (represented by the geometric mean of all benchmarks), which means that PyPy is about times faster than CPython

+

How has PyPy performance evolved over time?

+
+

Plot 2: Geometric averages of normalized times, out of benchmarks. Smaller is better. "times faster" inside parenthesis

+
{% endblock body %} diff --git a/example/urls.py b/example/urls.py index 34c3fca1..a1f7628b 100644 --- a/example/urls.py +++ b/example/urls.py @@ -19,8 +19,8 @@ #('^$', redirect_to, {'url': '/speed/'}), ) -urlpatterns += patterns( - '', +urlpatterns += patterns('', + (r'^json/$', 'codespeed.views.get_home_data'), (r'^', include('codespeed.urls')), #(r'^speed/', include('codespeed.urls')), ) From 69d3f621d3eabab033aea8e182aed8d7ad001f43 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:44:19 +0200 Subject: [PATCH 04/60] Add Google Analytics script --- example/templates/base.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/example/templates/base.html b/example/templates/base.html index 1da6890d..252f11c4 100644 --- a/example/templates/base.html +++ b/example/templates/base.html @@ -50,5 +50,15 @@

{% block page_title %}SPEED CENTER{% endblock page_title %}

{% endblock %} + + From 5029db8cd9496e2fd2e05fc02f539d12a8ab94df Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:45:05 +0200 Subject: [PATCH 05/60] Add pointlabels jqplot plugin for Home page plot --- .../static/js/jqplot/jqplot.pointLabels.min.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 codespeed/static/js/jqplot/jqplot.pointLabels.min.js diff --git a/codespeed/static/js/jqplot/jqplot.pointLabels.min.js b/codespeed/static/js/jqplot/jqplot.pointLabels.min.js new file mode 100644 index 00000000..2bf8a86d --- /dev/null +++ b/codespeed/static/js/jqplot/jqplot.pointLabels.min.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2009 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT and GPL version 2.0 licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris dot leonello at gmail dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + */ +(function(c){c.jqplot.PointLabels=function(e){this.show=c.jqplot.config.enablePlugins;this.location="n";this.labelsFromSeries=false;this.seriesLabelIndex=null;this.labels=[];this.stackedValue=false;this.ypadding=6;this.xpadding=6;this.escapeHTML=true;this.edgeTolerance=0;this.hideZeros=false;c.extend(true,this,e)};var a=["nw","n","ne","e","se","s","sw","w"];var d={nw:0,n:1,ne:2,e:3,se:4,s:5,sw:6,w:7};var b=["se","s","sw","w","nw","n","ne","e"];c.jqplot.PointLabels.init=function(k,h,g,e){var n=c.extend(true,{},g,e);this.plugins.pointLabels=new c.jqplot.PointLabels(n.pointLabels);var f=this.plugins.pointLabels;if(f.labels.length==0||f.labelsFromSeries){if(f.stackedValue){if(this._plotData.length&&this._plotData[0].length){var m=f.seriesLabelIndex||this._plotData[0].length-1;for(var j=0;j');u.insertAfter(s.canvas);if(q.escapeHTML){u.text(m)}else{u.html(m)}var f=q.location;if(this.waterfall&&parseInt(m,10)<0){f=b[d[f]]}var l=v.u2p(y[r][0])+q.xOffset(u,f);var g=n.u2p(y[r][1])+q.yOffset(u,f);u.css("left",l);u.css("top",g);var j=l+c(u).width();var o=g+c(u).height();var x=q.edgeTolerance;var e=c(s.canvas).position().left;var t=c(s.canvas).position().top;var w=s.canvas.width+e;var k=s.canvas.height+t;if(l-xw||o+x>k){c(u).remove()}}}};c.jqplot.postSeriesInitHooks.push(c.jqplot.PointLabels.init);c.jqplot.postDrawSeriesHooks.push(c.jqplot.PointLabels.draw)})(jQuery); \ No newline at end of file From 96160f3a52d19b136ead35320cace3867bad5666 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:56:00 +0200 Subject: [PATCH 06/60] Add PyPy favicon --- example/override/static/images/favicon.ico | Bin 0 -> 3230 bytes example/templates/base.html | 1 + 2 files changed, 1 insertion(+) create mode 100644 example/override/static/images/favicon.ico diff --git a/example/override/static/images/favicon.ico b/example/override/static/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c79bb6ded95b2a0035b0a9c47c7f2785cfbed0c1 GIT binary patch literal 3230 zcmcIm2~ZSA6rJ5!&S41Xf;r$ zqM;n$@_8clzhRx^3y<0yxNOOWLwN@5E3@F(uoR~Af}pCc0X2Osa6&;p<3>tWSl8 zttqR^inqu?o%-HNTpdlKHY5kogI*c5YB9RcX!0AL5>p~plPM99)42uv)7P)el8tFh0|Do15q5JsypNP(wD|-W z%=Ct3Od?$KiwUoy`dGk=bce_xKQ-72J*`R{s)|NMX$*2p;;^_m1G$|Wk#V{V$>*xz zx;YI|7aI`vL+yZm*!69YmS@5wB@m+wwFh#s%gBZ_a|yAWoru{7Pa|sIQKC9t^ASIC z zoN0(7olWsXJYF3F0p~}_JVh`?wMbp1-#EY?CUQ57nWW2fJ1G9|UF!^L*olnZM@Tr< zgMg}S(6*TYfl#PVeV#K50}WhinFFTJ>MxzD!?dlQBR%V|8jgF`eP!!}TR}1LD{q8< zMGMP;)u42chg;UH={Q#(GoXL0DvFJ(We{h0U4g*J$ioLgTX!O)aW59%1B<z95Od)MG#;&E!Y(i%UY-`x-gcgaM?OCQX8lfJr^n4Ob-Aq~3;dk0gx zdl9f@VE$iL+vdG%1IhPwv<6Lc(7Y-L*5+cC!{#^9e99FFrqTAVzUB2qvF9+6e|8Yj z`%hxLsRe|h5hI@R{%xqMig;}eb^P3>1RMXi)iEf}@kU&PEkwNVZ%WIfU}wTm=1vJ; zi)|$ctZgO9-B(Cb*JaE;a0)JYYuR`{enkK`yUAi)Y)d3v&GFbxwy~Vp|0aqH9~c|LQ05Jvnyn}yw(c%b z3}t?16UU*uHGv#&NhJH~lvwpq5OQ*Zky#jt^b#c$>y>a>u7K5IIjr&$;jn2Lk+oG4 zS#uS9>Z&2Du7RTcFf#i7K+b)Fz?wET?w>~M>a+DQq=|TeDJA{3EZG?+_N3#>-Sbh` zl8zN+O3d3B5BWMJWW`C4mZU*inggebe0bEAz;8!AA`iABj(*x&s|NJs1RRa|Zo@b$`flh7@CaIenFm n-h7oK08g>{Kj1qGh)S>fW0i+|;n>HN&;015(^x74VcF#$?Vs(& literal 0 HcmV?d00001 diff --git a/example/templates/base.html b/example/templates/base.html index 252f11c4..5ec7231a 100644 --- a/example/templates/base.html +++ b/example/templates/base.html @@ -9,6 +9,7 @@ + {% block extra_head %}{% endblock %} From b7e214b40fa90988f1f174c9215f22a1fff8480d Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 20:15:34 +0200 Subject: [PATCH 07/60] Add legend to first "home" plot --- codespeed/static/css/main.css | 2 +- example/templates/home.html | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/codespeed/static/css/main.css b/codespeed/static/css/main.css index 0220fd30..815e00aa 100644 --- a/codespeed/static/css/main.css +++ b/codespeed/static/css/main.css @@ -123,7 +123,7 @@ div#presentation div.menubox { } div#presentation div.menubox:hover { border: 5px solid #FFCE9C; } -div#presentation p { height: 5em; padding-left: 120px; } +div#presentation div.menubox p { height: 5em; padding-left: 120px; } div#presentation div#changes p { background: url(../images/changes.png) no-repeat; diff --git a/example/templates/home.html b/example/templates/home.html index 168fbd1e..3d667650 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -54,10 +54,11 @@ } trunk_geomean = Math.pow(trunk_geomean, 1/plotdata[0].length); var geofaster = 1/trunk_geomean; - $('#geomean').html((100*trunk_geomean).toFixed(1)); + $('#geomean').html(trunk_geomean.toFixed(2)); $('#geofaster').html(geofaster.toFixed(1)); // Render first plot plotoptions1 = { + legend:{show:true}, seriesDefaults: { showMarker: false, rendererOptions:{barPadding: 2, barMargin:5} @@ -67,10 +68,14 @@ }, series:[ { + label: 'PyPy trunk', renderer:$.jqplot.BarRenderer, pointLabels:{labels:labels} }, - {pointLabels:{show:false}} + { + label: 'CPython', + pointLabels:{show:false} + } ], axes: { xaxis: { @@ -85,7 +90,7 @@ } }; plot1 = $.jqplot("cpythonplot", plotdata, plotoptions1); - + // Prepare and render second plot var geomeans = [1.0]; var num_of_benchs = 0; @@ -109,6 +114,7 @@ geolabels.push(geomeans[i].toFixed(2) + " (" + (1/geomeans[i]).toFixed(1) + "x)"); } $('#num_of_benchs').html(num_of_benchs) + plotoptions2 = { seriesDefaults: { renderer:$.jqplot.BarRenderer, @@ -182,12 +188,13 @@

Comparison


-
+

How fast is PyPy?

Plot 1: The above plot represents PyPy trunk (with JIT) benchmark times normalized to CPython. Smaller is better.

-

While it depends greately on the type of taks being performed, currently PyPy takes % of the time that CPython needs to complete an average given task (represented by the geometric mean of all benchmarks), which means that PyPy is about times faster than CPython

+

It depends greatly on the type of task being performed. The geometric average of all benchmarks is or times faster than CPython

How has PyPy performance evolved over time?

+

Plot 2: Geometric averages of normalized times, out of benchmarks. Smaller is better. "times faster" inside parenthesis

From 9f75a7066e71ff45aeb1db037ae753cdac3b8b2b Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Mon, 18 Jul 2011 21:56:27 +0200 Subject: [PATCH 08/60] Don't choose a revision that doesn't have results for pypy-c-jit --- codespeed/views.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/codespeed/views.py b/codespeed/views.py index 51f7de27..27a375c3 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -308,7 +308,7 @@ def comparison(request): pass # The selected baseline was not checked except: pass # Keep "none" as default baseline - print selectedbaseline + selecteddirection = False if 'hor' in data and data['hor'] == "true" or\ hasattr(settings, 'CHART_ORIENTATION') and settings.CHART_ORIENTATION == 'horizontal': @@ -940,21 +940,32 @@ def get_home_data(request): branch__project=cp_exe.project).order_by('-date')[0] cp_results = Result.objects.filter( executable=cp_exe, revision=cp_lastrev, environment=env) - # Fetch PyPy trunk data + pp_exe = Executable.objects.get(name="pypy-c-jit") pp_branch = Branch.objects.get(name="default", project=pp_exe.project) - pp_lastrev = Revision.objects.filter(branch=pp_branch).order_by('-date')[0] - pp_results = Result.objects.filter( - executable=pp_exe, revision=pp_lastrev, environment=env) # Fetch PyPy tagged revisions pp_taggedrevs = Revision.objects.filter( project=pp_exe.project ).exclude(tag="").order_by('date') data['tagged_revs'] = [rev.tag for rev in pp_taggedrevs] - pp_results = {'PyPy trunk': pp_results} + pp_results = {} for rev in pp_taggedrevs: pp_results[rev.tag] = Result.objects.filter( executable=pp_exe, revision=rev, environment=env) + + # Fetch PyPy trunk data + revs = Revision.objects.filter(branch=pp_branch).order_by('-date')[:5] + pp_lastrev = None + for i in range(4): + pp_lastrev = revs[i] + if pp_lastrev.results.filter(executable=pp_exe): + break + pp_lastrev = None + if pp_lastrev is None: + return HttpResponse(json.dumps( data )) + pp_results['PyPy trunk'] = Result.objects.filter( + executable=pp_exe, revision=pp_lastrev, environment=env) + # Save data benchmarks = [] for res in cp_results: From 601625940ebda49f9665095a142b88e15ca05e57 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 21 Aug 2011 17:37:21 +0200 Subject: [PATCH 09/60] Improve pypy branch query, set WEBSITE_NAME and project name in template --- codespeed/settings.py | 2 +- codespeed/views.py | 2 +- example/templates/base.html | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/codespeed/settings.py b/codespeed/settings.py index 8340aa7f..3bcb7e54 100644 --- a/codespeed/settings.py +++ b/codespeed/settings.py @@ -2,7 +2,7 @@ """Default settings for Codespeed""" ## General default options ## -WEBSITE_NAME = "MySpeedSite" # This name will be used in the reports RSS feed +WEBSITE_NAME = "PyPy's Speed Center" # This name will be used in the reports RSS feed DEF_ENVIRONMENT = None #Name of the environment which should be selected as default diff --git a/codespeed/views.py b/codespeed/views.py index 27a375c3..bc844b73 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -945,7 +945,7 @@ def get_home_data(request): pp_branch = Branch.objects.get(name="default", project=pp_exe.project) # Fetch PyPy tagged revisions pp_taggedrevs = Revision.objects.filter( - project=pp_exe.project + branch=pp_branch ).exclude(tag="").order_by('date') data['tagged_revs'] = [rev.tag for rev in pp_taggedrevs] pp_results = {} diff --git a/example/templates/base.html b/example/templates/base.html index 5ec7231a..af7d6b92 100644 --- a/example/templates/base.html +++ b/example/templates/base.html @@ -1,8 +1,8 @@ - {% block title %}MyProject's Speed Center{% endblock %} - + {% block title %}PyPy's Speed Center{% endblock %} + From 224babeaf27a9a0cbb6599d1adf2fb1f468b490a Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Thu, 17 May 2012 11:53:48 +0200 Subject: [PATCH 10/60] Use the proper key for CPython data Update default baseline Increase width of second graph --- codespeed/views.py | 4 ++-- example/settings.py | 2 +- example/templates/home.html | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/codespeed/views.py b/codespeed/views.py index 303be50f..2e457907 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -935,6 +935,7 @@ def get_home_data(request): cp_exe = Executable.objects.get(name="cpython") cp_lastrev = Revision.objects.filter( branch__project=cp_exe.project).order_by('-date')[0] + data['baseline'] = 'CPython ' + cp_lastrev.tag cp_results = Result.objects.filter( executable=cp_exe, revision=cp_lastrev, environment=env) @@ -969,8 +970,7 @@ def get_home_data(request): if res == 0: continue benchmarks.append(res.benchmark.name) - key = 'CPython ' + cp_lastrev.tag - data['results'][res.benchmark.name] = {key: res.value} + data['results'][res.benchmark.name] = {data['baseline']: res.value} for rev_name in pp_results: val = 0 for pp_res in pp_results[rev_name]: diff --git a/example/settings.py b/example/settings.py index 07823e07..f767132e 100644 --- a/example/settings.py +++ b/example/settings.py @@ -124,7 +124,7 @@ def process_exception(self, request, exception): #DEF_ENVIRONMENT = None #Name of the environment which should be selected as default -DEF_BASELINE = {'executable': 'cpython', 'revision': '100'} # Which executable + revision should be default as a baseline +DEF_BASELINE = {'executable': 'cpython', 'revision': '101'} # Which executable + revision should be default as a baseline # Given as the name of the executable and commitid of the revision # Example: defaultbaseline = {'executable': 'myexe', 'revision': '21'} diff --git a/example/templates/home.html b/example/templates/home.html index 3d667650..26b35ee7 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -38,7 +38,7 @@ add_to_tagged_data = false; } if (add_to_tagged_data === false) { break; } - relative_value = data['results'][benchname][rev]/data['results'][benchname]['CPython 2.6.2']; + relative_value = data['results'][benchname][rev]/data['results'][benchname][data['baseline']]; tagged_data[i].push(relative_value) } // Only add benchmark if there are no 0 values @@ -46,7 +46,7 @@ // First add benchmark benchmarks.push(benchname); // Add PyPy trunk and CPython's 1.0 value - relative_value = data['results'][benchname]['PyPy trunk']/data['results'][benchname]['CPython 2.6.2']; + relative_value = data['results'][benchname]['PyPy trunk']/data['results'][benchname][data['baseline']]; plotdata[0].push(relative_value); plotdata[1].push(1.0); labels.push(relative_value.toFixed(2)); @@ -73,7 +73,7 @@ pointLabels:{labels:labels} }, { - label: 'CPython', + label: data['baseline'], pointLabels:{show:false} } ], @@ -84,7 +84,7 @@ tickOptions: {angle: -40} }, yaxis:{ - ticks: [0, 0.25, 0.5, 0.75, 1, 1.25, 1.5], + ticks: [0, 0.25, 0.5, 0.75, 1, 1.25], tickOptions:{formatString:'%.2f'} } } @@ -104,7 +104,7 @@ geomeans.push(tempgeo); } geomeans.push(trunk_geomean); - var ticks = ['CPython 2.6.2']; + var ticks = [data['baseline']]; for (var i in data['tagged_revs']) { ticks.push(data['tagged_revs'][i]); } @@ -195,7 +195,7 @@

How fast is PyPy?

It depends greatly on the type of task being performed. The geometric average of all benchmarks is or times faster than CPython

How has PyPy performance evolved over time?

-
+

Plot 2: Geometric averages of normalized times, out of benchmarks. Smaller is better. "times faster" inside parenthesis

From e4919086cc6912268c3cc2d2ebc67e733743949b Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Fri, 8 Jun 2012 14:43:38 +0200 Subject: [PATCH 11/60] Invert plot 2 --- example/templates/home.html | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/example/templates/home.html b/example/templates/home.html index 26b35ee7..bc3b8edf 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -101,17 +101,19 @@ tempgeo *= tagged_data[i][j]; } tempgeo = Math.pow(tempgeo, 1/tagged_data[i].length); + tempgeo = 1/tempgeo; geomeans.push(tempgeo); } - geomeans.push(trunk_geomean); + geomeans.push(1/trunk_geomean); var ticks = [data['baseline']]; for (var i in data['tagged_revs']) { ticks.push(data['tagged_revs'][i]); } ticks.push('PyPy trunk'); var geolabels = new Array(); - for (var i in geomeans) { - geolabels.push(geomeans[i].toFixed(2) + " (" + (1/geomeans[i]).toFixed(1) + "x)"); + for (var i in geomeans) { +// geolabels.push(geomeans[i].toFixed(2) + " (" + (1/geomeans[i]).toFixed(1) + "x)"); + geolabels.push(geomeans[i].toFixed(2) + "x"); } $('#num_of_benchs').html(num_of_benchs) @@ -131,7 +133,8 @@ ticks: ticks }, yaxis:{ - ticks: [0.0, 0.25, 0.5, 0.75, 1.0, 1.25], +// ticks: [0.0, 0.25, 0.5, 0.75, 1.0, 1.25], + min: 0, tickOptions:{formatString:'%.2f'} } } @@ -196,7 +199,7 @@

How fast is PyPy?

How has PyPy performance evolved over time?

-

Plot 2: Geometric averages of normalized times, out of benchmarks. Smaller is better. "times faster" inside parenthesis

+

Plot 2: Speedup compared to CPython, using the inverse of the geometric average of normalized times, out of benchmarks.

{% endblock body %} From 2d9325e01c29e73fde30a4f7f6de2894160a8daf Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Fri, 8 Jun 2012 15:04:38 +0200 Subject: [PATCH 12/60] Add reference to paper explaining geometric mean for normalized results --- example/templates/home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/templates/home.html b/example/templates/home.html index bc3b8edf..141abff3 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -199,7 +199,7 @@

How fast is PyPy?

How has PyPy performance evolved over time?

-

Plot 2: Speedup compared to CPython, using the inverse of the geometric average of normalized times, out of benchmarks.

+

Plot 2: Speedup compared to CPython, using the inverse of the geometric average of normalized times, out of benchmarks (see paper on why the geometric mean is better for normalized results).

{% endblock body %} From 51d4b63439e883ca2c69e2d7962f3593b573e16d Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 6 Jan 2013 12:19:33 -0800 Subject: [PATCH 13/60] exec wrapper script. --- manage.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 manage.py diff --git a/manage.py b/manage.py new file mode 100644 index 00000000..c6e84457 --- /dev/null +++ b/manage.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +import os +import sys + +new_file = os.path.join(os.path.dirname(__file__), 'example', 'manage.py') +os.execl(sys.executable, sys.executable, new_file, *sys.argv) From 9da7418e4b42e894e166536addb9c8504ef82713 Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 6 Jan 2013 12:25:18 -0800 Subject: [PATCH 14/60] unix is hard. --- manage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manage.py b/manage.py index c6e84457..802ac262 100644 --- a/manage.py +++ b/manage.py @@ -3,4 +3,4 @@ import sys new_file = os.path.join(os.path.dirname(__file__), 'example', 'manage.py') -os.execl(sys.executable, sys.executable, new_file, *sys.argv) +os.execl(sys.executable, new_file, new_file, *sys.argv) From 2084839530a2dfbce068f69ac6514e0ef81e8910 Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 6 Jan 2013 12:32:53 -0800 Subject: [PATCH 15/60] No really, I'm bad at unix. --- manage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manage.py b/manage.py index 802ac262..1962469e 100644 --- a/manage.py +++ b/manage.py @@ -3,4 +3,4 @@ import sys new_file = os.path.join(os.path.dirname(__file__), 'example', 'manage.py') -os.execl(sys.executable, new_file, new_file, *sys.argv) +os.execl(sys.executable, sys.executable, new_file, *sys.argv[1:]) From b2056a761e3db332b544179d2e063b2e6f3930c8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 7 Jan 2013 12:21:12 -0800 Subject: [PATCH 16/60] Incrase the size of a field --- .../009_auto__chg_field_branch_name.py | 97 +++++++++++++++++++ codespeed/models.py | 2 +- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 codespeed/migrations/009_auto__chg_field_branch_name.py diff --git a/codespeed/migrations/009_auto__chg_field_branch_name.py b/codespeed/migrations/009_auto__chg_field_branch_name.py new file mode 100644 index 00000000..f35dcc57 --- /dev/null +++ b/codespeed/migrations/009_auto__chg_field_branch_name.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Changing field 'Branch.name' + db.alter_column('codespeed_branch', 'name', self.gf('django.db.models.fields.CharField')(max_length=50)) + + def backwards(self, orm): + # Changing field 'Branch.name' + db.alter_column('codespeed_branch', 'name', self.gf('django.db.models.fields.CharField')(max_length=20)) + + models = { + 'codespeed.benchmark': { + 'Meta': {'object_name': 'Benchmark'}, + 'benchmark_type': ('django.db.models.fields.CharField', [], {'default': "'C'", 'max_length': '1'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'lessisbetter': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'units': ('django.db.models.fields.CharField', [], {'default': "'seconds'", 'max_length': '20'}), + 'units_title': ('django.db.models.fields.CharField', [], {'default': "'Time'", 'max_length': '30'}) + }, + 'codespeed.branch': { + 'Meta': {'unique_together': "(('name', 'project'),)", 'object_name': 'Branch'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'branches'", 'to': "orm['codespeed.Project']"}) + }, + 'codespeed.environment': { + 'Meta': {'object_name': 'Environment'}, + 'cpu': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kernel': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'memory': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'os': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}) + }, + 'codespeed.executable': { + 'Meta': {'object_name': 'Executable'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'executables'", 'to': "orm['codespeed.Project']"}) + }, + 'codespeed.project': { + 'Meta': {'object_name': 'Project'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'repo_pass': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'repo_path': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'repo_type': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1'}), + 'repo_user': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'track': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'codespeed.report': { + 'Meta': {'unique_together': "(('revision', 'executable', 'environment'),)", 'object_name': 'Report'}, + '_tablecache': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'colorcode': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '10'}), + 'environment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Environment']"}), + 'executable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Executable']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'revision': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Revision']"}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) + }, + 'codespeed.result': { + 'Meta': {'unique_together': "(('revision', 'executable', 'benchmark', 'environment'),)", 'object_name': 'Result'}, + 'benchmark': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Benchmark']"}), + 'date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'environment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Environment']"}), + 'executable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Executable']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'revision': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Revision']"}), + 'std_dev': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'val_max': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'val_min': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'value': ('django.db.models.fields.FloatField', [], {}) + }, + 'codespeed.revision': { + 'Meta': {'unique_together': "(('commitid', 'branch'),)", 'object_name': 'Revision'}, + 'author': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'branch': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['codespeed.Branch']"}), + 'commitid': ('django.db.models.fields.CharField', [], {'max_length': '42'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['codespeed.Project']"}), + 'tag': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}) + } + } + + complete_apps = ['codespeed'] diff --git a/codespeed/models.py b/codespeed/models.py index 39488c2e..c2047271 100644 --- a/codespeed/models.py +++ b/codespeed/models.py @@ -28,7 +28,7 @@ def __unicode__(self): class Branch(models.Model): - name = models.CharField(max_length=20) + name = models.CharField(max_length=50) project = models.ForeignKey(Project, related_name="branches") def __unicode__(self): From 5dfa14f14d91f59cd64342947a337f73342d3d43 Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 28 Nov 2014 09:10:43 +0200 Subject: [PATCH 17/60] tilt xlabels on Plot 2 --- example/templates/home.html | 1 + 1 file changed, 1 insertion(+) diff --git a/example/templates/home.html b/example/templates/home.html index 141abff3..6ce4b133 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -131,6 +131,7 @@ xaxis: { renderer: $.jqplot.CategoryAxisRenderer, ticks: ticks + tickOptions: {angle: -40} }, yaxis:{ // ticks: [0.0, 0.25, 0.5, 0.75, 1.0, 1.25], From 38757655382dd7c97582bb7c722d9707cb03c48a Mon Sep 17 00:00:00 2001 From: mattip Date: Sat, 29 Nov 2014 21:33:21 +0200 Subject: [PATCH 18/60] whoops --- example/templates/home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/templates/home.html b/example/templates/home.html index 6ce4b133..aad5162f 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -130,7 +130,7 @@ axes: { xaxis: { renderer: $.jqplot.CategoryAxisRenderer, - ticks: ticks + ticks: ticks, tickOptions: {angle: -40} }, yaxis:{ From 5a3bb8ca11e6468a515a4550198d6c21870210ba Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 26 Dec 2014 14:39:47 +0200 Subject: [PATCH 19/60] test, fix angling x-axis on cpythonplot2 --- example/templates/home.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/templates/home.html b/example/templates/home.html index aad5162f..8714ab73 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -122,6 +122,9 @@ renderer:$.jqplot.BarRenderer, showMarker: false }, + axesDefaults: { + tickRenderer: $.jqplot.CanvasAxisTickRenderer + }, series:[ { pointLabels:{labels:geolabels} From 97f81b699e45b8135a8249ee5b8687c73d6667f8 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 08:46:12 -0500 Subject: [PATCH 20/60] add a deploy-requirements.txt --- deploy-requirements.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 deploy-requirements.txt diff --git a/deploy-requirements.txt b/deploy-requirements.txt new file mode 100644 index 00000000..ed1bed4e --- /dev/null +++ b/deploy-requirements.txt @@ -0,0 +1,3 @@ +. +psycopg2==2.7.7 +gunicorn==19.9.0 From 36086d3780632f86d4b90b0093b0e28d6cc6f0c6 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 09:20:55 -0500 Subject: [PATCH 21/60] add wsgi entrypoint --- example/wsgi.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 example/wsgi.py diff --git a/example/wsgi.py b/example/wsgi.py new file mode 100644 index 00000000..20b8f2d1 --- /dev/null +++ b/example/wsgi.py @@ -0,0 +1,8 @@ +# This is used for staging & production +import os +import sys + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings") + +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application() From 4fc00dd978602cd1a55d3856190cb3729426304c Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 10:01:38 -0500 Subject: [PATCH 22/60] allow local_settings.py overrides --- example/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/example/settings.py b/example/settings.py index f767132e..43cfb22c 100644 --- a/example/settings.py +++ b/example/settings.py @@ -175,3 +175,5 @@ def process_exception(self, request, exception): #DEF_BRANCH = "default" # Defines the default branch to be used. # In git projects, this branch is usually be calles # "master" + +from .local_settings import * From bcd448086cb8d4abce932364d8578e5f675dabf1 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 10:02:45 -0500 Subject: [PATCH 23/60] seems that this isn't handling Django > 1.4... --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5a6a5f18..9a0d5cd6 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ version='0.9.0', url='https://github.com/tobami/codespeed', license='GNU Lesser General Public License version 2.1', - install_requires=['django>=1.3', 'isodate', 'south'], + install_requires=['django>=1.3,<=1.5', 'isodate', 'south'], packages=find_packages(exclude=['ez_setup', 'example']), description='A web application to monitor and analyze the performance of your code', include_package_data=True, From fa1abb45291941600900fa83731eb90a18ba33e5 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 16:24:37 -0500 Subject: [PATCH 24/60] don't use a relative import --- example/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/settings.py b/example/settings.py index 43cfb22c..2aba39eb 100644 --- a/example/settings.py +++ b/example/settings.py @@ -176,4 +176,4 @@ def process_exception(self, request, exception): # In git projects, this branch is usually be calles # "master" -from .local_settings import * +from local_settings import * From b07808f27a65cac9ae4467f2d73f762023065d5c Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 16:41:55 -0500 Subject: [PATCH 25/60] make it so --- example/settings.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/example/settings.py b/example/settings.py index 2aba39eb..956319d5 100644 --- a/example/settings.py +++ b/example/settings.py @@ -1,6 +1,10 @@ # -*- coding: utf-8 -*- # Django settings for a speedcenter project. import os +import os.path +import sys + +sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) DEBUG = True TEMPLATE_DEBUG = DEBUG From aae7f89d5b71c21e3f022ac683d3cd1319aaa9c2 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 14:16:08 +0200 Subject: [PATCH 26/60] Custom PyPy about.html --- sample_project/templates/about.html | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sample_project/templates/about.html b/sample_project/templates/about.html index 7eebe2e7..1c4d6a9c 100644 --- a/sample_project/templates/about.html +++ b/sample_project/templates/about.html @@ -5,18 +5,22 @@

About this site

-

<description of site and what benchmarks that are run>

+

We have nightly benchmark runs of pypy-c-jit and pypy-c, together with cpython 2.6.2 data for comparison.

This site runs on top of Django and Codespeed

About the benchmarks

-

The code can be found here.

-

About MyProject

-

<Description of the main project>

-

Main website: MySite

+

The code can be found here and here.

+

About PyPy

+

PyPy is a very compliant implementation of the Python language.

+

Main website: pypy.org

+ +

Blog: morepypy.blogspot.com

About Codespeed

Codespeed is a web application to monitor and analyze the performance of your code.

Code: github.com/tobami/codespeed

Wiki: wiki.github.com/tobami/codespeed/

Contact

-

For problems or suggestions about this website write to...

+

For problems or suggestions about this website write to

+

the pypy-dev mailing list or directly to Miquel Torres (tobami at googlemail dot com)

+
{% endblock %} From 9c3ec4d784da4ec8ffa7e034ad23d6e9585f4103 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:18:20 +0200 Subject: [PATCH 27/60] Custom PyPy settings --- example/settings.py | 174 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 example/settings.py diff --git a/example/settings.py b/example/settings.py new file mode 100644 index 00000000..8d7efaa3 --- /dev/null +++ b/example/settings.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Django settings for a speedcenter project. +import os + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +BASEDIR = os.path.dirname(__file__) + +#: The directory which should contain checked out source repositories: +REPOSITORY_BASE_PATH = os.path.join(BASEDIR, "repos") + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASEDIR, 'data.db'), + } +} + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = False + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = os.path.join(BASEDIR, "media") + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '/media/' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/static/admin/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 'as%n_m#)^vee2pe91^^@c))sl7^c6t-9r8n)_69%)2yt+(la2&' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + # 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', +) + +if DEBUG: + import traceback + import logging + + # Define a class that logs unhandled errors + class LogUncatchedErrors: + def process_exception(self, request, exception): + logging.error("Unhandled Exception on request for %s\n%s" % + (request.build_absolute_uri(), + traceback.format_exc())) + # And add it to the middleware classes + MIDDLEWARE_CLASSES += ('settings.LogUncatchedErrors',) + + # set shown level of logging output to debug + logging.basicConfig(level=logging.DEBUG) + + +ROOT_URLCONF = 'example.urls' + +TEMPLATE_DIRS = ( + os.path.join(os.path.dirname(__file__), 'templates'), +) + +TEMPLATE_CONTEXT_PROCESSORS = ( + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + 'django.core.context_processors.debug', + 'django.core.context_processors.i18n', + 'django.core.context_processors.media', + 'django.core.context_processors.static', + 'django.core.context_processors.request', +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + #'django.contrib.sites', + 'django.contrib.admin', + 'django.contrib.staticfiles', + 'codespeed', + 'south' +) + +STATIC_URL = '/static/' + +STATIC_ROOT = os.path.join(BASEDIR, "sitestatic") + +# Codespeed settings that can be overwritten here. +## General default options ## +#WEBSITE_NAME = "MySpeedSite" # This name will be used in the reports RSS feed + +#DEF_ENVIRONMENT = None #Name of the environment which should be selected as default + + +DEF_BASELINE = {'executable': 'cpython', 'revision': '100'} # Which executable + revision should be default as a baseline + # Given as the name of the executable and commitid of the revision + # Example: defaultbaseline = {'executable': 'myexe', 'revision': '21'} + +#TREND = 10 # Default value for the depth of the trend + # Used by reports for the latest runs and changes view + +# Threshold that determines when a performance change over the last result is significant +CHANGE_THRESHOLD = 5.0 + +# Threshold that determines when a performance change +# over a number of revisions is significant +TREND_THRESHOLD = 6.0 + +## Changes view options ## +#DEF_EXECUTABLE = None # Executable that should be chosen as default in the changes view + # Given as the name of the executable. + # Example: defaultexecutable = "myexe" + +## Timeline view options ## +#DEF_BENCHMARK = "grid" # Default selected benchmark. Possible values: + # "grid": will show the grid of plots + # "show_none": will just show a text message + # "mybench": will select benchmark "mybench" + +#TIMELINE_BRANCHES = True # NOTE: Only the default branch is currently shown + # Get timeline results for specific branches + # Set to False if you want timeline plots and results only for trunk. + +## Comparison view options ## +#CHART_TYPE = 'normal bars' # The options are 'normal bars', 'stacked bars' and 'relative bars' + +NORMALIZATION = True # True will enable normalization as the default selection + # in the Comparison view. The default normalization can be + # chosen in the defaultbaseline setting + +#CHART_ORIENTATION = 'vertical' # 'vertical' or 'horizontal can be chosen as + # default chart orientation + +COMP_EXECUTABLES = [('pypy-c-jit', 'L'), ('pypy-c', 'L')] # Which executable + revision should be checked as default + # Given as a list of tuples containing the + # name of an executable + commitid of a revision + # An 'L' denotes the last revision + # Example: + # COMP_EXECUTABLES = [ + # ('myexe', '21df2423ra'), + # ('myexe', 'L'),] + From 34f7def947d4d94f2b53a44262a1be069b45a75d Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:42:07 +0200 Subject: [PATCH 28/60] Add custom PyPy homepage --- codespeed/views.py | 44 ++++++++ example/settings.py | 2 +- sample_project/templates/home.html | 168 ++++++++++++++++++++++++++++- 3 files changed, 211 insertions(+), 3 deletions(-) diff --git a/codespeed/views.py b/codespeed/views.py index b3da0f0f..14572462 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -841,6 +841,7 @@ def add_json_results(request): return HttpResponse("All result data saved successfully", status=202) +<<<<<<< HEAD def django_has_content_type(): return (django.VERSION[0] > 1 or (django.VERSION[0] == 1 and django.VERSION[1] >= 6)) @@ -874,3 +875,46 @@ def makeimage(request): response['Content-Disposition'] = 'attachment; filename=image.png' return response +def get_home_data(request): + if request.method != 'GET': + return HttpResponseNotAllowed('GET') + data = {'results': {}, 'benchmarks': []} + env = Environment.objects.get(name='tannit') + # Fetch CPython data + cp_exe = Executable.objects.get(name="cpython") + cp_lastrev = Revision.objects.filter( + branch__project=cp_exe.project).order_by('-date')[0] + cp_results = Result.objects.filter( + executable=cp_exe, revision=cp_lastrev, environment=env) + # Fetch PyPy trunk data + pp_exe = Executable.objects.get(name="pypy-c-jit") + pp_branch = Branch.objects.get(name="default", project=pp_exe.project) + pp_lastrev = Revision.objects.filter(branch=pp_branch).order_by('-date')[0] + pp_results = Result.objects.filter( + executable=pp_exe, revision=pp_lastrev, environment=env) + # Fetch PyPy tagged revisions + pp_taggedrevs = Revision.objects.filter( + project=pp_exe.project + ).exclude(tag="").order_by('date') + data['tagged_revs'] = [rev.tag for rev in pp_taggedrevs] + pp_results = {'PyPy trunk': pp_results} + for rev in pp_taggedrevs: + pp_results[rev.tag] = Result.objects.filter( + executable=pp_exe, revision=rev, environment=env) + # Save data + benchmarks = [] + for res in cp_results: + if res == 0: + continue + benchmarks.append(res.benchmark.name) + key = 'CPython ' + cp_lastrev.tag + data['results'][res.benchmark.name] = {key: res.value} + for rev_name in pp_results: + val = 0 + for pp_res in pp_results[rev_name]: + if pp_res.benchmark.name == res.benchmark.name: + val = pp_res.value + data['results'][res.benchmark.name][rev_name] = val + benchmarks.sort() + data['benchmarks'] = benchmarks + return HttpResponse(json.dumps( data )) diff --git a/example/settings.py b/example/settings.py index 8d7efaa3..73027dcf 100644 --- a/example/settings.py +++ b/example/settings.py @@ -119,7 +119,7 @@ def process_exception(self, request, exception): # Codespeed settings that can be overwritten here. ## General default options ## -#WEBSITE_NAME = "MySpeedSite" # This name will be used in the reports RSS feed +WEBSITE_NAME = "PyPy Speed Center" # This name will be used in the reports RSS feed #DEF_ENVIRONMENT = None #Name of the environment which should be selected as default diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index 67848d37..14a33f92 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -30,7 +30,137 @@

Comparison

{% block extra_body %} {{ block.super }} + + + + + + + + + {% endblock %} +{% block navigation %} +{% endblock navigation %} + +{% block body %} +
+ + + +
+ +
+

How fast is PyPy?

+
+

Plot 1: The above plot represents PyPy trunk (with JIT) benchmark times normalized to CPython. Smaller is better.

+

While it depends greately on the type of taks being performed, currently PyPy takes % of the time that CPython needs to complete an average given task (represented by the geometric mean of all benchmarks), which means that PyPy is about times faster than CPython

+

How has PyPy performance evolved over time?

+
+

Plot 2: Geometric averages of normalized times, out of benchmarks. Smaller is better. "times faster" inside parenthesis

+
+
+{% endblock body %} From ab6063cc2f244cba178e1ab5fa6045615902ee66 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:44:19 +0200 Subject: [PATCH 29/60] Add Google Analytics script --- example/templates/base.html | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 example/templates/base.html diff --git a/example/templates/base.html b/example/templates/base.html new file mode 100644 index 00000000..cc60dfb4 --- /dev/null +++ b/example/templates/base.html @@ -0,0 +1,75 @@ + + + + {% block title %}PyPy's Speed Center{% endblock %} + + + + + + + + + {% block extra_head %}{% endblock %} + + +
+ {# TODO: Rename id=title to id=header and/or switch to
#} +
+ {% block page_header %} + {% block logo %} + logo + {% endblock logo %} +

{% block page_title %}SPEED CENTER{% endblock page_title %}

+ {% block top_nav %} + + {% endblock top_nav %} + {% endblock page_header %} +
+ +
+ +
+{% block body %} +
Base template
+{% endblock %} +
+
+{% block footer %} + + + +{% endblock %} +
+ + + + From 4adbb14598ba308be9a24311af3f683d6b1b10a9 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:45:05 +0200 Subject: [PATCH 30/60] Add pointlabels jqplot plugin for Home page plot --- .../static/js/jqplot/jqplot.pointLabels.min.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 codespeed/static/js/jqplot/jqplot.pointLabels.min.js diff --git a/codespeed/static/js/jqplot/jqplot.pointLabels.min.js b/codespeed/static/js/jqplot/jqplot.pointLabels.min.js new file mode 100644 index 00000000..2bf8a86d --- /dev/null +++ b/codespeed/static/js/jqplot/jqplot.pointLabels.min.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2009 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT and GPL version 2.0 licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris dot leonello at gmail dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + */ +(function(c){c.jqplot.PointLabels=function(e){this.show=c.jqplot.config.enablePlugins;this.location="n";this.labelsFromSeries=false;this.seriesLabelIndex=null;this.labels=[];this.stackedValue=false;this.ypadding=6;this.xpadding=6;this.escapeHTML=true;this.edgeTolerance=0;this.hideZeros=false;c.extend(true,this,e)};var a=["nw","n","ne","e","se","s","sw","w"];var d={nw:0,n:1,ne:2,e:3,se:4,s:5,sw:6,w:7};var b=["se","s","sw","w","nw","n","ne","e"];c.jqplot.PointLabels.init=function(k,h,g,e){var n=c.extend(true,{},g,e);this.plugins.pointLabels=new c.jqplot.PointLabels(n.pointLabels);var f=this.plugins.pointLabels;if(f.labels.length==0||f.labelsFromSeries){if(f.stackedValue){if(this._plotData.length&&this._plotData[0].length){var m=f.seriesLabelIndex||this._plotData[0].length-1;for(var j=0;j');u.insertAfter(s.canvas);if(q.escapeHTML){u.text(m)}else{u.html(m)}var f=q.location;if(this.waterfall&&parseInt(m,10)<0){f=b[d[f]]}var l=v.u2p(y[r][0])+q.xOffset(u,f);var g=n.u2p(y[r][1])+q.yOffset(u,f);u.css("left",l);u.css("top",g);var j=l+c(u).width();var o=g+c(u).height();var x=q.edgeTolerance;var e=c(s.canvas).position().left;var t=c(s.canvas).position().top;var w=s.canvas.width+e;var k=s.canvas.height+t;if(l-xw||o+x>k){c(u).remove()}}}};c.jqplot.postSeriesInitHooks.push(c.jqplot.PointLabels.init);c.jqplot.postDrawSeriesHooks.push(c.jqplot.PointLabels.draw)})(jQuery); \ No newline at end of file From de207b9b6414e23b47b2533915aae81707a8536e Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 15:56:00 +0200 Subject: [PATCH 31/60] Add PyPy favicon --- example/override/static/images/favicon.ico | Bin 0 -> 3230 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 example/override/static/images/favicon.ico diff --git a/example/override/static/images/favicon.ico b/example/override/static/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c79bb6ded95b2a0035b0a9c47c7f2785cfbed0c1 GIT binary patch literal 3230 zcmcIm2~ZSA6rJ5!&S41Xf;r$ zqM;n$@_8clzhRx^3y<0yxNOOWLwN@5E3@F(uoR~Af}pCc0X2Osa6&;p<3>tWSl8 zttqR^inqu?o%-HNTpdlKHY5kogI*c5YB9RcX!0AL5>p~plPM99)42uv)7P)el8tFh0|Do15q5JsypNP(wD|-W z%=Ct3Od?$KiwUoy`dGk=bce_xKQ-72J*`R{s)|NMX$*2p;;^_m1G$|Wk#V{V$>*xz zx;YI|7aI`vL+yZm*!69YmS@5wB@m+wwFh#s%gBZ_a|yAWoru{7Pa|sIQKC9t^ASIC z zoN0(7olWsXJYF3F0p~}_JVh`?wMbp1-#EY?CUQ57nWW2fJ1G9|UF!^L*olnZM@Tr< zgMg}S(6*TYfl#PVeV#K50}WhinFFTJ>MxzD!?dlQBR%V|8jgF`eP!!}TR}1LD{q8< zMGMP;)u42chg;UH={Q#(GoXL0DvFJ(We{h0U4g*J$ioLgTX!O)aW59%1B<z95Od)MG#;&E!Y(i%UY-`x-gcgaM?OCQX8lfJr^n4Ob-Aq~3;dk0gx zdl9f@VE$iL+vdG%1IhPwv<6Lc(7Y-L*5+cC!{#^9e99FFrqTAVzUB2qvF9+6e|8Yj z`%hxLsRe|h5hI@R{%xqMig;}eb^P3>1RMXi)iEf}@kU&PEkwNVZ%WIfU}wTm=1vJ; zi)|$ctZgO9-B(Cb*JaE;a0)JYYuR`{enkK`yUAi)Y)d3v&GFbxwy~Vp|0aqH9~c|LQ05Jvnyn}yw(c%b z3}t?16UU*uHGv#&NhJH~lvwpq5OQ*Zky#jt^b#c$>y>a>u7K5IIjr&$;jn2Lk+oG4 zS#uS9>Z&2Du7RTcFf#i7K+b)Fz?wET?w>~M>a+DQq=|TeDJA{3EZG?+_N3#>-Sbh` zl8zN+O3d3B5BWMJWW`C4mZU*inggebe0bEAz;8!AA`iABj(*x&s|NJs1RRa|Zo@b$`flh7@CaIenFm n-h7oK08g>{Kj1qGh)S>fW0i+|;n>HN&;015(^x74VcF#$?Vs(& literal 0 HcmV?d00001 From e2b197f24219ab99527d8a9a298c59d3b573a2d1 Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 17 Jul 2011 20:15:34 +0200 Subject: [PATCH 32/60] Add legend to first "home" plot --- codespeed/static/css/main.css | 2 +- sample_project/templates/home.html | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/codespeed/static/css/main.css b/codespeed/static/css/main.css index 34afa5bc..d1a2fbe3 100644 --- a/codespeed/static/css/main.css +++ b/codespeed/static/css/main.css @@ -119,7 +119,7 @@ div#presentation div.menubox { } div#presentation div.menubox:hover { border: 5px solid #FFCE9C; } -div#presentation p { height: 5em; padding-left: 120px; } +div#presentation div.menubox p { height: 5em; padding-left: 120px; } div#presentation div#changes p { background: url(../images/changes.png) no-repeat; diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index 14a33f92..910bc79e 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -82,10 +82,11 @@

Comparison

} trunk_geomean = Math.pow(trunk_geomean, 1/plotdata[0].length); var geofaster = 1/trunk_geomean; - $('#geomean').html((100*trunk_geomean).toFixed(1)); + $('#geomean').html(trunk_geomean.toFixed(2)); $('#geofaster').html(geofaster.toFixed(1)); // Render first plot plotoptions1 = { + legend:{show:true}, seriesDefaults: { showMarker: false, rendererOptions:{barPadding: 2, barMargin:5} @@ -95,10 +96,14 @@

Comparison

}, series:[ { + label: 'PyPy trunk', renderer:$.jqplot.BarRenderer, pointLabels:{labels:labels} }, - {pointLabels:{show:false}} + { + label: 'CPython', + pointLabels:{show:false} + } ], axes: { xaxis: { @@ -113,7 +118,7 @@

Comparison

} }; plot1 = $.jqplot("cpythonplot", plotdata, plotoptions1); - + // Prepare and render second plot var geomeans = [1.0]; var num_of_benchs = 0; @@ -137,6 +142,7 @@

Comparison

geolabels.push(geomeans[i].toFixed(2) + " (" + (1/geomeans[i]).toFixed(1) + "x)"); } $('#num_of_benchs').html(num_of_benchs) + plotoptions2 = { seriesDefaults: { renderer:$.jqplot.BarRenderer, @@ -210,12 +216,13 @@

Comparison


-
+

How fast is PyPy?

Plot 1: The above plot represents PyPy trunk (with JIT) benchmark times normalized to CPython. Smaller is better.

-

While it depends greately on the type of taks being performed, currently PyPy takes % of the time that CPython needs to complete an average given task (represented by the geometric mean of all benchmarks), which means that PyPy is about times faster than CPython

+

It depends greatly on the type of task being performed. The geometric average of all benchmarks is or times faster than CPython

How has PyPy performance evolved over time?

+

Plot 2: Geometric averages of normalized times, out of benchmarks. Smaller is better. "times faster" inside parenthesis

From 209dab0af360166e390744a1bc32caa0a27a0fbf Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Mon, 18 Jul 2011 21:56:27 +0200 Subject: [PATCH 33/60] Don't choose a revision that doesn't have results for pypy-c-jit --- codespeed/views.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/codespeed/views.py b/codespeed/views.py index 14572462..127e108d 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -886,21 +886,32 @@ def get_home_data(request): branch__project=cp_exe.project).order_by('-date')[0] cp_results = Result.objects.filter( executable=cp_exe, revision=cp_lastrev, environment=env) - # Fetch PyPy trunk data + pp_exe = Executable.objects.get(name="pypy-c-jit") pp_branch = Branch.objects.get(name="default", project=pp_exe.project) - pp_lastrev = Revision.objects.filter(branch=pp_branch).order_by('-date')[0] - pp_results = Result.objects.filter( - executable=pp_exe, revision=pp_lastrev, environment=env) # Fetch PyPy tagged revisions pp_taggedrevs = Revision.objects.filter( project=pp_exe.project ).exclude(tag="").order_by('date') data['tagged_revs'] = [rev.tag for rev in pp_taggedrevs] - pp_results = {'PyPy trunk': pp_results} + pp_results = {} for rev in pp_taggedrevs: pp_results[rev.tag] = Result.objects.filter( executable=pp_exe, revision=rev, environment=env) + + # Fetch PyPy trunk data + revs = Revision.objects.filter(branch=pp_branch).order_by('-date')[:5] + pp_lastrev = None + for i in range(4): + pp_lastrev = revs[i] + if pp_lastrev.results.filter(executable=pp_exe): + break + pp_lastrev = None + if pp_lastrev is None: + return HttpResponse(json.dumps( data )) + pp_results['PyPy trunk'] = Result.objects.filter( + executable=pp_exe, revision=pp_lastrev, environment=env) + # Save data benchmarks = [] for res in cp_results: From b5b96d13e0cee972265a5998555de532f477680a Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Sun, 21 Aug 2011 17:37:21 +0200 Subject: [PATCH 34/60] Improve pypy branch query, set WEBSITE_NAME and project name in template --- codespeed/settings.py | 2 +- codespeed/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codespeed/settings.py b/codespeed/settings.py index 4e3b5d59..d191b339 100644 --- a/codespeed/settings.py +++ b/codespeed/settings.py @@ -2,7 +2,7 @@ """Default settings for Codespeed""" ## General default options ## -WEBSITE_NAME = "MySpeedSite" # This name will be used in the reports RSS feed +WEBSITE_NAME = "PyPy's Speed Center" # This name will be used in the reports RSS feed DEF_ENVIRONMENT = None # Name of the environment which should be selected as default diff --git a/codespeed/views.py b/codespeed/views.py index 127e108d..4837f56e 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -891,7 +891,7 @@ def get_home_data(request): pp_branch = Branch.objects.get(name="default", project=pp_exe.project) # Fetch PyPy tagged revisions pp_taggedrevs = Revision.objects.filter( - project=pp_exe.project + branch=pp_branch ).exclude(tag="").order_by('date') data['tagged_revs'] = [rev.tag for rev in pp_taggedrevs] pp_results = {} From 3e9c67f761284150f95972e5e8f9157c65b7d03c Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Thu, 17 May 2012 11:53:48 +0200 Subject: [PATCH 35/60] Use the proper key for CPython data Update default baseline Increase width of second graph --- codespeed/views.py | 4 ++-- example/settings.py | 2 +- sample_project/templates/home.html | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/codespeed/views.py b/codespeed/views.py index 4837f56e..37f7db1a 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -884,6 +884,7 @@ def get_home_data(request): cp_exe = Executable.objects.get(name="cpython") cp_lastrev = Revision.objects.filter( branch__project=cp_exe.project).order_by('-date')[0] + data['baseline'] = 'CPython ' + cp_lastrev.tag cp_results = Result.objects.filter( executable=cp_exe, revision=cp_lastrev, environment=env) @@ -918,8 +919,7 @@ def get_home_data(request): if res == 0: continue benchmarks.append(res.benchmark.name) - key = 'CPython ' + cp_lastrev.tag - data['results'][res.benchmark.name] = {key: res.value} + data['results'][res.benchmark.name] = {data['baseline']: res.value} for rev_name in pp_results: val = 0 for pp_res in pp_results[rev_name]: diff --git a/example/settings.py b/example/settings.py index 73027dcf..061232f7 100644 --- a/example/settings.py +++ b/example/settings.py @@ -124,7 +124,7 @@ def process_exception(self, request, exception): #DEF_ENVIRONMENT = None #Name of the environment which should be selected as default -DEF_BASELINE = {'executable': 'cpython', 'revision': '100'} # Which executable + revision should be default as a baseline +DEF_BASELINE = {'executable': 'cpython', 'revision': '101'} # Which executable + revision should be default as a baseline # Given as the name of the executable and commitid of the revision # Example: defaultbaseline = {'executable': 'myexe', 'revision': '21'} diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index 910bc79e..93baf3e7 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -66,7 +66,7 @@

Comparison

add_to_tagged_data = false; } if (add_to_tagged_data === false) { break; } - relative_value = data['results'][benchname][rev]/data['results'][benchname]['CPython 2.6.2']; + relative_value = data['results'][benchname][rev]/data['results'][benchname][data['baseline']]; tagged_data[i].push(relative_value) } // Only add benchmark if there are no 0 values @@ -74,7 +74,7 @@

Comparison

// First add benchmark benchmarks.push(benchname); // Add PyPy trunk and CPython's 1.0 value - relative_value = data['results'][benchname]['PyPy trunk']/data['results'][benchname]['CPython 2.6.2']; + relative_value = data['results'][benchname]['PyPy trunk']/data['results'][benchname][data['baseline']]; plotdata[0].push(relative_value); plotdata[1].push(1.0); labels.push(relative_value.toFixed(2)); @@ -101,7 +101,7 @@

Comparison

pointLabels:{labels:labels} }, { - label: 'CPython', + label: data['baseline'], pointLabels:{show:false} } ], @@ -112,7 +112,7 @@

Comparison

tickOptions: {angle: -40} }, yaxis:{ - ticks: [0, 0.25, 0.5, 0.75, 1, 1.25, 1.5], + ticks: [0, 0.25, 0.5, 0.75, 1, 1.25], tickOptions:{formatString:'%.2f'} } } @@ -132,7 +132,7 @@

Comparison

geomeans.push(tempgeo); } geomeans.push(trunk_geomean); - var ticks = ['CPython 2.6.2']; + var ticks = [data['baseline']]; for (var i in data['tagged_revs']) { ticks.push(data['tagged_revs'][i]); } @@ -223,7 +223,7 @@

How fast is PyPy?

It depends greatly on the type of task being performed. The geometric average of all benchmarks is or times faster than CPython

How has PyPy performance evolved over time?

-
+

Plot 2: Geometric averages of normalized times, out of benchmarks. Smaller is better. "times faster" inside parenthesis

From 23d5aafc8e47f8084f9f0c7a9f5316d36d72408c Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Fri, 8 Jun 2012 14:43:38 +0200 Subject: [PATCH 36/60] Invert plot 2 --- sample_project/templates/home.html | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index 93baf3e7..2efcbc62 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -129,17 +129,19 @@

Comparison

tempgeo *= tagged_data[i][j]; } tempgeo = Math.pow(tempgeo, 1/tagged_data[i].length); + tempgeo = 1/tempgeo; geomeans.push(tempgeo); } - geomeans.push(trunk_geomean); + geomeans.push(1/trunk_geomean); var ticks = [data['baseline']]; for (var i in data['tagged_revs']) { ticks.push(data['tagged_revs'][i]); } ticks.push('PyPy trunk'); var geolabels = new Array(); - for (var i in geomeans) { - geolabels.push(geomeans[i].toFixed(2) + " (" + (1/geomeans[i]).toFixed(1) + "x)"); + for (var i in geomeans) { +// geolabels.push(geomeans[i].toFixed(2) + " (" + (1/geomeans[i]).toFixed(1) + "x)"); + geolabels.push(geomeans[i].toFixed(2) + "x"); } $('#num_of_benchs').html(num_of_benchs) @@ -159,7 +161,8 @@

Comparison

ticks: ticks }, yaxis:{ - ticks: [0.0, 0.25, 0.5, 0.75, 1.0, 1.25], +// ticks: [0.0, 0.25, 0.5, 0.75, 1.0, 1.25], + min: 0, tickOptions:{formatString:'%.2f'} } } @@ -224,7 +227,7 @@

How fast is PyPy?

How has PyPy performance evolved over time?

-

Plot 2: Geometric averages of normalized times, out of benchmarks. Smaller is better. "times faster" inside parenthesis

+

Plot 2: Speedup compared to CPython, using the inverse of the geometric average of normalized times, out of benchmarks.

{% endblock body %} From c15ab3b5022bad228e01205e609ea9cd226b9cfa Mon Sep 17 00:00:00 2001 From: Miquel Torres Date: Fri, 8 Jun 2012 15:04:38 +0200 Subject: [PATCH 37/60] Add reference to paper explaining geometric mean for normalized results --- sample_project/templates/home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index 2efcbc62..9b137b3d 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -227,7 +227,7 @@

How fast is PyPy?

How has PyPy performance evolved over time?

-

Plot 2: Speedup compared to CPython, using the inverse of the geometric average of normalized times, out of benchmarks.

+

Plot 2: Speedup compared to CPython, using the inverse of the geometric average of normalized times, out of benchmarks (see paper on why the geometric mean is better for normalized results).

{% endblock body %} From cdb2941f0bd2e4a71425afc2bc7fd14645166a4f Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 6 Jan 2013 12:19:33 -0800 Subject: [PATCH 38/60] exec wrapper script. --- manage.py | 1 + 1 file changed, 1 insertion(+) diff --git a/manage.py b/manage.py index 1c3713d6..9f56f9db 100755 --- a/manage.py +++ b/manage.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import os, sys + if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sample_project.settings") From 10bec1909510b04c1c7608df602f7cef2815da1e Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 6 Jan 2013 12:25:18 -0800 Subject: [PATCH 39/60] unix is hard. --- manage.py | 1 - 1 file changed, 1 deletion(-) diff --git a/manage.py b/manage.py index 9f56f9db..1c3713d6 100755 --- a/manage.py +++ b/manage.py @@ -1,7 +1,6 @@ #!/usr/bin/env python import os, sys - if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sample_project.settings") From 29dec697781fd8a9a14bb9c3c7603976a45d1afc Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 6 Jan 2013 12:32:53 -0800 Subject: [PATCH 40/60] No really, I'm bad at unix. --- manage.py | 1 - 1 file changed, 1 deletion(-) diff --git a/manage.py b/manage.py index 1c3713d6..dd62d642 100755 --- a/manage.py +++ b/manage.py @@ -5,5 +5,4 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sample_project.settings") from django.core.management import execute_from_command_line - execute_from_command_line(sys.argv) From 92fd0b18e33c6ec6130ccbfa29ad51560c6114f6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 7 Jan 2013 12:21:12 -0800 Subject: [PATCH 41/60] Incrase the size of a field --- .../009_auto__chg_field_branch_name.py | 97 +++++++++++++++++++ codespeed/models.py | 2 +- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 codespeed/migrations/009_auto__chg_field_branch_name.py diff --git a/codespeed/migrations/009_auto__chg_field_branch_name.py b/codespeed/migrations/009_auto__chg_field_branch_name.py new file mode 100644 index 00000000..f35dcc57 --- /dev/null +++ b/codespeed/migrations/009_auto__chg_field_branch_name.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Changing field 'Branch.name' + db.alter_column('codespeed_branch', 'name', self.gf('django.db.models.fields.CharField')(max_length=50)) + + def backwards(self, orm): + # Changing field 'Branch.name' + db.alter_column('codespeed_branch', 'name', self.gf('django.db.models.fields.CharField')(max_length=20)) + + models = { + 'codespeed.benchmark': { + 'Meta': {'object_name': 'Benchmark'}, + 'benchmark_type': ('django.db.models.fields.CharField', [], {'default': "'C'", 'max_length': '1'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'lessisbetter': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'units': ('django.db.models.fields.CharField', [], {'default': "'seconds'", 'max_length': '20'}), + 'units_title': ('django.db.models.fields.CharField', [], {'default': "'Time'", 'max_length': '30'}) + }, + 'codespeed.branch': { + 'Meta': {'unique_together': "(('name', 'project'),)", 'object_name': 'Branch'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'branches'", 'to': "orm['codespeed.Project']"}) + }, + 'codespeed.environment': { + 'Meta': {'object_name': 'Environment'}, + 'cpu': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kernel': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'memory': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'os': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}) + }, + 'codespeed.executable': { + 'Meta': {'object_name': 'Executable'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'executables'", 'to': "orm['codespeed.Project']"}) + }, + 'codespeed.project': { + 'Meta': {'object_name': 'Project'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'repo_pass': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'repo_path': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'repo_type': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1'}), + 'repo_user': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'track': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'codespeed.report': { + 'Meta': {'unique_together': "(('revision', 'executable', 'environment'),)", 'object_name': 'Report'}, + '_tablecache': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'colorcode': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '10'}), + 'environment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Environment']"}), + 'executable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Executable']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'revision': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Revision']"}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) + }, + 'codespeed.result': { + 'Meta': {'unique_together': "(('revision', 'executable', 'benchmark', 'environment'),)", 'object_name': 'Result'}, + 'benchmark': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Benchmark']"}), + 'date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'environment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Environment']"}), + 'executable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Executable']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'revision': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Revision']"}), + 'std_dev': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'val_max': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'val_min': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'value': ('django.db.models.fields.FloatField', [], {}) + }, + 'codespeed.revision': { + 'Meta': {'unique_together': "(('commitid', 'branch'),)", 'object_name': 'Revision'}, + 'author': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'branch': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['codespeed.Branch']"}), + 'commitid': ('django.db.models.fields.CharField', [], {'max_length': '42'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['codespeed.Project']"}), + 'tag': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}) + } + } + + complete_apps = ['codespeed'] diff --git a/codespeed/models.py b/codespeed/models.py index 4c707a7b..301c7545 100644 --- a/codespeed/models.py +++ b/codespeed/models.py @@ -104,7 +104,7 @@ def is_less_important_than(self, val, color): @python_2_unicode_compatible class Branch(models.Model): - name = models.CharField(max_length=32) + name = models.CharField(max_length=50) project = models.ForeignKey(Project, related_name="branches") def __str__(self): From 65a938d9870efaf1560555d1877f1b4eb1d4b80c Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 28 Nov 2014 09:10:43 +0200 Subject: [PATCH 42/60] tilt xlabels on Plot 2 --- sample_project/templates/home.html | 1 + 1 file changed, 1 insertion(+) diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index 9b137b3d..60be12d8 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -159,6 +159,7 @@

Comparison

xaxis: { renderer: $.jqplot.CategoryAxisRenderer, ticks: ticks + tickOptions: {angle: -40} }, yaxis:{ // ticks: [0.0, 0.25, 0.5, 0.75, 1.0, 1.25], From 3de9041eda0ff9030eab603d9dc51fe465388e20 Mon Sep 17 00:00:00 2001 From: mattip Date: Sat, 29 Nov 2014 21:33:21 +0200 Subject: [PATCH 43/60] whoops --- sample_project/templates/home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index 60be12d8..ce8c4272 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -158,7 +158,7 @@

Comparison

axes: { xaxis: { renderer: $.jqplot.CategoryAxisRenderer, - ticks: ticks + ticks: ticks, tickOptions: {angle: -40} }, yaxis:{ From 92d277dbb3b6d1ccc10df2fef2ceef392a737edd Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 26 Dec 2014 14:39:47 +0200 Subject: [PATCH 44/60] test, fix angling x-axis on cpythonplot2 --- sample_project/templates/home.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index ce8c4272..094c987d 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -150,6 +150,9 @@

Comparison

renderer:$.jqplot.BarRenderer, showMarker: false }, + axesDefaults: { + tickRenderer: $.jqplot.CanvasAxisTickRenderer + }, series:[ { pointLabels:{labels:geolabels} From bfccbec29ef10981762562df821b20fb488d7473 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 08:46:12 -0500 Subject: [PATCH 45/60] add a deploy-requirements.txt --- deploy-requirements.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 deploy-requirements.txt diff --git a/deploy-requirements.txt b/deploy-requirements.txt new file mode 100644 index 00000000..ed1bed4e --- /dev/null +++ b/deploy-requirements.txt @@ -0,0 +1,3 @@ +. +psycopg2==2.7.7 +gunicorn==19.9.0 From 5f4eeedbb97e2a238ce5667d9baaa94f590a545d Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 09:20:55 -0500 Subject: [PATCH 46/60] add wsgi entrypoint --- example/wsgi.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 example/wsgi.py diff --git a/example/wsgi.py b/example/wsgi.py new file mode 100644 index 00000000..20b8f2d1 --- /dev/null +++ b/example/wsgi.py @@ -0,0 +1,8 @@ +# This is used for staging & production +import os +import sys + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings") + +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application() From f15a60584a5f0361a8e1ca2e8a97c7da31346b76 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 10:01:38 -0500 Subject: [PATCH 47/60] allow local_settings.py overrides --- example/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/example/settings.py b/example/settings.py index 061232f7..b1dc01ac 100644 --- a/example/settings.py +++ b/example/settings.py @@ -172,3 +172,4 @@ def process_exception(self, request, exception): # ('myexe', '21df2423ra'), # ('myexe', 'L'),] +from .local_settings import * From f7cbe313403dfab7bbcbec9e0b1695e9233ae835 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 10:02:45 -0500 Subject: [PATCH 48/60] seems that this isn't handling Django > 1.4... --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 80ba4b89..025cfd16 100644 --- a/setup.py +++ b/setup.py @@ -31,3 +31,4 @@ 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', ] ) + From a586c60e26effef090f99f30a5c93f5056109727 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 16:24:37 -0500 Subject: [PATCH 49/60] don't use a relative import --- example/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/example/settings.py b/example/settings.py index b1dc01ac..5436a9a1 100644 --- a/example/settings.py +++ b/example/settings.py @@ -173,3 +173,4 @@ def process_exception(self, request, exception): # ('myexe', 'L'),] from .local_settings import * + From 1e08ed172e174aa13a0ba05c853badf90053c5ea Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Fri, 22 Feb 2019 16:41:55 -0500 Subject: [PATCH 50/60] make it so --- example/settings.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/example/settings.py b/example/settings.py index 5436a9a1..f63cf7ae 100644 --- a/example/settings.py +++ b/example/settings.py @@ -1,6 +1,10 @@ # -*- coding: utf-8 -*- # Django settings for a speedcenter project. import os +import os.path +import sys + +sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) DEBUG = True TEMPLATE_DEBUG = DEBUG From 984b0d8a240a5237f9116b5ddaf7bc8eca6996e3 Mon Sep 17 00:00:00 2001 From: mattip Date: Tue, 2 Apr 2019 22:53:46 +0300 Subject: [PATCH 51/60] fix merge and update --- codespeed/commits/mercurial.py | 2 +- .../009_auto__chg_field_branch_name.py | 97 ------------------ codespeed/models.py | 2 +- codespeed/settings.py | 2 +- .../static/images/favicon.ico | Bin codespeed/views.py | 55 ---------- sample_project/settings.py | 14 ++- sample_project/templates/about.html | 7 +- .../templates/codespeed/base_site.html | 2 +- sample_project/templates/home.html | 37 +------ 10 files changed, 24 insertions(+), 194 deletions(-) delete mode 100644 codespeed/migrations/009_auto__chg_field_branch_name.py rename {example/override => codespeed}/static/images/favicon.ico (100%) diff --git a/codespeed/commits/mercurial.py b/codespeed/commits/mercurial.py index de0c63e8..ffe132eb 100644 --- a/codespeed/commits/mercurial.py +++ b/codespeed/commits/mercurial.py @@ -63,7 +63,7 @@ def getlogs(endrev, startrev): if p.returncode != 0: raise CommitLogError(str(stderr)) else: - stdout = stdout.rstrip('\n') # Remove last newline + stdout = stdout.rstrip(b'\n') # Remove last newline logs = [] for log in stdout.split("=newlog=\n"): elements = [] diff --git a/codespeed/migrations/009_auto__chg_field_branch_name.py b/codespeed/migrations/009_auto__chg_field_branch_name.py deleted file mode 100644 index f35dcc57..00000000 --- a/codespeed/migrations/009_auto__chg_field_branch_name.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Changing field 'Branch.name' - db.alter_column('codespeed_branch', 'name', self.gf('django.db.models.fields.CharField')(max_length=50)) - - def backwards(self, orm): - # Changing field 'Branch.name' - db.alter_column('codespeed_branch', 'name', self.gf('django.db.models.fields.CharField')(max_length=20)) - - models = { - 'codespeed.benchmark': { - 'Meta': {'object_name': 'Benchmark'}, - 'benchmark_type': ('django.db.models.fields.CharField', [], {'default': "'C'", 'max_length': '1'}), - 'description': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'lessisbetter': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), - 'units': ('django.db.models.fields.CharField', [], {'default': "'seconds'", 'max_length': '20'}), - 'units_title': ('django.db.models.fields.CharField', [], {'default': "'Time'", 'max_length': '30'}) - }, - 'codespeed.branch': { - 'Meta': {'unique_together': "(('name', 'project'),)", 'object_name': 'Branch'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'branches'", 'to': "orm['codespeed.Project']"}) - }, - 'codespeed.environment': { - 'Meta': {'object_name': 'Environment'}, - 'cpu': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'kernel': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'memory': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), - 'os': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}) - }, - 'codespeed.executable': { - 'Meta': {'object_name': 'Executable'}, - 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'executables'", 'to': "orm['codespeed.Project']"}) - }, - 'codespeed.project': { - 'Meta': {'object_name': 'Project'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), - 'repo_pass': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), - 'repo_path': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), - 'repo_type': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1'}), - 'repo_user': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), - 'track': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) - }, - 'codespeed.report': { - 'Meta': {'unique_together': "(('revision', 'executable', 'environment'),)", 'object_name': 'Report'}, - '_tablecache': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'colorcode': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '10'}), - 'environment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Environment']"}), - 'executable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Executable']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'revision': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Revision']"}), - 'summary': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) - }, - 'codespeed.result': { - 'Meta': {'unique_together': "(('revision', 'executable', 'benchmark', 'environment'),)", 'object_name': 'Result'}, - 'benchmark': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Benchmark']"}), - 'date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'environment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Environment']"}), - 'executable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Executable']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'revision': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Revision']"}), - 'std_dev': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'val_max': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'val_min': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'value': ('django.db.models.fields.FloatField', [], {}) - }, - 'codespeed.revision': { - 'Meta': {'unique_together': "(('commitid', 'branch'),)", 'object_name': 'Revision'}, - 'author': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'branch': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['codespeed.Branch']"}), - 'commitid': ('django.db.models.fields.CharField', [], {'max_length': '42'}), - 'date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['codespeed.Project']"}), - 'tag': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}) - } - } - - complete_apps = ['codespeed'] diff --git a/codespeed/models.py b/codespeed/models.py index f673d43c..82e55444 100644 --- a/codespeed/models.py +++ b/codespeed/models.py @@ -475,7 +475,7 @@ def get_changes_table(self, trend_depth=10, force_save=False): val_max = "-" # Calculate percentage change relative to previous result - result = resobj.value + result = max(resobj.value, 0) change = "-" if len(change_list): c = change_list.filter(benchmark=bench) diff --git a/codespeed/settings.py b/codespeed/settings.py index 70390e0e..42a38678 100644 --- a/codespeed/settings.py +++ b/codespeed/settings.py @@ -2,7 +2,7 @@ """Default settings for Codespeed""" ## General default options ## -WEBSITE_NAME = "PyPy's Speed Center" # This name will be used in the reports RSS feed +WEBSITE_NAME = "MySpeedSite" # This name will be used in the reports RSS feed DEF_ENVIRONMENT = None # Name of the environment which should be selected as default diff --git a/example/override/static/images/favicon.ico b/codespeed/static/images/favicon.ico similarity index 100% rename from example/override/static/images/favicon.ico rename to codespeed/static/images/favicon.ico diff --git a/codespeed/views.py b/codespeed/views.py index 8199db54..b498bdb4 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -926,7 +926,6 @@ def add_json_results(request): return HttpResponse("All result data saved successfully", status=202) -<<<<<<< HEAD def django_has_content_type(): return (django.VERSION[0] > 1 or (django.VERSION[0] == 1 and django.VERSION[1] >= 6)) @@ -960,57 +959,3 @@ def makeimage(request): response['Content-Disposition'] = 'attachment; filename=image.png' return response -def get_home_data(request): - if request.method != 'GET': - return HttpResponseNotAllowed('GET') - data = {'results': {}, 'benchmarks': []} - env = Environment.objects.get(name='tannit') - # Fetch CPython data - cp_exe = Executable.objects.get(name="cpython") - cp_lastrev = Revision.objects.filter( - branch__project=cp_exe.project).order_by('-date')[0] - data['baseline'] = 'CPython ' + cp_lastrev.tag - cp_results = Result.objects.filter( - executable=cp_exe, revision=cp_lastrev, environment=env) - - pp_exe = Executable.objects.get(name="pypy-c-jit") - pp_branch = Branch.objects.get(name="default", project=pp_exe.project) - # Fetch PyPy tagged revisions - pp_taggedrevs = Revision.objects.filter( - branch=pp_branch - ).exclude(tag="").order_by('date') - data['tagged_revs'] = [rev.tag for rev in pp_taggedrevs] - pp_results = {} - for rev in pp_taggedrevs: - pp_results[rev.tag] = Result.objects.filter( - executable=pp_exe, revision=rev, environment=env) - - # Fetch PyPy trunk data - revs = Revision.objects.filter(branch=pp_branch).order_by('-date')[:5] - pp_lastrev = None - for i in range(4): - pp_lastrev = revs[i] - if pp_lastrev.results.filter(executable=pp_exe): - break - pp_lastrev = None - if pp_lastrev is None: - return HttpResponse(json.dumps( data )) - pp_results['PyPy trunk'] = Result.objects.filter( - executable=pp_exe, revision=pp_lastrev, environment=env) - - # Save data - benchmarks = [] - for res in cp_results: - if res == 0: - continue - benchmarks.append(res.benchmark.name) - data['results'][res.benchmark.name] = {data['baseline']: res.value} - for rev_name in pp_results: - val = 0 - for pp_res in pp_results[rev_name]: - if pp_res.benchmark.name == res.benchmark.name: - val = pp_res.value - data['results'][res.benchmark.name][rev_name] = val - benchmarks.sort() - data['benchmarks'] = benchmarks - return HttpResponse(json.dumps( data )) diff --git a/sample_project/settings.py b/sample_project/settings.py index 71a58745..d0c98f79 100644 --- a/sample_project/settings.py +++ b/sample_project/settings.py @@ -2,6 +2,9 @@ # Django settings for a Codespeed project. import os +from codespeed.settings import * +WEBSITE_NAME = "PyPy's Speed Center" # This name will be used in the reports RSS feed + DEBUG = True BASEDIR = os.path.abspath(os.path.dirname(__file__)) @@ -34,8 +37,6 @@ MEDIA_URL = '/media/' -ADMIN_MEDIA_PREFIX = '/static/admin/' - SECRET_KEY = 'as%n_m#)^vee2pe91^^@c))sl7^c6t-9r8n)_69%)2yt+(la2&' @@ -83,6 +84,11 @@ os.path.join(BASEDIR, 'static'), ) +SHOW_REPORTS = False +SHOW_HISTORICAL = True +DEF_BASELINE = {'executable': 'cpython', 'revision': '2.6.2'} +DEF_EXECUTABLE = 'pypy-c-jit' +DEF_ENVIRONMENT = 'tannit' -# Codespeed settings that can be overwritten here. -from codespeed.settings import * + +from .local_settings import * diff --git a/sample_project/templates/about.html b/sample_project/templates/about.html index 1c4d6a9c..f05d10b1 100644 --- a/sample_project/templates/about.html +++ b/sample_project/templates/about.html @@ -5,10 +5,13 @@

About this site

-

We have nightly benchmark runs of pypy-c-jit and pypy-c, together with cpython 2.6.2 data for comparison.

+

We have nightly benchmark runs of pypy, together with cpython 2.6.2 data for comparison.

This site runs on top of Django and Codespeed

About the benchmarks

-

The code can be found here and here.

+

The code can be found here.

+

This is a benchmark suite based on Unladen Swallow, adapted for PyPY and +runs on Python2. For a port of these benchmarks to Python3 see the python speed site

About PyPy

PyPy is a very compliant implementation of the Python language.

Main website: pypy.org

diff --git a/sample_project/templates/codespeed/base_site.html b/sample_project/templates/codespeed/base_site.html index 0ba7ca30..5f5c6a01 100644 --- a/sample_project/templates/codespeed/base_site.html +++ b/sample_project/templates/codespeed/base_site.html @@ -1,5 +1,5 @@ {% extends "codespeed/base.html" %} {% block title %} - My Own Title + PyPy Speed {% endblock %} diff --git a/sample_project/templates/home.html b/sample_project/templates/home.html index 51ed27c4..2a0ddf3c 100644 --- a/sample_project/templates/home.html +++ b/sample_project/templates/home.html @@ -179,6 +179,9 @@

How has {{ default_exe.project }} performance evolved over time?

renderer:$.jqplot.BarRenderer, showMarker: false }, + axesDefaults: { + tickRenderer: $.jqplot.CanvasAxisTickRenderer + }, series:[ { pointLabels:{labels:geolabels} @@ -187,7 +190,8 @@

How has {{ default_exe.project }} performance evolved over time?

axes: { xaxis: { renderer: $.jqplot.CategoryAxisRenderer, - ticks: ticks + ticks: ticks, + tickOptions: {angle: -40} }, yaxis:{ min: 0, @@ -210,34 +214,3 @@

How has {{ default_exe.project }} performance evolved over time?

}); {% endblock %} -{% block navigation %} -{% endblock navigation %} - -{% block body %} -
- - - -
- -
-

How fast is PyPy?

-
-

Plot 1: The above plot represents PyPy trunk (with JIT) benchmark times normalized to CPython. Smaller is better.

-

It depends greatly on the type of task being performed. The geometric average of all benchmarks is or times faster than CPython

-

How has PyPy performance evolved over time?

- -
-

Plot 2: Speedup compared to CPython, using the inverse of the geometric average of normalized times, out of benchmarks (see paper on why the geometric mean is better for normalized results).

-
-
-{% endblock body %} From ba2fd712b6f063c20c77acd5e28a351795845e92 Mon Sep 17 00:00:00 2001 From: mattip Date: Wed, 3 Apr 2019 12:45:28 +0300 Subject: [PATCH 52/60] ENH: handle environment for historical data --- codespeed/views.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/codespeed/views.py b/codespeed/views.py index b498bdb4..bff0a0be 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -94,12 +94,20 @@ def gethistoricaldata(request): # Fetch Baseline data baseline_exe = Executable.objects.get( name=settings.DEF_BASELINE['executable']) - baseline_lastrev = Revision.objects.filter( - branch__project=baseline_exe.project).order_by('-date')[0] + baseline_revs = Revision.objects.filter( + branch__project=baseline_exe.project).order_by('-date') + baseline_lastrev = baseline_revs[0] + for rev in baseline_revs: + baseline_results = Result.objects.filter( + executable=baseline_exe, revision=rev, environment=env) + if baseline_results: + baseline_lastrev = rev + break + if len(baseline_results) == 0: + logger.error('Could not find results for {} rev="{}" env="{}"'.format( + baseline_exe, baseline_lastrev, env)) data['baseline'] = '{} {}'.format( settings.DEF_BASELINE['executable'], baseline_lastrev.tag) - baseline_results = Result.objects.filter( - executable=baseline_exe, revision=baseline_lastrev, environment=env) default_exe = Executable.objects.get(name=settings.DEF_EXECUTABLE) default_branch = Branch.objects.get( @@ -108,21 +116,24 @@ def gethistoricaldata(request): # Fetch tagged revisions for default executable default_taggedrevs = Revision.objects.filter( - branch=default_branch - ).exclude(tag="").order_by('date') - data['tagged_revs'] = [rev.tag for rev in default_taggedrevs] + branch=default_branch + ).exclude(tag="").order_by('date') default_results = {} for rev in default_taggedrevs: - default_results[rev.tag] = Result.objects.filter( + res = Result.objects.filter( executable=default_exe, revision=rev, environment=env) - + if not res: + logger.info('no results for %s %s %s' % (str(default_exe), str(rev), str(env))) + continue + default_results[rev.tag] = res + data['tagged_revs'] = [rev.tag for rev in default_taggedrevs if rev.tag in default_results] # Fetch data for latest results revs = Revision.objects.filter( branch=default_branch).order_by('-date')[:5] default_lastrev = None for i in range(4): default_lastrev = revs[i] - if default_lastrev.results.filter(executable=default_exe): + if default_lastrev.results.filter(executable=default_exe, environment=env): break default_lastrev = None if default_lastrev is None: @@ -892,7 +903,6 @@ def add_result(request): return HttpResponseBadRequest(response) else: create_report_if_enough_data(response[0], response[1], response[2]) - logger.debug("add_result: completed") return HttpResponse("Result data saved successfully", status=202) @@ -917,12 +927,9 @@ def add_json_results(request): else: unique_reports.add(response) - logger.debug("add_json_results: about to create reports") for rep in unique_reports: create_report_if_enough_data(rep[0], rep[1], rep[2]) - logger.debug("add_json_results: completed") - return HttpResponse("All result data saved successfully", status=202) From 039f99e05cc2db99ba20ccf70f214d3d7143473f Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 4 Apr 2019 13:01:20 +0300 Subject: [PATCH 53/60] remove file from old data model --- .../009_auto__chg_field_branch_name.py | 97 ------------------- 1 file changed, 97 deletions(-) delete mode 100644 codespeed/migrations/009_auto__chg_field_branch_name.py diff --git a/codespeed/migrations/009_auto__chg_field_branch_name.py b/codespeed/migrations/009_auto__chg_field_branch_name.py deleted file mode 100644 index f35dcc57..00000000 --- a/codespeed/migrations/009_auto__chg_field_branch_name.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Changing field 'Branch.name' - db.alter_column('codespeed_branch', 'name', self.gf('django.db.models.fields.CharField')(max_length=50)) - - def backwards(self, orm): - # Changing field 'Branch.name' - db.alter_column('codespeed_branch', 'name', self.gf('django.db.models.fields.CharField')(max_length=20)) - - models = { - 'codespeed.benchmark': { - 'Meta': {'object_name': 'Benchmark'}, - 'benchmark_type': ('django.db.models.fields.CharField', [], {'default': "'C'", 'max_length': '1'}), - 'description': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'lessisbetter': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), - 'units': ('django.db.models.fields.CharField', [], {'default': "'seconds'", 'max_length': '20'}), - 'units_title': ('django.db.models.fields.CharField', [], {'default': "'Time'", 'max_length': '30'}) - }, - 'codespeed.branch': { - 'Meta': {'unique_together': "(('name', 'project'),)", 'object_name': 'Branch'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'branches'", 'to': "orm['codespeed.Project']"}) - }, - 'codespeed.environment': { - 'Meta': {'object_name': 'Environment'}, - 'cpu': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'kernel': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'memory': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), - 'os': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}) - }, - 'codespeed.executable': { - 'Meta': {'object_name': 'Executable'}, - 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'executables'", 'to': "orm['codespeed.Project']"}) - }, - 'codespeed.project': { - 'Meta': {'object_name': 'Project'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), - 'repo_pass': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), - 'repo_path': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), - 'repo_type': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1'}), - 'repo_user': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), - 'track': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) - }, - 'codespeed.report': { - 'Meta': {'unique_together': "(('revision', 'executable', 'environment'),)", 'object_name': 'Report'}, - '_tablecache': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'colorcode': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '10'}), - 'environment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Environment']"}), - 'executable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Executable']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'revision': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reports'", 'to': "orm['codespeed.Revision']"}), - 'summary': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) - }, - 'codespeed.result': { - 'Meta': {'unique_together': "(('revision', 'executable', 'benchmark', 'environment'),)", 'object_name': 'Result'}, - 'benchmark': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Benchmark']"}), - 'date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'environment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Environment']"}), - 'executable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Executable']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'revision': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'results'", 'to': "orm['codespeed.Revision']"}), - 'std_dev': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'val_max': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'val_min': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'value': ('django.db.models.fields.FloatField', [], {}) - }, - 'codespeed.revision': { - 'Meta': {'unique_together': "(('commitid', 'branch'),)", 'object_name': 'Revision'}, - 'author': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'branch': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['codespeed.Branch']"}), - 'commitid': ('django.db.models.fields.CharField', [], {'max_length': '42'}), - 'date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['codespeed.Project']"}), - 'tag': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}) - } - } - - complete_apps = ['codespeed'] From f3b5c847b44f4d29c7439088f018b8ccc5a3f369 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 4 Apr 2019 13:01:30 +0300 Subject: [PATCH 54/60] fix merge --- codespeed/views.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/codespeed/views.py b/codespeed/views.py index d2fe258b..7cbdfccd 100644 --- a/codespeed/views.py +++ b/codespeed/views.py @@ -931,3 +931,37 @@ def add_json_results(request): create_report_if_enough_data(rep[0], rep[1], rep[2]) return HttpResponse("All result data saved successfully", status=202) + +def django_has_content_type(): + return (django.VERSION[0] > 1 or + (django.VERSION[0] == 1 and django.VERSION[1] >= 6)) + + +@require_GET +def makeimage(request): + data = request.GET + + try: + validate_results_request(data) + except ValidationError as err: + return HttpResponseBadRequest(str(err)) + + try: + result_data = get_benchmark_results(data) + except ObjectDoesNotExist as err: + return HttpResponseNotFound(str(err)) + + image_data = gen_image_from_results( + result_data, + int(data['width']) if 'width' in data else None, + int(data['height']) if 'height' in data else None) + + if django_has_content_type(): + response = HttpResponse(content=image_data, content_type='image/png') + else: + response = HttpResponse(content=image_data, mimetype='image/png') + + response['Content-Length'] = len(image_data) + response['Content-Disposition'] = 'attachment; filename=image.png' + + return response From 4751450236f2b6911767204937f894a1b4555a90 Mon Sep 17 00:00:00 2001 From: mattip Date: Mon, 8 Apr 2019 19:19:30 +0300 Subject: [PATCH 55/60] move from sample_project to speed_pypy --- sample_project/settings.py | 14 +-- {sample_project => speed_pypy}/README.md | 0 {sample_project => speed_pypy}/__init__.py | 0 speed_pypy/settings.py | 94 +++++++++++++++++++ .../templates/404.html | 0 .../templates/500.html | 0 .../templates/about.html | 0 .../templates/admin/base_site.html | 0 .../templates/codespeed/base_site.html | 0 .../templates/feeds/latest_description.html | 0 .../templates/feeds/latest_title.html | 0 .../templates/home.html | 0 {sample_project => speed_pypy}/urls.py | 0 {example => speed_pypy}/wsgi.py | 0 14 files changed, 98 insertions(+), 10 deletions(-) rename {sample_project => speed_pypy}/README.md (100%) rename {sample_project => speed_pypy}/__init__.py (100%) create mode 100644 speed_pypy/settings.py rename {sample_project => speed_pypy}/templates/404.html (100%) rename {sample_project => speed_pypy}/templates/500.html (100%) rename {sample_project => speed_pypy}/templates/about.html (100%) rename {sample_project => speed_pypy}/templates/admin/base_site.html (100%) rename {sample_project => speed_pypy}/templates/codespeed/base_site.html (100%) rename {sample_project => speed_pypy}/templates/feeds/latest_description.html (100%) rename {sample_project => speed_pypy}/templates/feeds/latest_title.html (100%) rename {sample_project => speed_pypy}/templates/home.html (100%) rename {sample_project => speed_pypy}/urls.py (100%) rename {example => speed_pypy}/wsgi.py (100%) diff --git a/sample_project/settings.py b/sample_project/settings.py index d0c98f79..71a58745 100644 --- a/sample_project/settings.py +++ b/sample_project/settings.py @@ -2,9 +2,6 @@ # Django settings for a Codespeed project. import os -from codespeed.settings import * -WEBSITE_NAME = "PyPy's Speed Center" # This name will be used in the reports RSS feed - DEBUG = True BASEDIR = os.path.abspath(os.path.dirname(__file__)) @@ -37,6 +34,8 @@ MEDIA_URL = '/media/' +ADMIN_MEDIA_PREFIX = '/static/admin/' + SECRET_KEY = 'as%n_m#)^vee2pe91^^@c))sl7^c6t-9r8n)_69%)2yt+(la2&' @@ -84,11 +83,6 @@ os.path.join(BASEDIR, 'static'), ) -SHOW_REPORTS = False -SHOW_HISTORICAL = True -DEF_BASELINE = {'executable': 'cpython', 'revision': '2.6.2'} -DEF_EXECUTABLE = 'pypy-c-jit' -DEF_ENVIRONMENT = 'tannit' - -from .local_settings import * +# Codespeed settings that can be overwritten here. +from codespeed.settings import * diff --git a/sample_project/README.md b/speed_pypy/README.md similarity index 100% rename from sample_project/README.md rename to speed_pypy/README.md diff --git a/sample_project/__init__.py b/speed_pypy/__init__.py similarity index 100% rename from sample_project/__init__.py rename to speed_pypy/__init__.py diff --git a/speed_pypy/settings.py b/speed_pypy/settings.py new file mode 100644 index 00000000..d0c98f79 --- /dev/null +++ b/speed_pypy/settings.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Django settings for a Codespeed project. +import os + +from codespeed.settings import * +WEBSITE_NAME = "PyPy's Speed Center" # This name will be used in the reports RSS feed + +DEBUG = True + +BASEDIR = os.path.abspath(os.path.dirname(__file__)) +TOPDIR = os.path.split(BASEDIR)[1] + +#: The directory which should contain checked out source repositories: +REPOSITORY_BASE_PATH = os.path.join(BASEDIR, "repos") + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASEDIR, 'data.db'), + } +} + +TIME_ZONE = 'America/Chicago' + +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +USE_I18N = False + +MEDIA_ROOT = os.path.join(BASEDIR, "media") + +MEDIA_URL = '/media/' + +SECRET_KEY = 'as%n_m#)^vee2pe91^^@c))sl7^c6t-9r8n)_69%)2yt+(la2&' + + +MIDDLEWARE = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +) + +ROOT_URLCONF = '{0}.urls'.format(TOPDIR) + + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASEDIR, 'templates')], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.admin', + 'django.contrib.staticfiles', + 'codespeed', +) + + +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASEDIR, "sitestatic") +STATICFILES_DIRS = ( + os.path.join(BASEDIR, 'static'), +) + +SHOW_REPORTS = False +SHOW_HISTORICAL = True +DEF_BASELINE = {'executable': 'cpython', 'revision': '2.6.2'} +DEF_EXECUTABLE = 'pypy-c-jit' +DEF_ENVIRONMENT = 'tannit' + + +from .local_settings import * diff --git a/sample_project/templates/404.html b/speed_pypy/templates/404.html similarity index 100% rename from sample_project/templates/404.html rename to speed_pypy/templates/404.html diff --git a/sample_project/templates/500.html b/speed_pypy/templates/500.html similarity index 100% rename from sample_project/templates/500.html rename to speed_pypy/templates/500.html diff --git a/sample_project/templates/about.html b/speed_pypy/templates/about.html similarity index 100% rename from sample_project/templates/about.html rename to speed_pypy/templates/about.html diff --git a/sample_project/templates/admin/base_site.html b/speed_pypy/templates/admin/base_site.html similarity index 100% rename from sample_project/templates/admin/base_site.html rename to speed_pypy/templates/admin/base_site.html diff --git a/sample_project/templates/codespeed/base_site.html b/speed_pypy/templates/codespeed/base_site.html similarity index 100% rename from sample_project/templates/codespeed/base_site.html rename to speed_pypy/templates/codespeed/base_site.html diff --git a/sample_project/templates/feeds/latest_description.html b/speed_pypy/templates/feeds/latest_description.html similarity index 100% rename from sample_project/templates/feeds/latest_description.html rename to speed_pypy/templates/feeds/latest_description.html diff --git a/sample_project/templates/feeds/latest_title.html b/speed_pypy/templates/feeds/latest_title.html similarity index 100% rename from sample_project/templates/feeds/latest_title.html rename to speed_pypy/templates/feeds/latest_title.html diff --git a/sample_project/templates/home.html b/speed_pypy/templates/home.html similarity index 100% rename from sample_project/templates/home.html rename to speed_pypy/templates/home.html diff --git a/sample_project/urls.py b/speed_pypy/urls.py similarity index 100% rename from sample_project/urls.py rename to speed_pypy/urls.py diff --git a/example/wsgi.py b/speed_pypy/wsgi.py similarity index 100% rename from example/wsgi.py rename to speed_pypy/wsgi.py From e065bbd79952b4c7cc4b2fb49a6cc0242ae6e137 Mon Sep 17 00:00:00 2001 From: "Ernest W. Durbin III" Date: Mon, 8 Apr 2019 11:35:18 -0500 Subject: [PATCH 56/60] Update wsgi.py --- speed_pypy/wsgi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speed_pypy/wsgi.py b/speed_pypy/wsgi.py index 20b8f2d1..6d7a2a33 100644 --- a/speed_pypy/wsgi.py +++ b/speed_pypy/wsgi.py @@ -2,7 +2,7 @@ import os import sys -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "speed_pypy.settings") from django.core.wsgi import get_wsgi_application application = get_wsgi_application() From 09aa41cd0c11da1cdd8c8ee0804f7f94e6167e28 Mon Sep 17 00:00:00 2001 From: "Ernest W. Durbin III" Date: Mon, 8 Apr 2019 11:46:27 -0500 Subject: [PATCH 57/60] update manage.py settings --- manage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manage.py b/manage.py index 91328678..7cfa57cd 100755 --- a/manage.py +++ b/manage.py @@ -2,7 +2,7 @@ import os, sys if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sample_project.settings") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "speed_pypy.settings") from django.core.management import execute_from_command_line execute_from_command_line(sys.argv) From a709f47632b7be5241cdbab3bf0d5dc5038db245 Mon Sep 17 00:00:00 2001 From: "Ernest W. Durbin III" Date: Mon, 8 Apr 2019 12:15:45 -0500 Subject: [PATCH 58/60] make this directory so collectstatic doesn't complain --- speed_pypy/static/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 speed_pypy/static/.gitkeep diff --git a/speed_pypy/static/.gitkeep b/speed_pypy/static/.gitkeep new file mode 100644 index 00000000..e69de29b From 2f3ee82aee95d245dd48bf85e472ccc2b9b41d02 Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 19 Apr 2019 11:56:43 +0300 Subject: [PATCH 59/60] BUG: stdout is bytes, convert to str --- codespeed/commits/mercurial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codespeed/commits/mercurial.py b/codespeed/commits/mercurial.py index ffe132eb..828521f3 100644 --- a/codespeed/commits/mercurial.py +++ b/codespeed/commits/mercurial.py @@ -63,7 +63,7 @@ def getlogs(endrev, startrev): if p.returncode != 0: raise CommitLogError(str(stderr)) else: - stdout = stdout.rstrip(b'\n') # Remove last newline + stdout = str(stdout).rstrip(b'\n') # Remove last newline logs = [] for log in stdout.split("=newlog=\n"): elements = [] From 5e1bdae927ab2fc7b50d0b650ba3a2eb3cba0f96 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 18 Apr 2019 11:43:32 +0300 Subject: [PATCH 60/60] BUG: stdout is bytes on python3 --- codespeed/commits/mercurial.py | 2 +- codespeed/tests/test_commits.py | 62 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 codespeed/tests/test_commits.py diff --git a/codespeed/commits/mercurial.py b/codespeed/commits/mercurial.py index de0c63e8..0f4f5938 100644 --- a/codespeed/commits/mercurial.py +++ b/codespeed/commits/mercurial.py @@ -63,7 +63,7 @@ def getlogs(endrev, startrev): if p.returncode != 0: raise CommitLogError(str(stderr)) else: - stdout = stdout.rstrip('\n') # Remove last newline + stdout = stdout.decode('utf-8').rstrip('\n') # Remove last newline logs = [] for log in stdout.split("=newlog=\n"): elements = [] diff --git a/codespeed/tests/test_commits.py b/codespeed/tests/test_commits.py new file mode 100644 index 00000000..3c09d03e --- /dev/null +++ b/codespeed/tests/test_commits.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from datetime import datetime, timedelta +import subprocess +import tempfile +import os + +from django.test import TestCase, override_settings +from django.urls import reverse + +from codespeed.models import (Project, Benchmark, Revision, Branch, Executable, + Environment, Result, Report) + +hgdir = '' + +def setUpModule(): + global hgdir + hgdir = tempfile.TemporaryDirectory() + subprocess.check_call(['hg', 'init'], cwd=hgdir.name) + # Add some commits + readme = os.path.join(hgdir.name, 'README.md') + file1 = os.path.join(hgdir.name, 'file1.py') + with open(readme, 'w') as hg_file: + hg_file.write('readme') + subprocess.check_call(['hg', 'add', readme], cwd=hgdir.name) + subprocess.check_call(['hg', 'commit', '-m', "first commit"], cwd=hgdir.name) + with open(file1, 'w') as hg_file: + hg_file.write('value = 10') + subprocess.check_call(['hg', 'add', file1], cwd=hgdir.name) + subprocess.check_call(['hg', 'commit', '-m', "second commit"], cwd=hgdir.name) + +def tearDownModule(): + hgdir.cleanup() + +class TestMercurial(TestCase): + + def setUp(self): + self.days = 0 + self.hgdir = hgdir.name + self.starttime = datetime.now() + timedelta(days=-100) + + Project(repo_type='M', name='pro', + repo_path=str(self.hgdir)).save() + self.pro = Project.objects.get(name='pro') + + Branch(project=self.pro, name='default').save() + self.b = Branch.objects.get(name='default') + + Environment(name='Walden Pond').save() + Executable(name='walden', project=self.pro).save() + Benchmark(name='TestBench').save() + + self.env = Environment.objects.get(name='Walden Pond') + self.exe = Executable.objects.get(name='walden') + self.bench = Benchmark.objects.get(name='TestBench') + cmd = ['hg', '-R', self.hgdir, 'id', '-r', '1'] + self.cid = subprocess.check_output(cmd).split()[0] + Revision(commitid=self.cid.decode('utf-8'), date=self.starttime, branch=self.b, + project=self.pro).save() + + def test_hg(self): + response = self.client.get(reverse('displaylogs'), {'revisionid':1}) + assert response.status_code == 200, 'expected 200 got %d' % response.status_code