performance wall of shame (bug 600430)

This commit is contained in:
Jeff Balogh 2010-11-18 15:19:07 -08:00
Родитель f399f45b69
Коммит 654e071d36
11 изменённых файлов: 229 добавлений и 34 удалений

Просмотреть файл

@ -951,40 +951,6 @@ class AppSupport(amo.models.ModelBase):
db_table = 'appsupport'
class PerformanceAppversions(amo.models.ModelBase):
"""
Add-on performance appversions. This table is pretty much the same as
`appversions` but is separate because we need to push the perf stuff now
and I'm scared to mess with `appversions` because remora uses it in some
sensitive places. If we survive past 2012 and people suddenly have too
much time on their hands, consider merging the two.
"""
APP_CHOICES = [('fx', 'Firefox')]
app = models.CharField(max_length=255, choices=APP_CHOICES)
version = models.CharField(max_length=255, db_index=True)
class Meta:
db_table = 'perf_appversions'
class Performance(amo.models.ModelBase):
"""Add-on performance numbers. A bit denormalized."""
TEST_CHOICES = [('ts', 'Startup Time')]
addon = models.ForeignKey(Addon)
average = models.FloatField(default=0, db_index=True)
appversion = models.ForeignKey('PerformanceAppVersions')
# TODO(clouserw): Replace this field below with what you really want.
# os = models.CharField(max_length=255)
test = models.CharField(max_length=50, choices=TEST_CHOICES)
class Meta:
db_table = 'perf_results'
class Charity(amo.models.ModelBase):
name = models.CharField(max_length=255)
url = models.URLField()

0
apps/perf/__init__.py Normal file
Просмотреть файл

Просмотреть файл

@ -0,0 +1,48 @@
[
{
"pk": 1,
"model": "perf.performanceosversion",
"fields": {
"version": "10.6",
"os": "mac",
"modified": "2010-11-18 14:52:54",
"created": "2010-11-18 14:52:54"
}
},
{
"pk": 1,
"model": "perf.performanceappversions",
"fields": {
"app": "fx",
"version": "3.6",
"modified": "2010-11-18 14:43:00",
"created": "2010-11-18 14:43:00"
}
},
{
"pk": 3,
"model": "perf.performance",
"fields": {
"created": "2010-11-18 14:53:11",
"average": 5.2117100000000001,
"modified": "2010-11-18 14:53:11",
"appversion": 1,
"test": "ts",
"osversion": 1,
"addon": 3615
}
},
{
"pk": 2,
"model": "perf.performance",
"fields": {
"created": "2010-11-18 14:53:11",
"average": 14.849299999999999,
"modified": "2010-11-18 14:53:11",
"appversion": 1,
"test": "ts",
"osversion": 1,
"addon": 5299
}
}
]

44
apps/perf/models.py Normal file
Просмотреть файл

@ -0,0 +1,44 @@
from django.db import models
import amo.models
class PerformanceAppVersions(amo.models.ModelBase):
"""
Add-on performance appversions. This table is pretty much the same as
`appversions` but is separate because we need to push the perf stuff now
and I'm scared to mess with `appversions` because remora uses it in some
sensitive places. If we survive past 2012 and people suddenly have too
much time on their hands, consider merging the two.
"""
APP_CHOICES = [('fx', 'Firefox')]
app = models.CharField(max_length=255, choices=APP_CHOICES)
version = models.CharField(max_length=255, db_index=True)
class Meta:
db_table = 'perf_appversions'
class PerformanceOSVersion(amo.models.ModelBase):
os = models.CharField(max_length=255)
version = models.CharField(max_length=255)
class Meta:
db_table = 'perf_osversions'
class Performance(amo.models.ModelBase):
"""Add-on performance numbers. A bit denormalized."""
TEST_CHOICES = [('ts', 'Startup Time')]
addon = models.ForeignKey('addons.Addon')
average = models.FloatField(default=0, db_index=True)
appversion = models.ForeignKey(PerformanceAppVersions)
osversion = models.ForeignKey(PerformanceOSVersion)
test = models.CharField(max_length=50, choices=TEST_CHOICES)
class Meta:
db_table = 'perf_results'

Просмотреть файл

@ -0,0 +1,75 @@
{% extends "base.html" %}
{% set title = _('Slow Performing Add-ons') %}
{% set worst = (perfs[addons[0].id].average - baseline) / baseline %}
{% set app = APP.pretty %}
{% block title %}{{ page_title(title) }}{% endblock %}
{% block bodyclass %}inverse{% endblock %}
{% block content %}
<header>
{{ breadcrumbs([(None, title)]) }}
<h2>{{ title }}</h2>
</header>
<div class="primary" role="main">
<p>{% trans %}
Add-ons provide many useful features and functions for your browser.
However, add-ons can also slow down your browsing experience. Some add-ons
can even slow down {{ app }} until it is difficult to use for regular web
browsing. It can also be difficult to determine what add-ons are the source
of the problem. We provide this list in the hopes that it will help you
identify add-ons that are affecting the performance of your browser.
{% endtrans %}</p>
<h3>{{ _('Add-ons with Slowest Start-up') }}</h3>
<p>{% trans %}
The following add-ons have the most impact on how long it takes {{ app }} to
start up.
{% endtrans %}</p>
<table id="perf-results">
<thead>
<tr>
<th>{{ _('Rank') }}</th>
<th>{{ _('Add-on') }}</th>
<th>{{ _('Impact') }}</th>
<th class="shhhh">{{ _('Longer lines are slower') }}</th>
</tr>
</thead>
<tbody>
{% for addon in addons %}
<tr>
{% set perf = perfs[addon.id] %}
<td># {{ loop.index }}</td>
<td>
<img src="{{ addon.icon_url }}" class="icon">
<a href="{{ addon.get_url_path() }}">{{ addon.name }}</a>
{{ _('by') }} {{ users_list(addon.listed_authors) }}
</td>
{% with num = (perf.average - baseline) / baseline %}
<td>{{ _('{0}% slower')|f((100 * num)|int) }}</td>
<td><div class="bar" style="background-color: red; width: {{ num / worst * 100 }}%">&nbsp</div></td>
{% endwith %}
</tr>
{% endfor %}
</tbody>
</table>
<a href="#">{{ _('Show more add-ons') }}</a>
</div>
<div class="secondary">
<div class="highlight">
<h4>{{ _('For Add-on Developers') }}</h4>
<p>{% trans %}
Don't let poor performance affect the experience of your users. Here are a
few tips on how to keep your add-ons responsive and nimble.
{% endtrans %}</p>
<a class="more-info" href="#">
{{ _('Learn more about performance') }}</a>
</div>
</div>
{% endblock %}

29
apps/perf/tests.py Normal file
Просмотреть файл

@ -0,0 +1,29 @@
import test_utils
from nose.tools import eq_
from amo.urlresolvers import reverse
from perf.models import Performance
class TestPerfIndex(test_utils.TestCase):
fixtures = ['base/apps', 'base/addon_3615', 'base/addon_5299_gcal',
'perf/index']
def setUp(self):
# TODO: appversion
self.url = reverse('perf.index')
def test_get(self):
# Are you there page?
r = self.client.get(self.url)
eq_(r.status_code, 200)
addons = r.context['addons']
eq_([a.id for a in addons],
[p.addon_id for p in Performance.objects.order_by('-average')])
for addon in addons:
assert r.context['perfs'][addon.id]
def test_empty_perf_table(self):
Performance.objects.all().delete()
r = self.client.get(self.url)
eq_(r.status_code, 404)

8
apps/perf/urls.py Normal file
Просмотреть файл

@ -0,0 +1,8 @@
from django.conf.urls.defaults import patterns, url, include
from . import views
urlpatterns = patterns('',
url('^$', views.index, name='perf.index'),
)

20
apps/perf/views.py Normal file
Просмотреть файл

@ -0,0 +1,20 @@
from django.shortcuts import get_list_or_404
from django.views.decorators.cache import cache_control
import jingo
from addons.models import Addon
from .models import Performance
@cache_control(max_age=60 * 60 * 24) # Cache for a day.
def index(request):
addons = (Addon.objects.listed(request.APP)
.filter(performance__average__isnull=False)
.order_by('-performance__average')[:50]) # LEFT OUTER :(
addons = get_list_or_404(addons)
qs = Performance.objects.filter(addon__in=[a.id for a in addons])
perfs = dict((p.addon_id, p) for p in qs)
return jingo.render(request, 'perf/index.html',
dict(addons=addons, perfs=perfs, baseline=1.2))

Просмотреть файл

@ -0,0 +1 @@
CREATE INDEX avg_addon_idx ON perf_results (average, addon_id);

Просмотреть файл

@ -259,6 +259,7 @@ INSTALLED_APPS = (
'jingo_minify',
'nick',
'pages',
'perf',
'reviews',
'search',
'sharing',

Просмотреть файл

@ -43,6 +43,9 @@ urlpatterns = patterns('',
# AMO admin (not django admin).
('^admin/', include('zadmin.urls')),
# Performance wall of shame.
('^performance/', include('perf.urls')),
# Nick's special pages.
('^nickspages/', include('nick.urls')),