I switched from google charts API to NVD3 and I am getting some huge problems with memory. The chart is created from the data acquired from the server, which changes depending on the passed parameters. When the parameters change (triggered by clicks on legend texts), the chart has to be redrawn as it may have different number of data lines.
When the chart is drawn for the first time, everything works as expected (apart from one minor(?) error which I will describe later). However, after the parameters are changed, the chart initializes correctly, but after a few AJAX calls, the memory used by the chrome tab increases in a second to 1.5 GB and the tab freezes. There are no other errors when it happens.
It's probably an issue of incorrect nvd3 usage as the data passed to the graph seems to be all right. I would really appreciate some help in resolving this problem.
Edit:
I think I located the problem and it might be some bug in nvd3. It happens when all the data lines (at least two) that are plotted in the chart have the same numerical data.
In my case, I am getting temperature readings from the server and when the readings could not be correctly obtained the temperature is set to -273 for example. Then, when no readings could be obtained, all the data lines are like constant function y=-273 and the tab almost instantly eats up 1.5gb of memory and freezes. But if there is at least one other data line built using even a bit different data let's say y=-273.1 everything works ok.
Does anybody have a clue what's going on?
The other problem I mentioned is an error:
Uncaught TypeError: Cannot read property 'each' of undefined nv.d3.js:5854
although it doesn't seem to have any effect on the generation of the chart.
Below I post the relevant part of code.
var chart;
var dataSet = [];
var initialized = false;
function collectD3Data() {
$.ajax({
type: 'GET',
url: '/chartdata',
data: {
// some parameters to get different data from server
},
success: function(response) {
console.log(initialized + " " + response);
if(!initialized){
dataSet = [];
}
for(var j = 0; j < response[0].temperatures.length; j++){
var values = [];
for(var i = 0; i < response.length; i++) {
var obj = {
"x": new Date(response[i].date),
"y": parseFloat(response[i].temperatures[j])
};
values.push(obj);
}
if(!initialized) {
values = values.slice((values.length - 50 > 0) ? values.length - 50 : 0 , values.length);
dataSet.push({"key":"series " + j, "area":false, "values":values});
}
else {
dataSet[j].values.push(values[0]);
if(dataSet[j].values.length > 50) {
dataSet[j].values.shift();
}
}
}
if(!initialized) {
nv.addGraph(addMyChart(dataSet));
}
chart.update();
initialized = true;
window.setTimeout(collectD3Data, 1000);
},
error: function(x, t, m) {
console.log("Some ajax error...");
window.setTimeout(collectD3Data, 1000);
}
});
}
function addMyChart()
{
chart = nv.models.lineWithFocusChart();
chart.xAxis.tickFormat(function(d) { return d3.time.format('%X')(new Date(d)); });
chart.x2Axis.tickFormat(function(d) { return d3.time.format('%X')(new Date(d)); });
chart.yAxis.tickFormat(d3.format(',.2f'));
chart.y2Axis.tickFormat(d3.format(',.2f'));
d3.select('#chart svg')
.datum(dataSet)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
}
$("svg").on('click', 'g.nv-legend g.nv-series text', function(){
initialized = false;
});
After some time, I found the problem. It turned out to be a bug with voronoi in nvd3 library:
https://github.com/novus/nvd3/pull/448
A solution was proposed in that issue and this solved my problem with that giant memory leak. It turned out that it appeared as a result of having points of the plots at the same coordinates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With