Latest version of user-report server code
This was SVN commit r9051.
This commit is contained in:
parent
a0a245d0ec
commit
b70a0a5b5a
75
source/tools/webservices/userreport/gl.py
Normal file
75
source/tools/webservices/userreport/gl.py
Normal file
@ -0,0 +1,75 @@
|
||||
glext_versions = {
|
||||
"GL_EXT_gpu_shader4": "3.0",
|
||||
"GL_NV_conditional_render": "3.0",
|
||||
"GL_ARB_color_buffer_float": "3.0",
|
||||
"GL_ARB_depth_buffer_float": "3.0",
|
||||
"GL_ARB_texture_float": "3.0",
|
||||
"GL_EXT_packed_float": "3.0",
|
||||
"GL_EXT_texture_shared_exponent": "3.0",
|
||||
"GL_EXT_framebuffer_object": "3.0",
|
||||
"GL_NV_half_float": "3.0",
|
||||
"GL_ARB_half_float_pixel": "3.0",
|
||||
"GL_EXT_framebuffer_multisample": "3.0",
|
||||
"GL_EXT_framebuffer_blit": "3.0",
|
||||
"GL_EXT_texture_integer": "3.0",
|
||||
"GL_EXT_texture_array": "3.0",
|
||||
"GL_EXT_packed_depth_stencil": "3.0",
|
||||
"GL_EXT_draw_buffers2": "3.0",
|
||||
"GL_EXT_texture_compression_rgtc": "3.0",
|
||||
"GL_EXT_transform_feedback": "3.0",
|
||||
"GL_APPLE_vertex_array_object": "3.0",
|
||||
"GL_EXT_framebuffer_sRGB": "3.0",
|
||||
|
||||
"GL_ARB_pixel_buffer_object": "2.1",
|
||||
"GL_EXT_texture_sRGB": "2.1",
|
||||
|
||||
"GL_ARB_shader_objects": "2.0",
|
||||
"GL_ARB_vertex_shader": "2.0",
|
||||
"GL_ARB_fragment_shader": "2.0",
|
||||
"GL_ARB_shading_language_100": "2.0",
|
||||
"GL_ARB_draw_buffers": "2.0",
|
||||
"GL_ARB_texture_non_power_of_two": "2.0",
|
||||
"GL_ARB_point_sprite": "2.0",
|
||||
"GL_EXT_blend_equation_separate": "2.0",
|
||||
|
||||
"GL_ARB_vertex_buffer_object": "1.5",
|
||||
"GL_ARB_occlusion_query": "1.5",
|
||||
"GL_EXT_shadow_funcs": "1.5",
|
||||
|
||||
"GL_SGIS_generate_mipmap": "1.4",
|
||||
"GL_NV_blend_square": "1.4",
|
||||
"GL_ARB_depth_texture": "1.4",
|
||||
"GL_ARB_shadow": "1.4",
|
||||
"GL_EXT_fog_coord": "1.4",
|
||||
"GL_EXT_multi_draw_arrays": "1.4",
|
||||
"GL_ARB_point_parameters": "1.4",
|
||||
"GL_EXT_secondary_color": "1.4",
|
||||
"GL_EXT_blend_func_separate": "1.4",
|
||||
"GL_EXT_stencil_wrap": "1.4",
|
||||
"GL_ARB_texture_env_crossbar": "1.4",
|
||||
"GL_EXT_texture_lod_bias": "1.4",
|
||||
"GL_ARB_texture_mirrored_repeat": "1.4",
|
||||
"GL_ARB_window_pos": "1.4",
|
||||
|
||||
"GL_ARB_texture_compression": "1.3",
|
||||
"GL_ARB_texture_cube_map": "1.3",
|
||||
"GL_ARB_multisample": "1.3",
|
||||
"GL_ARB_multitexture": "1.3",
|
||||
"GL_ARB_transpose_matrix": "1.3",
|
||||
"GL_ARB_texture_env_add": "1.3",
|
||||
"GL_ARB_texture_env_combine": "1.3",
|
||||
"GL_ARB_texture_env_dot3": "1.3",
|
||||
"GL_ARB_texture_border_clamp": "1.3",
|
||||
|
||||
"GL_EXT_texture3D": "1.2",
|
||||
"GL_EXT_bgra": "1.2",
|
||||
"GL_EXT_packed_pixels": "1.2",
|
||||
"GL_EXT_rescale_normal": "1.2",
|
||||
"GL_EXT_separate_specular_color": "1.2",
|
||||
"GL_SGIS_texture_edge_clamp": "1.2",
|
||||
"GL_SGIS_texture_lod": "1.2",
|
||||
"GL_EXT_draw_range_elements": "1.2",
|
||||
"GL_EXT_blend_color": "1.2",
|
||||
"GL_EXT_blend_minmax": "1.2",
|
||||
"GL_EXT_blend_subtract": "1.2",
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
from django.db import models
|
||||
from django.utils import simplejson
|
||||
|
||||
import re
|
||||
|
||||
class UserReport(models.Model):
|
||||
|
||||
uploader = models.IPAddressField(editable = False)
|
||||
@ -31,6 +33,12 @@ class UserReport(models.Model):
|
||||
self.cached_json = None
|
||||
return self.cached_json
|
||||
|
||||
def downcast(self):
|
||||
if self.data_type == 'hwdetect':
|
||||
return UserReport_hwdetect.objects.get(id = self.id)
|
||||
else:
|
||||
return self
|
||||
|
||||
class UserReport_hwdetect(UserReport):
|
||||
|
||||
class Meta:
|
||||
@ -48,6 +56,16 @@ class UserReport_hwdetect(UserReport):
|
||||
os = 'OS X'
|
||||
return os
|
||||
|
||||
def gl_renderer(self):
|
||||
json = self.data_json()
|
||||
if json is None or 'GL_RENDERER' not in json:
|
||||
return None
|
||||
# The renderer string should typically be interpreted as UTF-8
|
||||
try:
|
||||
return json['GL_RENDERER'].encode('iso-8859-1').decode('utf-8')
|
||||
except UnicodeError:
|
||||
return json['GL_RENDERER']
|
||||
|
||||
def gl_extensions(self):
|
||||
json = self.data_json()
|
||||
if json is None or 'GL_EXTENSIONS' not in json:
|
||||
@ -63,7 +81,72 @@ class UserReport_hwdetect(UserReport):
|
||||
for (k, v) in json.items():
|
||||
if not k.startswith('GL_'):
|
||||
continue
|
||||
if k in ('GL_RENDERER', 'GL_VENDOR', 'GL_EXTENSIONS'):
|
||||
if k == 'GL_VERSION':
|
||||
m = re.match(r'^(\d+\.\d+).*', v)
|
||||
if m:
|
||||
limits[k] = '%s [...]' % m.group(1)
|
||||
continue
|
||||
if k in ('GL_RENDERER', 'GL_EXTENSIONS'):
|
||||
continue
|
||||
# Hide some values that got deleted from the report in r8953, for consistency
|
||||
if k in ('GL_MAX_COLOR_MATRIX_STACK_DEPTH', 'GL_FRAGMENT_PROGRAM_ARB.GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB', 'GL_FRAGMENT_PROGRAM_ARB.GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB'):
|
||||
continue
|
||||
limits[k] = v
|
||||
return limits
|
||||
|
||||
# Construct a nice-looking concise graphics device identifier
|
||||
# (skipping boring hardware/driver details)
|
||||
def gl_device_identifier(self):
|
||||
r = self.gl_renderer()
|
||||
m = re.match(r'^(?:ATI |Mesa DRI )?(.*?)\s*(?:GEM 20100330 DEVELOPMENT|GEM 20091221 2009Q4|20090101|Series)?\s*(?:x86|/AGP|/PCI|/MMX|/MMX\+|/SSE|/SSE2|/3DNOW!|/3DNow!\+)*(?: TCL| NO-TCL)?(?: DRI2)?$', r)
|
||||
if m:
|
||||
r = m.group(1)
|
||||
return r
|
||||
|
||||
# Construct a nice string identifying the driver
|
||||
def gl_driver(self):
|
||||
json = self.data_json()
|
||||
gfx_drv_ver = json['gfx_drv_ver']
|
||||
|
||||
# Try the Mesa style first
|
||||
m = re.match(r'^OpenGL \d+\.\d+(?:\.\d+)? (Mesa .*)$', gfx_drv_ver)
|
||||
if m:
|
||||
return m.group(1)
|
||||
|
||||
# Try the NVIDIA Linux style
|
||||
m = re.match(r'^OpenGL \d+\.\d+(?:\.\d+)? NVIDIA (.*)$', gfx_drv_ver)
|
||||
if m:
|
||||
return m.group(1)
|
||||
|
||||
# Try the ATI Catalyst Linux style
|
||||
m = re.match(r'^OpenGL (\d+\.\d+\.\d+) Compatibility Profile Context$', gfx_drv_ver)
|
||||
if m:
|
||||
return m.group(1)
|
||||
|
||||
# Try to guess the relevant Windows driver
|
||||
# (These are the ones listed in lib/sysdep/os/win/wgfx.cpp)
|
||||
|
||||
if json['GL_VENDOR'] == 'NVIDIA Corporation':
|
||||
# Assume 64-bit takes precedence
|
||||
m = re.search(r'nvoglv64.dll \((.*?)\)', gfx_drv_ver)
|
||||
if m: return m.group(1)
|
||||
m = re.search(r'nvoglv32.dll \((.*?)\)', gfx_drv_ver)
|
||||
if m: return m.group(1)
|
||||
m = re.search(r'nvoglnt.dll \((.*?)\)', gfx_drv_ver)
|
||||
if m: return m.group(1)
|
||||
|
||||
if json['GL_VENDOR'] in ('ATI Technologies Inc.', 'Advanced Micro Devices, Inc.'):
|
||||
m = re.search(r'atioglxx.dll \((.*?)\)', gfx_drv_ver)
|
||||
if m: return m.group(1)
|
||||
|
||||
if json['GL_VENDOR'] == 'Intel':
|
||||
# Assume 64-bit takes precedence
|
||||
m = re.search(r'ig4icd64.dll \((.*?)\)', gfx_drv_ver)
|
||||
if m: return m.group(1)
|
||||
m = re.search(r'ig4icd32.dll \((.*?)\)', gfx_drv_ver)
|
||||
if m: return m.group(1)
|
||||
# Legacy 32-bit
|
||||
m = re.search(r'iglicd32.dll \((.*?)\)', gfx_drv_ver)
|
||||
if m: return m.group(1)
|
||||
|
||||
return gfx_drv_ver
|
||||
|
@ -37,16 +37,22 @@ CPU capabilities
|
||||
<th>Caches (data/instruction/unified)
|
||||
<th>TLBs
|
||||
<th>Feature bits
|
||||
<th>NUMA
|
||||
{% for cpu,users in cpus|sortedcpuitems %}
|
||||
<tr {% cycle 'class=alt' '' %}>
|
||||
<td>{{ cpu.os }}
|
||||
<td><nobr>{{ cpu.cpu_identifier }}</nobr>
|
||||
<td>{{ cpu.x86_vendor }}/{{ cpu.x86_model }}/{{ cpu.x86_family }}
|
||||
<td>{% if cpu.cpu_frequency = -1 %}?{% else %}{{ cpu.cpu_frequency|cpufreqformat }}{% endif %}
|
||||
<td>{% if cpu.cpu_frequency = -1 %}{% else %}{{ cpu.cpu_frequency|cpufreqformat }}{% endif %}
|
||||
<td>{{ cpu.cpu_numpackages }}×{{ cpu.cpu_coresperpackage }}×{{ cpu.cpu_logicalpercore }} = {{ cpu.cpu_numprocs }}
|
||||
<td><nobr>{{ cpu.caches|join:"<br>" }}</nobr>
|
||||
<td><nobr>{{ cpu.tlbs|join:"<br>" }}</nobr>
|
||||
<td>{% for cap in cpu.caps|sort %}{% if cap in x86_cap_descs %}<abbr title="{{ x86_cap_descs|dictget:cap }}">{{ cap }}</abbr>{% else %}{{ cap }}{% endif %} {% endfor %}
|
||||
<td>{% if cpu.numa_numnodes != 1 %}<nobr>
|
||||
Nodes: {{ cpu.numa_numnodes }}<br>
|
||||
Factor: {{ cpu.numa_factor|floatformat:3 }}<br>
|
||||
Interleaved: {{ cpu.numa_interleaved }}
|
||||
</nobr>{% endif %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
@ -0,0 +1,29 @@
|
||||
{% extends "reports/base.html" %}
|
||||
{% load report_tags %}
|
||||
|
||||
{% block content %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Received
|
||||
<th>User
|
||||
<th>gfx_card
|
||||
<th>gfx_drv_ver
|
||||
<th>uname_machine
|
||||
<th>uname_release
|
||||
<th>uname_sysname
|
||||
<th>uname_version
|
||||
{% for report in report_page.object_list %}
|
||||
{% with json=report.data_json %}
|
||||
<tr {% cycle 'class=alt' '' %}>
|
||||
<td>{{ report.upload_date|date:"Y-m-d" }} {{ report.upload_date|date:"H:i:s" }}
|
||||
<td><a href="{% url userreport.views_private.report_user report.user_id_hash %}"><abbr title="{{ report.user_id_hash }}">{{ report.user_id_hash|slice:"0:8" }}</abbr></a>
|
||||
<td>{{ json.gfx_card }}
|
||||
<td>{{ json.gfx_drv_ver }}
|
||||
<td>{{ json.uname_machine }}
|
||||
<td>{{ json.uname_release }}
|
||||
<td>{{ json.uname_sysname }}
|
||||
<td>{{ json.uname_version }}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endblock %}
|
@ -12,10 +12,7 @@ td.false.alt { background: #e22; }
|
||||
.device-status ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.device-status li {
|
||||
list-style: none;
|
||||
padding-left: 2em;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
@ -51,7 +48,7 @@ There is a column for each distinct set of reported features.</p>
|
||||
<tr><td>
|
||||
{% for device in devices %}
|
||||
<th{% safe_cycle ' class=alt' '' %}>
|
||||
{{ device.0.renderer }} ({{ device.0.os }}):
|
||||
{{ device.0.device }} ({{ device.0.os }}):
|
||||
<ul>{% for driver in device.1 %}<li>{{ driver }}{% endfor %}</ul>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@ -68,7 +65,7 @@ There is a column for each distinct set of reported features.</p>
|
||||
<tr><td>
|
||||
{% for device in devices %}
|
||||
<th{% safe_cycle ' class=alt' '' %}>
|
||||
{{ device.0.renderer }} ({{ device.0.os }}):
|
||||
{{ device.0.device }} ({{ device.0.os }}):
|
||||
<ul>{% for driver in device.1 %}<li>{{ driver }}{% endfor %}</ul>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@ -91,4 +88,4 @@ There is a column for each distinct set of reported features.</p>
|
||||
<input type=submit value="Compare selected devices">
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
@ -59,7 +59,7 @@ OpenGL capabilities report: {{ feature }}
|
||||
{% for device in values.true|sorteddeviceitems %}
|
||||
<tr class="data{% safe_cycle '' ' alt'%}">
|
||||
<td>{{ device.0.vendor }}
|
||||
<td class=r><a href="{% url userreport.views.report_opengl_device device.0.renderer %}">{{ device.0.renderer }}</a>
|
||||
<td class=r><a href="{% url userreport.views.report_opengl_device device.0.device %}">{{ device.0.renderer }}</a>
|
||||
<td>{{ device.0.os }}
|
||||
<td><ul>
|
||||
{% for driver in device.1|sort %}<li>{{ driver }}{% endfor %}
|
||||
@ -78,7 +78,7 @@ OpenGL capabilities report: {{ feature }}
|
||||
{% for device in values.false|sorteddeviceitems %}
|
||||
<tr class="data{% safe_cycle '' ' alt'%}">
|
||||
<td>{{ device.0.vendor }}
|
||||
<td class=r><a href="{% url userreport.views.report_opengl_device device.0.renderer %}">{{ device.0.renderer }}</a>
|
||||
<td class=r><a href="{% url userreport.views.report_opengl_device device.0.device %}">{{ device.0.renderer }}</a>
|
||||
<td>{{ device.0.os }}
|
||||
<td><ul>
|
||||
{% for driver in device.1|sort %}<li>{{ driver }}{% endfor %}
|
||||
@ -105,7 +105,7 @@ OpenGL capabilities report: {{ feature }}
|
||||
{% for device in values|dictget:val|sorteddeviceitems %}
|
||||
<tr class="data{% safe_cycle '' ' alt'%}">
|
||||
<td>{{ device.0.vendor }}
|
||||
<td class=r><a href="{% url userreport.views.report_opengl_device device.0.renderer %}">{{ device.0.renderer }}</a>
|
||||
<td class=r><a href="{% url userreport.views.report_opengl_device device.0.device %}">{{ device.0.renderer }}</a>
|
||||
<td>{{ device.0.os }}
|
||||
<td><ul>
|
||||
{% for driver in device.1|sort %}<li>{{ driver }}{% endfor %}
|
||||
@ -118,4 +118,4 @@ OpenGL capabilities report: {{ feature }}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
@ -68,6 +68,11 @@ function sort_by_name(ul)
|
||||
Feel free to do whatever you want with the data.</p>
|
||||
<p>See the <a href="{% url userreport.views.index %}">index page</a> for more stuff.</p>
|
||||
|
||||
<p>The listed extensions are based on the GL_EXTENSIONS string:
|
||||
we don't show an extension as supported if it's not explicitly advertised,
|
||||
even if GL_VERSION is a version where that extension was folded into
|
||||
the main spec.</p>
|
||||
|
||||
<div class=col>
|
||||
<h2>Extension support</h2>
|
||||
Sort by
|
||||
@ -79,6 +84,7 @@ Sort by
|
||||
<span class=progress title="Percentage of devices that support this extension"><span class=bar style="width:{% widthratio ext_devices|dictget:ext|length all_devices|length 40 %}px">{% widthratio ext_devices|dictget:ext|length all_devices|length 100 %}%</span></span>
|
||||
(<a href="{{ ext|glext_spec_link }}">spec</a>)
|
||||
<a href="{% url userreport.views.report_opengl_feature ext %}">{{ ext }}</a>
|
||||
{% if ext in ext_versions %}(~GL{{ ext_versions|dictget:ext }}){% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
@ -93,10 +99,10 @@ Sort by
|
||||
<div class=col>
|
||||
<h2>Device details</h2>
|
||||
<ul>
|
||||
{% for device in all_devices %}
|
||||
<li><a href="{% url userreport.views.report_opengl_device device %}">{{ device }}</a>
|
||||
{% for device,users in all_devices|sorteditems %}
|
||||
<li><a href="{% url userreport.views.report_opengl_device device %}">{{ device }}</a> {% if 0 %}({{ users|length }} users){% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
@ -0,0 +1,18 @@
|
||||
{% extends "reports/base.html" %}
|
||||
{% load report_tags %}
|
||||
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{{ data }}
|
||||
<hr>
|
||||
???
|
||||
|
||||
{% for report in reports %}
|
||||
{{ report }}
|
||||
<hr>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
@ -7,6 +7,9 @@ table.profile td {
|
||||
border-bottom: inherit;
|
||||
padding: 0 1em 0 0.5em;
|
||||
}
|
||||
table.profile td {
|
||||
white-space: pre;
|
||||
}
|
||||
.treemarker {
|
||||
color: #666;
|
||||
font-family: monospace;
|
||||
@ -38,4 +41,4 @@ table.profile td {
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
@ -82,32 +82,14 @@ def reverse(value):
|
||||
|
||||
@register.filter
|
||||
def format_profile(table):
|
||||
cols = set()
|
||||
def extract_cols(t):
|
||||
for name, row in t.items():
|
||||
for n in row:
|
||||
cols.add(n)
|
||||
if 'children' in row:
|
||||
extract_cols(row['children'])
|
||||
extract_cols(table)
|
||||
if 'children' in cols:
|
||||
cols.remove('children')
|
||||
cols = table['cols']
|
||||
|
||||
if 'msec/frame' in cols:
|
||||
cols = ('msec/frame', 'calls/frame', '%/frame', '%/parent', 'mem allocs')
|
||||
else:
|
||||
cols = sorted(cols)
|
||||
|
||||
|
||||
out = ['<th>']
|
||||
out = []
|
||||
for c in cols:
|
||||
out.append(u'<th>%s' % conditional_escape(c))
|
||||
|
||||
def handle(indents, indent, t):
|
||||
if 'msec/frame' in cols:
|
||||
items = [d[1] for d in sorted((-float(r.get('msec/frame', '')), (n,r)) for (n,r) in t.items())]
|
||||
else:
|
||||
items = sorted(t.items())
|
||||
items = sorted(t.items())
|
||||
|
||||
item_id = 0
|
||||
for name, row in items:
|
||||
@ -118,11 +100,13 @@ def format_profile(table):
|
||||
item_id += 1
|
||||
|
||||
out.append(u'<tr>')
|
||||
out.append(u'<td><span class=treemarker>%s%s─%s╴</span>%s' % (indent, (u'└' if last else u'├'), (u'┬' if 'children' in row else u'─'), conditional_escape(name)))
|
||||
for c in cols:
|
||||
out.append(u'<td>%s%s' % (' ' * indents, conditional_escape(row.get(c, ''))))
|
||||
if 'children' in row:
|
||||
handle(indents+1, indent+(u' ' if last else u'│ '), row['children'])
|
||||
handle(0, u'', table)
|
||||
out.append(u'<td><span class=treemarker>%s%s─%s╴</span>%s' % (indent, (u'└' if last else u'├'), (u'┬' if row[0] is not None else u'─'), conditional_escape(name)))
|
||||
outrow = []
|
||||
for c in range(1, len(cols)):
|
||||
outrow.append(u'<td>%s%s' % (' ' * indents, conditional_escape(row[c])))
|
||||
out.append('%s</td>' % ''.join(outrow))
|
||||
if row[0] is not None:
|
||||
handle(indents+1, indent+(u' ' if last else u'│ '), row[0])
|
||||
handle(0, u'', table['data'])
|
||||
|
||||
return mark_safe(u'\n'.join(out))
|
||||
|
@ -4,5 +4,7 @@ urlpatterns = patterns('',
|
||||
(r'^hwdetect/$', 'userreport.views_private.report_hwdetect'),
|
||||
(r'^messages/$', 'userreport.views_private.report_messages'),
|
||||
(r'^profile/$', 'userreport.views_private.report_profile'),
|
||||
(r'^performance/$', 'userreport.views_private.report_performance'),
|
||||
(r'^gfx/$', 'userreport.views_private.report_gfx'),
|
||||
(r'^user/([0-9a-f]+)$', 'userreport.views_private.report_user'),
|
||||
)
|
||||
|
@ -1,5 +1,6 @@
|
||||
from userreport.models import UserReport, UserReport_hwdetect
|
||||
import userreport.x86 as x86
|
||||
import userreport.gl
|
||||
|
||||
import hashlib
|
||||
import datetime
|
||||
@ -102,15 +103,20 @@ def report_cpu(request):
|
||||
else:
|
||||
return '%d-way' % w
|
||||
|
||||
def fmt_cache(c):
|
||||
def fmt_cache(c, t):
|
||||
types = ('?', 'D', 'I ', 'U')
|
||||
return "L%d %s: %s (%s, shared %dx, %dB line)" % (
|
||||
if c['type'] == 0:
|
||||
return "(Unknown %s cache)" % t
|
||||
return "L%d %s: %s (%s, shared %dx%s)" % (
|
||||
c['level'], types[c['type']], fmt_size(c['totalsize']),
|
||||
fmt_assoc(c['associativity']), c['sharedby'], c['linesize']
|
||||
fmt_assoc(c['associativity']), c['sharedby'],
|
||||
('' if c['linesize'] == 64 else ', %dB line' % c['linesize'])
|
||||
)
|
||||
|
||||
def fmt_tlb(c):
|
||||
def fmt_tlb(c, t):
|
||||
types = ('?', 'D', 'I ', 'U')
|
||||
if c['type'] == 0:
|
||||
return "(Unknown %s TLB)" % t
|
||||
return "L%d %s: %d-entry (%s, %s page)" % (
|
||||
c['level'], types[c['type']], c['entries'],
|
||||
fmt_assoc(c['associativity']), fmt_size(c['pagesize'])
|
||||
@ -121,16 +127,16 @@ def report_cpu(request):
|
||||
icaches = i[:]
|
||||
caches = []
|
||||
while len(dcaches) or len(icaches):
|
||||
if len(dcaches) and len(icaches) and dcaches[0] == icaches[0]:
|
||||
caches.append(cb(dcaches[0]))
|
||||
if len(dcaches) and len(icaches) and dcaches[0] == icaches[0] and dcaches[0]['type'] == 3:
|
||||
caches.append(cb(dcaches[0], 'U'))
|
||||
dcaches.pop(0)
|
||||
icaches.pop(0)
|
||||
else:
|
||||
if len(dcaches):
|
||||
caches.append(cb(dcaches[0]))
|
||||
caches.append(cb(dcaches[0], 'D'))
|
||||
dcaches.pop(0)
|
||||
if len(icaches):
|
||||
caches.append(cb(icaches[0]))
|
||||
caches.append(cb(icaches[0], 'I'))
|
||||
icaches.pop(0)
|
||||
return tuple(caches)
|
||||
|
||||
@ -168,29 +174,26 @@ def report_opengl_json(request):
|
||||
exts = report.gl_extensions()
|
||||
limits = report.gl_limits()
|
||||
|
||||
devices.setdefault(hashabledict({'vendor': json['GL_VENDOR'], 'renderer': json['GL_RENDERER'], 'os': report.os()}), {}).setdefault((hashabledict(limits), exts), set()).add(json['gfx_drv_ver'])
|
||||
devices.setdefault(hashabledict({'renderer': report.gl_renderer(), 'os': report.os()}), {}).setdefault((hashabledict(limits), exts), set()).add(report.gl_driver())
|
||||
|
||||
distinct_devices = []
|
||||
for (renderer, v) in devices.items():
|
||||
for (caps, versions) in v.items():
|
||||
distinct_devices.append((renderer, sorted(versions), caps))
|
||||
distinct_devices.sort(key = lambda x: (x[0]['vendor'], x[0]['renderer'], x[0]['os'], x))
|
||||
distinct_devices.sort(key = lambda x: (x[0]['renderer'], x[0]['os'], x))
|
||||
|
||||
data = []
|
||||
for r,vs,(limits,exts) in distinct_devices:
|
||||
data.append({'device': r, 'versions': vs, 'limits': limits, 'extensions': sorted(exts)})
|
||||
data.append({'device': r, 'drivers': vs, 'limits': limits, 'extensions': sorted(exts)})
|
||||
json = simplejson.dumps(data, indent=1, sort_keys=True)
|
||||
return HttpResponse(json, content_type = 'text/plain')
|
||||
|
||||
def device_identifier(json):
|
||||
return json['GL_RENDERER']
|
||||
|
||||
def report_opengl_index(request):
|
||||
reports = get_hwdetect_reports()
|
||||
|
||||
all_limits = set()
|
||||
all_exts = set()
|
||||
all_devices = set()
|
||||
all_devices = {}
|
||||
ext_devices = {}
|
||||
|
||||
for report in reports:
|
||||
@ -198,8 +201,8 @@ def report_opengl_index(request):
|
||||
if json is None:
|
||||
continue
|
||||
|
||||
device = device_identifier(json)
|
||||
all_devices.add(device)
|
||||
device = report.gl_device_identifier()
|
||||
all_devices.setdefault(device, set()).add(report.user_id_hash)
|
||||
|
||||
exts = report.gl_extensions()
|
||||
all_exts |= exts
|
||||
@ -211,13 +214,13 @@ def report_opengl_index(request):
|
||||
|
||||
all_limits = sorted(all_limits)
|
||||
all_exts = sorted(all_exts)
|
||||
all_devices = sorted(all_devices)
|
||||
|
||||
return render_to_response('reports/opengl_index.html', {
|
||||
'all_limits': all_limits,
|
||||
'all_exts': all_exts,
|
||||
'all_devices': all_devices,
|
||||
'ext_devices': ext_devices,
|
||||
'ext_versions': userreport.gl.glext_versions,
|
||||
})
|
||||
|
||||
def report_opengl_feature(request, feature):
|
||||
@ -232,6 +235,7 @@ def report_opengl_feature(request, feature):
|
||||
if json is None:
|
||||
continue
|
||||
|
||||
device = report.gl_device_identifier()
|
||||
exts = report.gl_extensions()
|
||||
limits = hashabledict(report.gl_limits())
|
||||
|
||||
@ -243,7 +247,7 @@ def report_opengl_feature(request, feature):
|
||||
val = limits[feature]
|
||||
all_values.add(val)
|
||||
|
||||
values.setdefault(val, {}).setdefault(hashabledict({'vendor': json['GL_VENDOR'], 'renderer': json['GL_RENDERER'], 'os': report.os()}), set()).add(json['gfx_drv_ver'])
|
||||
values.setdefault(val, {}).setdefault(hashabledict({'vendor': json['GL_VENDOR'], 'renderer': report.gl_renderer(), 'os': report.os(), 'device': device}), set()).add(report.gl_driver())
|
||||
|
||||
if values.keys() == [None]:
|
||||
raise Http404
|
||||
@ -274,7 +278,7 @@ def report_opengl_devices(request, selected):
|
||||
if json is None:
|
||||
continue
|
||||
|
||||
device = device_identifier(json)
|
||||
device = report.gl_device_identifier()
|
||||
all_devices.add(device)
|
||||
if device not in selected:
|
||||
continue
|
||||
@ -285,7 +289,7 @@ def report_opengl_devices(request, selected):
|
||||
limits = report.gl_limits()
|
||||
all_limits |= set(limits.keys())
|
||||
|
||||
devices.setdefault(hashabledict({'vendor': json['GL_VENDOR'], 'renderer': json['GL_RENDERER'], 'os': report.os()}), {}).setdefault((hashabledict(limits), exts), set()).add(json['gfx_drv_ver'])
|
||||
devices.setdefault(hashabledict({'device': report.gl_device_identifier(), 'os': report.os()}), {}).setdefault((hashabledict(limits), exts), set()).add(report.gl_driver())
|
||||
|
||||
if len(selected) == 1 and len(devices) == 0:
|
||||
raise Http404
|
||||
@ -297,7 +301,7 @@ def report_opengl_devices(request, selected):
|
||||
for (renderer, v) in devices.items():
|
||||
for (caps, versions) in v.items():
|
||||
distinct_devices.append((renderer, sorted(versions), caps))
|
||||
distinct_devices.sort(key = lambda x: (x[0]['vendor'], x[0]['renderer'], x[0]['os'], x))
|
||||
distinct_devices.sort(key = lambda x: (x[0]['device'], x))
|
||||
|
||||
return render_to_response('reports/opengl_device.html', {
|
||||
'selected': selected,
|
||||
|
@ -1,9 +1,13 @@
|
||||
from userreport.models import UserReport
|
||||
|
||||
from django.http import HttpResponseForbidden
|
||||
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
|
||||
|
||||
import re
|
||||
import numpy
|
||||
|
||||
def render_reports(request, reports, template, args):
|
||||
paginator = Paginator(reports, args.get('pagesize', 100))
|
||||
@ -34,7 +38,7 @@ def report_messages(request):
|
||||
|
||||
def report_profile(request):
|
||||
reports = UserReport.objects.order_by('-upload_date')
|
||||
reports = reports.filter(data_type = 'profile', data_version__gte = 1)
|
||||
reports = reports.filter(data_type = 'profile', data_version__gte = 2)
|
||||
|
||||
return render_reports(request, reports, 'reports/profile.html', {'pagesize': 20})
|
||||
|
||||
@ -43,3 +47,104 @@ def report_hwdetect(request):
|
||||
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 = 1)
|
||||
)
|
||||
|
||||
def summarise_hwdetect(report):
|
||||
json = report.data_json()
|
||||
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()
|
||||
msecs = None
|
||||
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:
|
||||
#msecs = m.group(1)
|
||||
try:
|
||||
if report.data_version == 1:
|
||||
msecs = float(table['render']['msec/frame'])
|
||||
else:
|
||||
msecs = float(table['data']['render'][2])
|
||||
except KeyError:
|
||||
pass
|
||||
# TODO: get the render time?
|
||||
# TODO: get shadow, water settings
|
||||
return {
|
||||
'msecs': msecs,
|
||||
'map': json['map'],
|
||||
'time': json['time'],
|
||||
# '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:
|
||||
profiles.append([report.user_id_hash, last_hwdetect[report.user_id_hash], summarise_profile(report)])
|
||||
|
||||
datapoints = {}
|
||||
for user,hwdetect,profile in profiles:
|
||||
if hwdetect['build_debug']:
|
||||
continue
|
||||
# if profile['time'] != 60:
|
||||
# continue
|
||||
if profile['msecs'] is None or float(profile['msecs']) == 0:
|
||||
continue
|
||||
datapoints.setdefault(hwdetect['device'], []).append(profile['msecs'])
|
||||
|
||||
# return render_to_response('reports/performance.html', {'data': datapoints, 'reports': profiles})
|
||||
|
||||
sorted_datapoints = sorted(datapoints.items(), key = lambda (k,v):
|
||||
-numpy.median(v)
|
||||
)
|
||||
|
||||
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,16))
|
||||
|
||||
ax = fig.add_subplot(111)
|
||||
fig.subplots_adjust(left = 0.05, right = 0.99, top = 0.99, bottom = 0.2)
|
||||
|
||||
ax.boxplot(data_boxplot, sym = '')
|
||||
ax.scatter(data_scatter[0], data_scatter[1], marker='x')
|
||||
|
||||
ax.set_ylim(1, 10000)
|
||||
ax.set_yscale('log')
|
||||
ax.set_ylabel('Render time (msecs)')
|
||||
|
||||
ax.set_xticklabels([k for k,v in sorted_datapoints], rotation=90, fontsize=8)
|
||||
|
||||
canvas = FigureCanvas(fig)
|
||||
response = HttpResponse(content_type = 'image/png')
|
||||
canvas.print_png(response, dpi=80)
|
||||
return response
|
||||
|
Loading…
Reference in New Issue
Block a user