performance improvements

pull/5/head
cubedro 10 years ago
parent d340b08f2a
commit 8cf001d24c
  1. 5
      app.js
  2. 2
      dist/css/netstats.min.css
  3. 2
      dist/index.html
  4. 2
      dist/js/netstats.min.js
  5. 2
      dist/js/netstats.min.js.map
  6. 10
      models/collection.js
  7. 6
      public/css/style.css
  8. 164
      public/js/controllers.js
  9. 88
      public/js/directives.js
  10. 2
      public/js/script.js
  11. 11
      views/index.jade

@ -157,11 +157,6 @@ api.on('connection', function(spark) {
});
askedForHistory = false;
client.write({
action: 'charts',
data: Nodes.getCharts()
});
});
spark.on('node-ping', function(data)

File diff suppressed because one or more lines are too long

2
dist/index.html vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -22,12 +22,12 @@ Collection.prototype.update = function(id, stats)
{
var node = this.getNode({ id: id });
if(!node)
if (!node)
return false;
var block = this._blockchain.add(stats.block, id);
if(! block)
if (!block)
return false;
var propagationHistory = this._blockchain.getNodePropagation(id);
@ -43,7 +43,7 @@ Collection.prototype.addHistory = function(id, blocks)
{
var node = this.getNode({ id: id });
if(!node)
if (!node)
return false;
blocks = blocks.reverse();
@ -60,7 +60,7 @@ Collection.prototype.updateLatency = function(id, latency)
{
var node = this.getNode({ id: id });
if(!node)
if (!node)
return false;
return node.setLatency(latency);
@ -70,7 +70,7 @@ Collection.prototype.inactive = function(id)
{
var node = this.getNode({ spark: id });
if(!node)
if (!node)
return false;
node.setState(false);

@ -277,6 +277,12 @@ table td i {
table td.peerPropagationChart {
padding: 4px 5px !important;
}
nodepropagchart {
display: inline-block;
width: 107px;
height: 20px;
vertical-align: top;
}
.table>tbody>tr>td,
.table>thead>tr>th {

@ -69,7 +69,7 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
$scope.$apply();
}, 200);
$scope.getNumber = function(num) {
$scope.getNumber = function (num) {
return new Array(num);
}
@ -118,7 +118,7 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
$scope.nodes = data;
_.forEach($scope.nodes, function(node, index) {
_.forEach($scope.nodes, function (node, index) {
// Init hashrate
if( _.isUndefined(node.stats.hashrate) )
$scope.nodes[index].stats.hashrate = 0;
@ -132,10 +132,6 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
// Init or recover pin
$scope.nodes[index].pinned = _.result(_.find(oldNodes, 'id', node.id), 'pinned', false);
$scope.$apply();
makePeerPropagationChart($scope.nodes[index]);
});
if($scope.nodes.length > 0)
@ -144,27 +140,26 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
break;
case "add":
if(addNewNode(data))
toastr['success']("New node "+ $scope.nodes[findIndex({id: data.id})].info.name +" connected!", "New node!");
else
toastr['info']("Node "+ $scope.nodes[findIndex({id: data.id})].info.name +" reconnected!", "Node is back!");
var index = findIndex({id: data.id});
$scope.$apply();
makePeerPropagationChart($scope.nodes[findIndex({id: data.id})]);
if( addNewNode(data) )
toastr['success']("New node "+ $scope.nodes[index].info.name +" connected!", "New node!");
else
toastr['info']("Node "+ $scope.nodes[index].info.name +" reconnected!", "Node is back!");
break;
case "update":
if(typeof data.stats.hashrate === 'undefined')
data.stats.hashrate = 0;
var index = findIndex({id: data.id});
if( _.isUndefined(data.stats.hashrate) )
data.stats.hashrate = 0;
if( !_.isUndefined($scope.nodes[index].stats) ) {
if($scope.nodes[index].stats.block.number < data.stats.block.number)
if( $scope.nodes[index].stats.block.number < data.stats.block.number )
{
var best = _.max($scope.nodes, function(node) {
var best = _.max($scope.nodes, function (node) {
return parseInt(node.stats.block.number);
}).stats.block;
@ -173,23 +168,22 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
} else {
data.stats.block.arrived = best.arrived;
}
$scope.nodes[index].history = data.history;
}
$scope.nodes[index].stats = data.stats;
$scope.nodes[index].history = data.history;
$scope.$apply();
makePeerPropagationChart($scope.nodes[index]);
}
break;
case "info":
$scope.nodes[findIndex({id: data.id})].info = data.info;
var index = findIndex({id: data.id});
$scope.nodes[index].info = data.info;
if(_.isUndefined($scope.nodes[findIndex({id: data.id})].pinned))
$scope.nodes[findIndex({id: data.id})].pinned = false;
if( _.isUndefined($scope.nodes[index].pinned) )
$scope.nodes[index].pinned = false;
break;
@ -200,10 +194,8 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
break;
case "uncleCount":
$scope.uncleCountChart = data;
$scope.uncleCount = data[0] + data[1];
jQuery('.spark-uncles').sparkline($scope.uncleCountChart.reverse(), {type: 'bar', barSpacing: 1});
$scope.uncleCountChart = data.reverse();
break;
@ -214,40 +206,34 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
$scope.difficultyChart = data.difficulty;
$scope.blockPropagationChart = data.propagation.histogram;
$scope.blockPropagationAvg = data.propagation.avg;
$scope.uncleCountChart = data.uncleCount;
$scope.uncleCount = data.uncleCount[0] + data.uncleCount[1];
$scope.uncleCountChart = data.uncleCount.reverse();
$scope.transactionDensity = data.transactions;
$scope.gasSpending = data.gasSpending;
$scope.miners = data.miners;
$scope.$apply();
getMinersNames();
jQuery('.spark-blocktimes').sparkline($scope.lastBlocksTime, {type: 'bar', tooltipSuffix: ' s'});
jQuery('.spark-difficulty').sparkline($scope.difficultyChart, {type: 'bar'});
jQuery('.spark-transactions').sparkline($scope.transactionDensity, {type: 'bar'});
jQuery('.spark-gasspending').sparkline($scope.gasSpending, {type: 'bar'});
jQuery('.spark-uncles').sparkline($scope.uncleCountChart.reverse(), {type: 'bar', barSpacing: 1});
break;
case "inactive":
var index = findIndex({id: data.id});
if( !_.isUndefined(data.stats) )
$scope.nodes[findIndex({id: data.id})].stats = data.stats;
$scope.nodes[index].stats = data.stats;
toastr['error']("Node "+ $scope.nodes[findIndex({id: data.id})].info.name +" went away!", "Node connection was lost!");
toastr['error']("Node "+ $scope.nodes[index].info.name +" went away!", "Node connection was lost!");
break;
case "latency":
if( !_.isUndefined(data.id) )
var node = $scope.nodes[findIndex({id: data.id})];
var index = findIndex({id: data.id});
if( !_.isUndefined(node) && !_.isUndefined(node.stats) && !_.isUndefined(node.stats.latency))
$scope.nodes[findIndex({id: data.id})].stats.latency = data.latency;
if( !_.isUndefined(data.id) )
var node = $scope.nodes[index];
$scope.$apply();
if( !_.isUndefined(node) && !_.isUndefined(node.stats) && !_.isUndefined(node.stats.latency) )
$scope.nodes[index].stats.latency = data.latency;
break;
@ -257,7 +243,7 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
break;
}
if(action !== "latency")
if( action !== "latency" && action !== "client-ping" )
{
updateStats();
}
@ -268,39 +254,11 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
return _.findIndex($scope.nodes, search);
}
function makePeerPropagationChart(node)
{
jQuery('.' + node.id).sparkline(node.history, {
type: 'bar',
negBarColor: '#7f7f7f',
zeroAxis: false,
height: 20,
barWidth : 2,
barSpacing : 1,
tooltipSuffix: '',
chartRangeMax: 8000,
colorMap: jQuery.range_map({
'0:1': '#10a0de',
'1:1000': '#7bcc3a',
'1001:3000': '#FFD162',
'3001:7000': '#ff8a00',
'7001:': '#F74B4B'
}),
tooltipFormatter: function (spark, opt, ms) {
var tooltip = '<div class="tooltip-arrow"></div><div class="tooltip-inner">';
tooltip += $filter('blockPropagationFilter')(ms[0].value, '');
tooltip += '</div>';
return tooltip;
}
});
}
function getMinersNames()
{
if($scope.miners.length > 0)
if( $scope.miners.length > 0 )
{
_.forIn($scope.miners, function(value, key)
_.forIn($scope.miners, function (value, key)
{
if(value.name !== false)
return;
@ -310,7 +268,7 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
var name = _.result(_.find(_.pluck($scope.nodes, 'info'), 'coinbase', value.miner), 'name');
if(typeof name !== 'undefined')
if( !_.isUndefined(name) )
$scope.miners[key].name = name;
});
}
@ -319,44 +277,32 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
function addNewNode(data)
{
var index = findIndex({id: data.id});
if(index < 0)
{
if(typeof data.stats !== 'undefined' && typeof data.stats.hashrate === 'undefined')
data.stats.hashrate = 0;
data.pinned = false;
if( _.isUndefined(data.history) )
{
data.history = new Array(40);
_.fill(data.history, -1);
}
if( _.isUndefined(data.history) )
if( index < 0 )
{
if( !_.isUndefined(data.stats) && _.isUndefined(data.stats.hashrate) )
{
data.history = new Array(40);
_.fill(data.history, -1);
data.stats.hashrate = 0;
}
data.pinned = false;
$scope.nodes.push(data);
return true;
}
if( !_.isUndefined($scope.nodes[index].pinned) )
{
data.pinned = $scope.nodes[index].pinned
}
else
{
data.pinned = false;
}
data.pinned = ( !_.isUndefined($scope.nodes[index].pinned) ? $scope.nodes[index].pinned : false);
if( !_.isUndefined($scope.nodes[index].pinned) )
if( !_.isUndefined($scope.nodes[index].history) )
{
data.history = $scope.nodes[index].history
}
else
{
if( _.isUndefined(data.history) )
{
data.history = new Array(40);
_.fill(data.history, -1);
}
data.history = $scope.nodes[index].history;
}
$scope.nodes[index] = data;
@ -366,22 +312,22 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
function updateStats()
{
if($scope.nodes.length)
if( $scope.nodes.length )
{
$scope.nodesTotal = $scope.nodes.length;
$scope.nodesActive = _.filter($scope.nodes, function(node) {
$scope.nodesActive = _.filter($scope.nodes, function (node) {
return node.stats.active == true;
}).length;
var bestBlock = _.max($scope.nodes, function(node) {
var bestBlock = _.max($scope.nodes, function (node) {
return parseInt(node.stats.block.number);
}).stats.block.number;
if(bestBlock > $scope.bestBlock)
if( bestBlock > $scope.bestBlock )
{
$scope.bestBlock = bestBlock;
$scope.bestStats = _.max($scope.nodes, function(node) {
$scope.bestStats = _.max($scope.nodes, function (node) {
return parseInt(node.stats.block.number);
}).stats;
@ -389,11 +335,11 @@ netStatsApp.controller('StatsCtrl', function($scope, $filter, socket, _, toastr)
$scope.lastDifficulty = $scope.bestStats.block.difficulty;
}
$scope.upTimeTotal = _.reduce($scope.nodes, function(total, node) {
$scope.upTimeTotal = _.reduce($scope.nodes, function (total, node) {
return total + node.stats.uptime;
}, 0) / $scope.nodes.length;
$scope.map = _.map($scope.nodes, function(node) {
$scope.map = _.map($scope.nodes, function (node) {
var fill = $filter('bubbleClass')(node.stats, $scope.bestBlock);
if(node.geo != null)

@ -2,13 +2,89 @@
/* Directives */
angular.module('netStatsApp.directives', []).
directive('appVersion', ['version', function(version) {
angular.module('netStatsApp.directives', [])
.directive('appVersion', ['version', function (version) {
return function(scope, elm, attrs) {
elm.text(version);
};
}]).
directive('nodemap', ['$compile', function($compile) {
}])
.directive('sparkchart', ['$compile', '$filter', function($compile, $filter) {
return {
restrict: 'EA',
scope: {
data: '='
},
link: function (scope, element, attrs)
{
scope.init = function ()
{
element.empty();
jQuery(element[0]).sparkline(scope.data, {
type: 'bar',
tooltipSuffix: (attrs.tooltipsuffix || '')
});
}
scope.init();
scope.$watch('data', function ()
{
scope.init();
}, true);
}
};
}])
.directive('nodepropagchart', ['$compile', '$filter', function($compile, $filter) {
return {
restrict: 'EA',
scope: {
data: '='
},
link: function (scope, element, attrs)
{
var options = {
type: 'bar',
negBarColor: '#7f7f7f',
zeroAxis: false,
height: 20,
barWidth : 2,
barSpacing : 1,
tooltipSuffix: '',
chartRangeMax: 8000,
colorMap: jQuery.range_map({
'0:1': '#10a0de',
'1:1000': '#7bcc3a',
'1001:3000': '#FFD162',
'3001:7000': '#ff8a00',
'7001:': '#F74B4B'
}),
tooltipFormatter: function (spark, opt, ms) {
var tooltip = '<div class="tooltip-arrow"></div><div class="tooltip-inner">';
tooltip += $filter('blockPropagationFilter')(ms[0].value, '');
tooltip += '</div>';
return tooltip;
}
};
scope.init = function ()
{
element.empty();
jQuery(element[0]).sparkline(scope.data, options);
}
scope.init();
scope.$watch('data', function ()
{
scope.init();
}, true);
}
};
}])
.directive('nodemap', ['$compile', function($compile) {
return {
restrict: 'EA',
scope: {
@ -112,8 +188,8 @@ angular.module('netStatsApp.directives', []).
}, true);
}
};
}]).
directive('histogram', ['$compile', function($compile) {
}])
.directive('histogram', ['$compile', function($compile) {
return {
restrict: 'EA',
scope: {

@ -10,7 +10,7 @@
$.fn.sparkline.defaults.bar.barSpacing = 1;
$.fn.sparkline.defaults.bar.tooltipClassname = 'jqstooltip';
$.fn.sparkline.defaults.bar.tooltipOffsetX = 0;
$.fn.sparkline.defaults.bar.tooltipFormat = $.spformat('<div class="tooltip-arrow"></div><div class="tooltip-inner">{{prefix}}{{value}}{{suffix}}</div>');
$.fn.sparkline.defaults.bar.tooltipFormat = $.spformat('<div class="tooltip-arrow"></div><div class="tooltip-inner">{{prefix}}{{value}} {{suffix}}</div>');
$.fn.sparkline.defaults.bar.colorMap = $.range_map({
'0:5': '#10a0de',
'6:12': '#7bcc3a',

@ -92,14 +92,14 @@ block content
//- i.icon-time
span.small-title block time
//- span.small-value {{ avgBlockTime | avgTimeFilter }}
span.big-details.spark-blocktimes
sparkchart.big-details.spark-blocktimes(data="lastBlocksTime", tooltipsuffix="s")
div.col-xs-3.stat-holder
div.big-info.chart.text-info
//- i.icon-difficulty
span.small-title difficulty
//- span.small-value {{ lastDifficulty | number }}
span.big-details.spark-difficulty
sparkchart.big-details.spark-difficulty(data="difficultyChart")
div.col-xs-3.stat-holder.xpull-right
div.big-info.chart.xdouble-chart(class="{{ blockPropagationAvg | propagationAvgTimeClass : true }}")
@ -123,19 +123,19 @@ block content
span.small-title uncle count #[&nbsp;]
span.small (25 blocks per bar)
//- span.small-value {{ bestStats.block.uncles.length }}/{{ uncleCount }}
span.big-details.spark-uncles
sparkchart.big-details.spark-uncles(data="uncleCountChart")
div.col-xs-3.stat-holder
div.big-info.chart.text-info
//- i.icon-uncle
span.small-title transactions
span.big-details.spark-transactions
sparkchart.big-details.spark-transactions(data="transactionDensity")
div.col-xs-3.stat-holder
div.big-info.chart.text-info
//- i.icon-gasprice
span.small-title gas spending
span.big-details.spark-gasspending
sparkchart.big-details.spark-gasspending(data="gasSpending")
@ -209,5 +209,6 @@ block content
div.propagationBox
span {{node.stats.block.propagation | blockPropagationFilter}}
td.peerPropagationChart(class="{{node.id}}")
nodepropagchart(data="node.history")
td(class="{{ node.stats | propagationNodeAvgTimeClass : bestBlock }}") {{ node.stats | blockPropagationAvgFilter : bestBlock }}
td(class="{{ node.stats.uptime | upTimeClass : node.stats.active }}") {{ node.stats.uptime | upTimeFilter }}

Loading…
Cancel
Save