show os-specific perf data (bug 641557)
This commit is contained in:
Родитель
3f60194b43
Коммит
c37e14202c
|
@ -24,13 +24,19 @@ class PerformanceAppVersions(amo.models.ModelBase):
|
|||
class PerformanceOSVersion(amo.models.ModelBase):
|
||||
os = models.CharField(max_length=255)
|
||||
version = models.CharField(max_length=255)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
class Meta:
|
||||
db_table = 'perf_osversions'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name or '%s %s' % (self.os, self.version)
|
||||
|
||||
|
||||
class Performance(amo.models.ModelBase):
|
||||
"""Add-on performance numbers. A bit denormalized."""
|
||||
# Cache storage for all platform perf numbers.
|
||||
ALL_PLATFORMS = 'perf:platforms'
|
||||
|
||||
TEST_CHOICES = [('ts', 'Startup Time')]
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import json
|
||||
import logging
|
||||
|
||||
import redisutils
|
||||
from celeryutils import task
|
||||
|
||||
from addons.models import Addon
|
||||
from .models import Performance
|
||||
|
||||
log = logging.getLogger('z.perf.task')
|
||||
|
||||
|
@ -11,13 +14,23 @@ log = logging.getLogger('z.perf.task')
|
|||
def update_perf(baseline, perf, **kw):
|
||||
log.info('[%s@%s] Updating perf' %
|
||||
(len(perf), update_perf.rate_limit))
|
||||
all_deltas = {}
|
||||
for addon, rows in perf:
|
||||
if addon is None:
|
||||
continue
|
||||
deltas = [(avg - baseline[os]) / float(baseline[os])
|
||||
for _, os, avg in rows]
|
||||
if any(d < 0 for d in deltas):
|
||||
deltas = dict((os, (avg - baseline[os]) / float(baseline[os]) * 100)
|
||||
for _, os, avg in rows)
|
||||
if any(d < 0 for d in deltas.values()):
|
||||
slowness = None
|
||||
all_deltas[addon] = None
|
||||
else:
|
||||
slowness = sum(deltas) / len(deltas) * 100
|
||||
slowness = int(sum(deltas.values()) / len(deltas))
|
||||
d = dict((k, int(v)) for k, v in deltas.items())
|
||||
# Include the average slowness as key 0.
|
||||
d[0] = slowness
|
||||
all_deltas[addon] = json.dumps(d, separators=(',', ':'))
|
||||
Addon.objects.filter(pk=addon).update(ts_slowness=slowness)
|
||||
|
||||
# Add all the calculated values to redis so we can show per-platform perf.
|
||||
redis = redisutils.connections['master']
|
||||
redis.hmset(Performance.ALL_PLATFORMS, all_deltas)
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
{% block bodyclass %}inverse{% endblock %}
|
||||
|
||||
{% block extrahead %}
|
||||
<link rel="stylesheet" href="{{ MEDIA_URL }}css/zamboni/perf.css">
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
|
@ -30,8 +34,18 @@
|
|||
The following add-ons have the most impact on how long it takes {{ app }}
|
||||
to start up.
|
||||
{% endtrans %}</p>
|
||||
{% if show_os %}
|
||||
<p id="show">
|
||||
{# L10n: Show All, Windows, Mac, Linux. The other names are inserted after the colon. #}
|
||||
{{ _('Show:') }}
|
||||
<span>
|
||||
{# No spaces or all is ruined! #}
|
||||
<a href="#"><b> {{ _('All') }}</b></a>{% for p in platforms|sort %}, <a href="#">{{ p }}</a>{% endfor %}
|
||||
</span>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<div id="perf-results">
|
||||
<div id="perf-results" data-platforms="{{ platforms|json }}">
|
||||
<div id="perf-results-inner">
|
||||
<table>
|
||||
<thead>
|
||||
|
@ -46,8 +60,10 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{% for addon in addons %}
|
||||
<tr id="addon-{{ loop.index }}" data-rank="{{ loop.index }}"
|
||||
{% if loop.index > 10 %}class="perf-hidden perf-small"{% endif %}>
|
||||
<tr class="addon-row"
|
||||
{% if os_perf[addon.id] %}
|
||||
data-platforms="{{ os_perf[addon.id] }}"
|
||||
{% endif %}>
|
||||
<td class="rank">#<b>{{ loop.index }}</b></td>
|
||||
<td class="addon">
|
||||
<div>
|
||||
|
@ -78,7 +94,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
{% if addons|length > 10 %}
|
||||
<p id="perf-more"><a href="#addon-11">{{ _('Show more add-ons') }}</a></p>
|
||||
<p id="perf-more"><a href="#">{{ _('Show more add-ons') }}</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,10 +4,11 @@ from django.shortcuts import get_list_or_404
|
|||
from django.views.decorators.cache import cache_control
|
||||
|
||||
import jingo
|
||||
import redisutils
|
||||
|
||||
from addons.models import Addon
|
||||
|
||||
from .models import Performance
|
||||
from .models import Performance, PerformanceOSVersion
|
||||
|
||||
|
||||
@cache_control(max_age=60 * 60 * 24) # Cache for a day.
|
||||
|
@ -15,5 +16,11 @@ def index(request):
|
|||
addons = (Addon.objects.listed(request.APP)
|
||||
.filter(ts_slowness__isnull=False).order_by('-ts_slowness'))
|
||||
addons = get_list_or_404(addons[:50])
|
||||
ids = [a.id for a in addons]
|
||||
redis = redisutils.connections['master']
|
||||
os_perf = dict(zip(ids, redis.hmget(Performance.ALL_PLATFORMS, ids)))
|
||||
platforms = dict((unicode(p), p.id)
|
||||
for p in PerformanceOSVersion.uncached.all())
|
||||
return jingo.render(request, 'perf/index.html',
|
||||
dict(addons=addons))
|
||||
dict(addons=addons, os_perf=os_perf, platforms=platforms,
|
||||
show_os=any(os_perf.values())))
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/** Performance page. **/
|
||||
#perf-results {
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #e0effd;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#perf-results table {
|
||||
border-bottom: 1px dotted #add0dc;
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Hide children over 10 until show-more is clicked. */
|
||||
#perf-results:not(.show-more) .addon-row:nth-child(n+10) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#perf-results th {
|
||||
font-size: 11px;
|
||||
vertical-align: top;
|
||||
padding: 0 20px 8px 0;
|
||||
}
|
||||
|
||||
#perf-results th.rank {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results th.rank {
|
||||
padding-right: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#perf-results th.impact {
|
||||
padding-right: 0;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#perf-results th.impact .percentage {
|
||||
color: #999;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#perf-results td {
|
||||
border-top: 1px dotted #add0dc;
|
||||
padding: 8px 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#perf-results td.rank {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#perf-results td.rank b,
|
||||
#perf-results td.impact b,
|
||||
#perf-results td.addon .addon-title > a {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
#perf-results td.rank b {
|
||||
font-weight: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#perf-results td.addon div {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#perf-results td.addon img.icon,
|
||||
#perf-results td.addon .addon-title,
|
||||
#perf-results td.addon .author {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#perf-results td.addon img.icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results td.addon img.icon {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#perf-results th.addon,
|
||||
#perf-results td.addon .addon-title {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results th.addon,
|
||||
.html-rtl #perf-results td.addon .addon-title {
|
||||
padding-left: 0;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
#perf-results td.addon .addon-title > a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#perf-results td.impact {
|
||||
color: #777;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
#perf-results .addon-row:nth-child(n+10) td.rank b,
|
||||
#perf-results .addon-row:nth-child(n+10) td.impact b,
|
||||
#perf-results .addon-row:nth-child(n+10) td.addon .addon-title > a {
|
||||
font-size: 1.0em;
|
||||
}
|
||||
|
||||
#perf-results .addon-row:nth-child(n+10) td.addon img.icon,
|
||||
#perf-results .addon-row:nth-child(n+10) td.addon .author,
|
||||
#perf-results .addon-row:nth-child(n+10) td.impact .slower span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#perf-results .addon-row:nth-child(n+10) td.addon img.icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
#perf-results .impact .slower,
|
||||
#perf-results .impact .percentage {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
#perf-results .impact .slower {
|
||||
text-align: right;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results .impact .slower {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#perf-results .impact .percentage {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
#perf-results .impact .slower {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results .impact .slower {
|
||||
padding: 0 0 0 10px;
|
||||
}
|
||||
|
||||
#perf-results td.impact .slower {
|
||||
border-right: 1px solid #f77;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results td.impact .slower {
|
||||
border-right-width: 0;
|
||||
border-left: 1px solid #f77;
|
||||
}
|
||||
|
||||
#perf-results td.impact .percentage {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#perf-results td.impact b {
|
||||
color: #444;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#perf-results .bar {
|
||||
background-color: #f77;
|
||||
height: 15px;
|
||||
-moz-transition: .5s width;
|
||||
}
|
||||
|
||||
#perf-results .addon-row:nth-child(n+10) .bar {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
#perf-results p#perf-more {
|
||||
font-size: 0.9em;
|
||||
margin: 1em 0 0 52px;
|
||||
}
|
||||
|
||||
#perf-results p#perf-more a {
|
||||
background: url(../../img/icons/arrows.gif) 100% -73px no-repeat;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results p#perf-more a {
|
||||
background-position: 0 -73px;
|
||||
padding: 0 0 0 15px;
|
||||
}
|
||||
|
||||
#perf-results p#perf-more a:hover,
|
||||
#perf-results p#perf-more a:focus,
|
||||
#perf-results p#perf-more a:active {
|
||||
background-position: 100% -113px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results p#perf-more a:hover,
|
||||
.html-rtl #perf-results p#perf-more a:focus,
|
||||
.html-rtl #perf-results p#perf-more a:active {
|
||||
background-position: 0 -113px;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2114,204 +2114,6 @@ form .error .note.error {
|
|||
}
|
||||
|
||||
|
||||
/** Performance page. **/
|
||||
#perf-results {
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #e0effd;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#perf-results table {
|
||||
border-bottom: 1px dotted #add0dc;
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#perf-results .perf-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#perf-results th {
|
||||
font-size: 11px;
|
||||
vertical-align: top;
|
||||
padding: 0 20px 8px 0;
|
||||
}
|
||||
|
||||
#perf-results th.rank {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results th.rank {
|
||||
padding-right: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#perf-results th.impact {
|
||||
padding-right: 0;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#perf-results th.impact .percentage {
|
||||
color: #999;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#perf-results td {
|
||||
border-top: 1px dotted #add0dc;
|
||||
padding: 8px 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#perf-results td.rank {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#perf-results td.rank b,
|
||||
#perf-results td.impact b,
|
||||
#perf-results td.addon .addon-title > a {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
#perf-results .perf-small td.rank b,
|
||||
#perf-results .perf-small td.impact b,
|
||||
#perf-results .perf-small td.addon .addon-title > a {
|
||||
font-size: 1.0em;
|
||||
}
|
||||
|
||||
#perf-results .perf-small td.addon img.icon,
|
||||
#perf-results .perf-small td.addon .author,
|
||||
#perf-results .perf-small td.impact .slower span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#perf-results td.rank b {
|
||||
font-weight: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#perf-results td.addon div {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#perf-results td.addon img.icon,
|
||||
#perf-results td.addon .addon-title,
|
||||
#perf-results td.addon .author {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#perf-results td.addon img.icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results td.addon img.icon {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#perf-results th.addon,
|
||||
#perf-results td.addon .addon-title {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results th.addon,
|
||||
.html-rtl #perf-results td.addon .addon-title {
|
||||
padding-left: 0;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
#perf-results td.addon .addon-title > a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#perf-results td.impact {
|
||||
color: #777;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
#perf-results .impact .slower,
|
||||
#perf-results .impact .percentage {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
#perf-results .impact .slower {
|
||||
text-align: right;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results .impact .slower {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#perf-results .impact .percentage {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
#perf-results .impact .slower {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results .impact .slower {
|
||||
padding: 0 0 0 10px;
|
||||
}
|
||||
|
||||
#perf-results td.impact .slower {
|
||||
border-right: 1px solid #f77;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results td.impact .slower {
|
||||
border-right-width: 0;
|
||||
border-left: 1px solid #f77;
|
||||
}
|
||||
|
||||
#perf-results td.impact .percentage {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#perf-results td.impact b {
|
||||
color: #444;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#perf-results .bar {
|
||||
background-color: #f77;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
#perf-results .perf-small .bar {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
#perf-results p#perf-more {
|
||||
font-size: 0.9em;
|
||||
margin: 1em 0 0 52px;
|
||||
}
|
||||
|
||||
#perf-results p#perf-more a {
|
||||
background: url(../../img/icons/arrows.gif) 100% -73px no-repeat;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results p#perf-more a {
|
||||
background-position: 0 -73px;
|
||||
padding: 0 0 0 15px;
|
||||
}
|
||||
|
||||
#perf-results p#perf-more a:hover,
|
||||
#perf-results p#perf-more a:focus,
|
||||
#perf-results p#perf-more a:active {
|
||||
background-position: 100% -113px;
|
||||
}
|
||||
|
||||
.html-rtl #perf-results p#perf-more a:hover,
|
||||
.html-rtl #perf-results p#perf-more a:focus,
|
||||
.html-rtl #perf-results p#perf-more a:active {
|
||||
background-position: 0 -113px;
|
||||
}
|
||||
|
||||
|
||||
/** =Personas Details page *********/
|
||||
.persona-img {
|
||||
height: 100px;
|
||||
|
|
|
@ -1,15 +1,60 @@
|
|||
$(document).ready(function() {
|
||||
$("#perf-more a").click(function(e) {
|
||||
var loc = $(this).attr("href");
|
||||
$("#perf-results tr.perf-hidden:lt(40)").removeClass("perf-hidden");
|
||||
var $next = $("#perf-results tr.perf-hidden:eq(0)");
|
||||
if ($next.length) {
|
||||
$(this).attr("href", "#addon-" + $next.attr("data-rank"));
|
||||
} else {
|
||||
$("#perf-more").remove();
|
||||
$("#perf-results table").css("border-bottom-width", 0);
|
||||
$("#perf-results tr:last-child").find("td, .impact div")
|
||||
.css("padding-bottom", 0);
|
||||
}
|
||||
"use strict";
|
||||
|
||||
var $perfResults = $('#perf-results'),
|
||||
platforms = JSON.parse($perfResults.attr('data-platforms')),
|
||||
results = [];
|
||||
|
||||
// We only show 10 at the beginning and toggle the rest here.
|
||||
$('#perf-more a').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#perf-more').remove();
|
||||
$perfResults.addClass('show-more');
|
||||
});
|
||||
|
||||
// Add All to the platforms map.
|
||||
platforms[gettext('All')] = 0;
|
||||
|
||||
// Gather all the os-specific data.
|
||||
$perfResults.find('tbody tr').each(function(i, e) {
|
||||
var p = $(this).attr('data-platforms')
|
||||
results.push(p ? JSON.parse(p) : {});
|
||||
});
|
||||
|
||||
if ($('#show').length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Switch to js strings so we have consistent gettext.
|
||||
switchNumbers(gettext('All'));
|
||||
|
||||
$('#show').delegate('a', 'click', function(e) {
|
||||
e.preventDefault();
|
||||
switchNumbers($.trim($(this).text()));
|
||||
});
|
||||
|
||||
// Change numbers and bar graphs to the selected platform data.
|
||||
function switchNumbers(selected) {
|
||||
var platform = platforms[selected],
|
||||
numbers = $.map(results, function(e) { return e[platform] || 0; }),
|
||||
worst = Math.max.apply(null, numbers);
|
||||
$perfResults.find('tbody tr').each(function(i, e) {
|
||||
var $this = $(this),
|
||||
num = results[i][platform] || 0;
|
||||
$this.find('.slower b').text(num === 0 ? gettext('N/A') : num + '%');
|
||||
$this.find('.bar').css('width', num / worst * 100 + '%');
|
||||
});
|
||||
showPlatforms(selected);
|
||||
}
|
||||
|
||||
// Redisplay the list of names to select the current platform.
|
||||
function showPlatforms(selected) {
|
||||
var _names = _.keys(platforms);
|
||||
_names.sort()
|
||||
var names = $.map(_names, function(e) {
|
||||
var name = e == selected ? '<b>' + e + '</b>' : e;
|
||||
return format('<a href="#">{0}</a>', name);
|
||||
});
|
||||
$('#show span').html(names.join(', '));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE perf_osversions ADD COLUMN name varchar(255);
|
||||
|
||||
UPDATE perf_osversions SET name='Mac OS X 10.5.8' WHERE id=1;
|
||||
UPDATE perf_osversions SET name='Fedora 12' WHERE id=2;
|
||||
UPDATE perf_osversions SET name='Windows XP' WHERE id=3;
|
||||
UPDATE perf_osversions SET name='Windows 7' WHERE id=4
|
Загрузка…
Ссылка в новой задаче