Skip to content
This repository has been archived by the owner on May 19, 2021. It is now read-only.

Commit

Permalink
Initial release
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas Haag committed Aug 17, 2016
0 parents commit eed4c43
Show file tree
Hide file tree
Showing 53 changed files with 2,466 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
*.sqlite*
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "vmprof-server"]
path = vmprof-server
url = https://github.com/vmprof/vmprof-server
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
recursive-include profiles/templates *
recursive-include vmprof_viewer/templates *
recursive-include vmprof_viewer/collected-static *
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# vmprof-viewer server

For vmprof-viewer usage instructions, see https://github.com/jonashaag/vmprof-viewer-client.

To get the vmprof-viewer server running, follow a standard Django deployment:

```sh
# Clone repo
git clone git+https://github.com/jonashaag/vmprof-viewer
cd vmprof-viewer
git submodule update --init

# Apply our vmprof-server patch
cd vmprof-server/; git apply ../vmprof-server-patch.diff; cd -

# Install dependencies
virtualenv env
. env/bin/activate
pip install -r requirements.txt

# Bootstrap server application
vmprof_viewer/manage.py migrate

# Start server
vmprof_viewer/manage.py runserver
```
Empty file added profiles/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions profiles/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
7 changes: 7 additions & 0 deletions profiles/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from __future__ import unicode_literals

from django.apps import AppConfig


class ProfilesConfig(AppConfig):
name = 'profiles'
36 changes: 36 additions & 0 deletions profiles/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10b1 on 2016-06-28 16:30
from __future__ import unicode_literals

from django.db import migrations, models
import profiles.models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='ProfileRun',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('project', models.CharField(max_length=200)),
('top_level_function', models.CharField(blank=True, max_length=200)),
('version', models.IntegerField()),
('cpu_profile', models.FileField(upload_to=profiles.models.get_profile_storage_directory)),
('memory_profile', models.FileField(upload_to=profiles.models.get_profile_storage_directory)),
('addr_name_map', models.FileField(upload_to=profiles.models.get_profile_storage_directory)),
('max_memory_use', models.BigIntegerField(blank=True, null=True)),
('time_spent', models.BigIntegerField(blank=True, null=True)),
('profile_resolution', models.BigIntegerField(blank=True, null=True)),
],
options={
'ordering': ['-created'],
},
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10b1 on 2016-08-04 09:12
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

replaces = [(b'profiles', '0002_auto_20160804_0910'), (b'profiles', '0003_remove_profilerun_end_state')]

dependencies = [
('profiles', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='profilerun',
name='start_date',
field=models.DateTimeField(blank=True, null=True),
),
]
Empty file added profiles/migrations/__init__.py
Empty file.
47 changes: 47 additions & 0 deletions profiles/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from __future__ import unicode_literals
from django.db import models


def get_profile_storage_directory(profile, filename):
return "%d/%s" % (profile.pk, filename)


class ProfileRun(models.Model):
created = models.DateTimeField(auto_now_add=True)
start_date = models.DateTimeField(blank=True, null=True)
project = models.CharField(max_length=200)
top_level_function = models.CharField(max_length=200, blank=True)
version = models.IntegerField()
cpu_profile = models.FileField(upload_to=get_profile_storage_directory)
memory_profile = models.FileField(upload_to=get_profile_storage_directory)
addr_name_map = models.FileField(upload_to=get_profile_storage_directory)
#: Maximum memory used by the function, in KiB. (max: 8 ZiB)
max_memory_use = models.BigIntegerField(blank=True, null=True)
#: Time spent in the function (in microseconds; this is simply a cached
#: version of "#ticks * profile_resolution")
time_spent = models.BigIntegerField(blank=True, null=True)
#: Time resolution of profile (delay between profile ticks in microseconds)
profile_resolution = models.BigIntegerField(blank=True, null=True)

class Meta:
ordering = ['-created']

@property
def max_memory_use_gib(self):
if self.max_memory_use is not None:
return self.max_memory_use / 1024.0 / 1024

@property
def time_spent_human(self):
if self.time_spent is not None:
res = []
remainder = self.time_spent / 10.**6
if remainder >= 3600:
res.append("%dh" % (remainder / 3600))
remainder %= 3600
if remainder >= 60:
res.append("%dm" % (remainder / 60))
remainder %= 60
if remainder > 0 and len(res) < 2:
res.append("%ds" % remainder)
return " ".join(res)
66 changes: 66 additions & 0 deletions profiles/static/css/mem.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
img.loading {
position: fixed;
width: 60px;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
}
#chart-container, #annotation {
float: left;
}
#chart-container {
z-index: 1;
background: white;
width: 73%;
height: 100%;
}
#chart { height: 100%; }
#annotation {
width: 25%;
height: 100%;
padding-left: 2%;
border-left: 1px solid #eee;
}
.mem-consumption {
text-align: right;
padding-bottom: 15px;
}
.stacktrace ul {
list-style-type: none;
padding-left: 0;
}
.stacktrace li {
font-family: monospace;
position: relative;
height: 1.5em;
overflow: hidden;
}
.stacktrace .func {
font-weight: bold;
position: absolute;
left: 0;
z-index: 2;
padding-right: 2em;
background: linear-gradient(to right,
white 0, white 80%, white 80%, rgba(255,255,255,0) 120%
);
}
.stacktrace .file {
position: absolute;
white-space: nowrap;
right: 0;
font-size: 0.85em;
}
.stacktrace-secondary .stacktrace-count {
text-align: right;
border-bottom: 1px solid #eee;
margin-top: 20px;
}
.stacktrace-secondary .stacktrace-count:hover {
cursor: help;
}
.stacktrace-secondary .stacktrace-secondary-help small {
margin-top: 50px;
display: block;
line-height: 1.1;
}
114 changes: 114 additions & 0 deletions profiles/static/js/cpu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
var app = angular.module('vmprof', ['ngRoute'], function($routeProvider) {
$routeProvider.when('/:vmprof_vanilla_workaround/', {
templateUrl: '/static/vmprof-server/details.html',
controller: 'details'
}).otherwise({
redirectTo: '/_/'
});
});


app.controller('details', function ($scope, $http, $routeParams, $timeout, $q,
$location) {
angular.element('svg').remove();

if ($scope.stats) {
display_log($scope, $routeParams, $timeout, $location);
return;
}
$scope.loading = true;

var addrNameMapFetch = ajaxMsgpack({url: ADDR_NAME_MAP_FETCH_URL});
var profileFetch = ajaxMsgpack({url: PROFILE_FETCH_URL});
$q.all([addrNameMapFetch, profileFetch]).then(function ([addrNameMap, profiles]) {
$scope.log = {data: {argv: "CPU profile"}, checksum: "_"};
$scope.stats = new Stats({
profiles: convertCPUProfile(addrNameMap, profiles)
});
display_log($scope, $routeParams, $timeout, $location);
}, function (err) {
showError("Error retrieving profile data", err.statusText);
});
});


function convertCPUProfile(adr_dict, [addr, count, jitInfo, children]) {
return [adr_dict[addr], addr, count, jitInfo,
children.map(convertCPUProfile.bind(null, adr_dict))];
}




/*** BEGIN UNCHANGED CODE FROM VMPROF-SERVER ***/
app.filter('ago', function() {
return function(input) {
return moment.utc(input, 'YYYY-MM-DD HH:mm:ss').fromNow();
};
});

function display_log($scope, $routeParams, $timeout, $location)
{
var stats = $scope.stats;
$scope.visualization = $routeParams.view || 'flames';

$timeout(function () {
$('[data-toggle=tooltip]').tooltip();
var height = 800; //$('.table').height();
var $visualization = $("#visualization");
if ($visualization.length < 1)
return;
$scope.visualizationChange = function(visualization) {
$scope.visualization = visualization;
var stats = $scope.stats;
if (visualization == 'list') {
Visualization.listOfFunctions(
$("#visualization"),
height, $scope, $location,
stats.VM, true
);
}
if (visualization == 'function-details') {
Visualization.functionDetails($("#visualization"),
height, $routeParams.func_addr, $scope, $location);
}
if (visualization == 'list-2') {
Visualization.listOfFunctions(
$("#visualization"),
height, $scope, $location,
stats.VM, false
);
}
if (visualization == 'flames') {
var d = stats.getProfiles($routeParams.id);
$scope.root = d.root;
var cutoff = d.root.total / 100;
var addresses = $routeParams.id;
var path_so_far;
$scope.total_time = stats.allStats[d.root.addr].total / stats.nodes.total;
$scope.self_time = stats.allStats[d.root.addr].self / stats.nodes.total;
$scope.node_total_time = d.root.total / stats.nodes.total;
$scope.node_self_time = d.root.self / stats.nodes.total;
$scope.paths = d.paths;

if (addresses) {
path_so_far = addresses.split(",");
} else {
path_so_far = [];
}
Visualization.flameChart(
$("#visualization"),
height,
d.root,
$scope, $location,
cutoff, path_so_far,
stats.VM
);
}
};

$scope.visualizationChange($scope.visualization);
});
$scope.loading = false;
}
/*** END UNCHANGED CODE FROM VMPROF-SERVER ***/
Loading

0 comments on commit eed4c43

Please sign in to comment.