268 lines
8.9 KiB
Python
268 lines
8.9 KiB
Python
from userreport.models import UserReport, UserReport_hwdetect
|
|
|
|
from django.http import HttpResponse, HttpResponseForbidden
|
|
from django.shortcuts import render_to_response
|
|
from django.template import RequestContext
|
|
from django.core.paginator import Paginator, InvalidPage, EmptyPage
|
|
from django.db.models import Q
|
|
from django.utils import simplejson
|
|
|
|
import re
|
|
import numpy
|
|
|
|
class hashabledict(dict):
|
|
def __hash__(self):
|
|
return hash(tuple(sorted(self.items())))
|
|
|
|
def render_reports(request, reports, template, args):
|
|
paginator = Paginator(reports, args.get('pagesize', 100))
|
|
try:
|
|
page = int(request.GET.get('page', '1'))
|
|
except ValueError:
|
|
page = 1
|
|
try:
|
|
report_page = paginator.page(page)
|
|
except (EmptyPage, InvalidPage):
|
|
report_page = paginator.page(paginator.num_pages)
|
|
|
|
args['report_page'] = report_page
|
|
return render_to_response(template, args)
|
|
|
|
|
|
def report_user(request, user):
|
|
reports = UserReport.objects.order_by('-upload_date')
|
|
reports = reports.filter(user_id_hash = user)
|
|
|
|
return render_reports(request, reports, 'reports/user.html', {'user': user})
|
|
|
|
def report_messages(request):
|
|
reports = UserReport.objects.order_by('-upload_date')
|
|
reports = reports.filter(data_type = 'message', data_version__gte = 1)
|
|
|
|
return render_reports(request, reports, 'reports/message.html', {})
|
|
|
|
def report_profile(request):
|
|
reports = UserReport.objects.order_by('-upload_date')
|
|
reports = reports.filter(data_type = 'profile', data_version__gte = 2)
|
|
|
|
return render_reports(request, reports, 'reports/profile.html', {'pagesize': 20})
|
|
|
|
def report_hwdetect(request):
|
|
reports = UserReport.objects.order_by('-upload_date')
|
|
reports = reports.filter(data_type = 'hwdetect', data_version__gte = 1)
|
|
|
|
return render_reports(request, reports, 'reports/hwdetect.html', {})
|
|
|
|
def report_gfx(request):
|
|
reports = UserReport.objects.order_by('-upload_date')
|
|
reports = reports.filter(data_type = 'hwdetect', data_version__gte = 1)
|
|
|
|
return render_reports(request, reports, 'reports/gfx.html', {'pagesize': 1000})
|
|
|
|
def report_performance(request):
|
|
reports = UserReport.objects.order_by('upload_date')
|
|
reports = reports.filter(
|
|
Q(data_type = 'hwdetect', data_version__gte = 5) |
|
|
Q(data_type = 'profile', data_version__gte = 2)
|
|
)
|
|
#reports = reports[:500]
|
|
|
|
def summarise_hwdetect(report):
|
|
json = report.data_json_nocache()
|
|
return {
|
|
'cpu_identifier': json['cpu_identifier'],
|
|
'device': report.gl_device_identifier(),
|
|
'build_debug': json['build_debug'],
|
|
'build_revision': json['build_revision'],
|
|
'build_datetime': json['build_datetime'],
|
|
'gfx_res': (json['video_xres'], json['video_yres']),
|
|
}
|
|
|
|
def summarise_profile(report):
|
|
json = report.data_json_nocache()
|
|
if 'map' in json:
|
|
mapname = json['map']
|
|
else:
|
|
mapname = 'unknown' # e.g. random maps
|
|
msecs = None
|
|
shadows = False
|
|
for name,table in json['profiler'].items():
|
|
m = re.match(r'Profiling Information for: root \(Time in node: (\d+\.\d+) msec/frame\)', name)
|
|
if m:
|
|
try:
|
|
msecs = float(table['data']['render'][2])
|
|
except KeyError:
|
|
pass
|
|
|
|
try:
|
|
if float(table['data']['render'][0]['render submissions'][0]['render shadow map'][2]):
|
|
shadows = True
|
|
except (KeyError, TypeError):
|
|
pass
|
|
|
|
if msecs is None:
|
|
return None
|
|
|
|
options = []
|
|
if shadows: options.append('S')
|
|
|
|
return {
|
|
'msecs': msecs,
|
|
'map': mapname,
|
|
'time': json['time'],
|
|
'options': '[%s]' % '+'.join(options),
|
|
# 'json': json
|
|
}
|
|
|
|
profiles = []
|
|
last_hwdetect = {}
|
|
for report in reports:
|
|
if report.data_type == 'hwdetect':
|
|
last_hwdetect[report.user_id_hash] = summarise_hwdetect(report.downcast())
|
|
elif report.data_type == 'profile':
|
|
if report.user_id_hash in last_hwdetect:
|
|
hwdetect = last_hwdetect[report.user_id_hash]
|
|
if hwdetect['build_debug']:
|
|
continue
|
|
prof = summarise_profile(report)
|
|
if prof is not None:
|
|
profiles.append([report.user_id_hash, hwdetect, prof])
|
|
|
|
datapoints = {}
|
|
for user,hwdetect,profile in profiles:
|
|
if profile['map'] != 'Death Canyon':
|
|
continue
|
|
if profile['time'] != 5:
|
|
continue
|
|
if profile['msecs'] is None or float(profile['msecs']) == 0:
|
|
continue
|
|
fps = 1000.0 / profile['msecs']
|
|
title = '%s %s' % (hwdetect['device'], profile['options'])
|
|
datapoints.setdefault(title, []).append(fps)
|
|
|
|
# return render_to_response('reports/performance.html', {'data': datapoints, 'reports': profiles})
|
|
|
|
sorted_datapoints = sorted(datapoints.items(), key = lambda (k,v):
|
|
-numpy.median(v)
|
|
)
|
|
|
|
print "# %d datapoints" % sum(len(v) for k,v in sorted_datapoints)
|
|
|
|
data_boxplot = [ v for k,v in sorted_datapoints ]
|
|
data_scatter = ([], [])
|
|
for i in range(len(data_boxplot)):
|
|
for x in data_boxplot[i]:
|
|
data_scatter[0].append(i+1)
|
|
data_scatter[1].append(x)
|
|
|
|
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
|
|
from matplotlib.figure import Figure
|
|
|
|
fig = Figure(figsize=(16, 0.25*len(datapoints.items())))
|
|
|
|
ax = fig.add_subplot(111)
|
|
fig.subplots_adjust(left = 0.22, right = 0.98, top = 0.98, bottom = 0.05)
|
|
|
|
ax.grid(True)
|
|
|
|
ax.boxplot(data_boxplot, vert = 0, sym = '')
|
|
ax.scatter(data_scatter[1], data_scatter[0], marker='x')
|
|
|
|
ax.set_xlim(0.1, 1000)
|
|
ax.set_xscale('log')
|
|
ax.set_xlabel('Framerate (fps)')
|
|
|
|
ax.set_yticklabels([k for k,v in sorted_datapoints], fontsize=8)
|
|
ax.set_ylabel('Device [options: Shadows + Water reflections]')
|
|
|
|
canvas = FigureCanvas(fig)
|
|
response = HttpResponse(content_type = 'image/png')
|
|
canvas.print_png(response, dpi=80)
|
|
return response
|
|
|
|
def report_ram(request):
|
|
reports = UserReport.objects
|
|
reports = reports.filter(data_type = 'hwdetect', data_version__gte = 1)
|
|
|
|
counts = {}
|
|
for report in reports:
|
|
#if not report.data_json()['os_linux']: continue
|
|
ram = report.data_json()['ram_total']
|
|
counts.setdefault(ram, set()).add(report.user_id_hash)
|
|
|
|
datapoints = []
|
|
accum = 0
|
|
for size,count in sorted(counts.items()):
|
|
accum += len(count)
|
|
datapoints.append((size, accum))
|
|
|
|
print "\n".join(repr(r) for r in datapoints)
|
|
|
|
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
|
|
from matplotlib.figure import Figure
|
|
|
|
fig = Figure(figsize=(16, 10))
|
|
|
|
ax = fig.add_subplot(111)
|
|
fig.subplots_adjust(left = 0.05, right = 0.98, top = 0.98, bottom = 0.05)
|
|
|
|
ax.grid(True)
|
|
|
|
ax.plot([ d[0] for d in datapoints ], [ 100*(1-float(d[1])/accum) for d in datapoints ])
|
|
|
|
ax.set_xticks([0, 256, 512] + [1024*n for n in range(1, 9)])
|
|
ax.set_xlim(0, 8192)
|
|
ax.set_xlabel('RAM (megabytes)')
|
|
|
|
ax.set_yticks(range(0, 101, 5))
|
|
ax.set_ylim(0, 100)
|
|
ax.set_ylabel('Cumulative percentage of users')
|
|
|
|
canvas = FigureCanvas(fig)
|
|
response = HttpResponse(content_type = 'image/png')
|
|
canvas.print_png(response, dpi=80)
|
|
return response
|
|
|
|
def report_os(request):
|
|
reports = UserReport_hwdetect.objects
|
|
reports = reports.filter(data_type = 'hwdetect', data_version__gte = 1)
|
|
|
|
counts = {}
|
|
for report in reports:
|
|
json = report.data_json()
|
|
if 'linux_release' in json:
|
|
counts.setdefault(repr(json['linux_release']), set()).add(report.user_id_hash)
|
|
os = report.os()
|
|
counts.setdefault(os, set()).add(report.user_id_hash)
|
|
|
|
out = ''
|
|
for c in sorted(counts.items(), key = lambda c: len(c[1])):
|
|
out += '%d %s\n' % (len(c[1]), c[0])
|
|
|
|
return HttpResponse(out, content_type = 'text/plain')
|
|
|
|
def report_hwdetect_test_data(request):
|
|
reports = UserReport_hwdetect.objects
|
|
reports = reports.filter(data_type = 'hwdetect', data_version__gte = 1)
|
|
|
|
data = set()
|
|
for report in reports:
|
|
json = report.data_json_nocache()
|
|
relevant = {
|
|
'os_unix': json['os_unix'],
|
|
'os_linux': json['os_linux'],
|
|
'os_macosx': json['os_macosx'],
|
|
'os_win': json['os_win'],
|
|
'gfx_card': json['gfx_card'],
|
|
'gfx_drv_ver': json['gfx_drv_ver'],
|
|
'gfx_mem': json['gfx_mem'],
|
|
'GL_VENDOR': json['GL_VENDOR'],
|
|
'GL_RENDERER': json['GL_RENDERER'],
|
|
'GL_VERSION': json['GL_VERSION'],
|
|
'GL_EXTENSIONS': json['GL_EXTENSIONS'],
|
|
}
|
|
data.add(hashabledict(relevant))
|
|
|
|
json = simplejson.dumps(list(data), indent=1, sort_keys=True)
|
|
return HttpResponse('var hwdetectTestData = %s' % json, content_type = 'text/plain')
|