创建新图表时 nvd3 内存泄漏
nvd3 memory leak when creating a new chart
我从 google 图表 API 切换到 NVD3,我遇到了一些内存方面的大问题。该图表是根据从服务器获取的数据创建的,这些数据会根据传递的参数而变化。当参数改变时(通过点击图例文本触发),图表必须重新绘制,因为它可能有不同数量的数据线。
当第一次绘制图表时,一切都按预期工作(除了我将在后面描述的一个小(?)错误)。但是,更改参数后,图表会正确初始化,但在几次 AJAX 调用后,chrome 选项卡使用的内存在一秒钟内增加到 1.5 GB,并且选项卡冻结。发生时没有其他错误。
这可能是 nvd3 使用不正确的问题,因为传递给图形的数据似乎没问题。如果能帮我解决这个问题,我将不胜感激。
编辑:
我想我找到了问题所在,它可能是 nvd3 中的一些错误。当图表中绘制的所有数据线(至少两条)具有相同的数值数据时,就会发生这种情况。
在我的例子中,我从服务器获取温度读数,当无法正确获取读数时,温度设置为 -273。然后,当无法获得任何读数时,所有数据行就像常量函数 y=-273 一样,选项卡几乎立即耗尽 1.5gb 内存并冻结。但是,如果至少有一条使用稍微不同的数据构建的其他数据线,假设 y=-273.1 一切正常。
有人知道发生了什么事吗?
我提到的另一个问题是错误的:
Uncaught TypeError: Cannot read property 'each' of undefined nv.d3.js:5854
虽然好像对图表的生成没有什么影响
下面是我post代码的相关部分。
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;
});
一段时间后,我发现了问题所在。原来是nvd3库中voronoi的bug:
https://github.com/novus/nvd3/pull/448
在那个问题中提出了一个解决方案,这解决了我的巨大内存泄漏问题。事实证明,它的出现是由于地块的点位于相同的坐标。
我从 google 图表 API 切换到 NVD3,我遇到了一些内存方面的大问题。该图表是根据从服务器获取的数据创建的,这些数据会根据传递的参数而变化。当参数改变时(通过点击图例文本触发),图表必须重新绘制,因为它可能有不同数量的数据线。
当第一次绘制图表时,一切都按预期工作(除了我将在后面描述的一个小(?)错误)。但是,更改参数后,图表会正确初始化,但在几次 AJAX 调用后,chrome 选项卡使用的内存在一秒钟内增加到 1.5 GB,并且选项卡冻结。发生时没有其他错误。
这可能是 nvd3 使用不正确的问题,因为传递给图形的数据似乎没问题。如果能帮我解决这个问题,我将不胜感激。
编辑:
我想我找到了问题所在,它可能是 nvd3 中的一些错误。当图表中绘制的所有数据线(至少两条)具有相同的数值数据时,就会发生这种情况。
在我的例子中,我从服务器获取温度读数,当无法正确获取读数时,温度设置为 -273。然后,当无法获得任何读数时,所有数据行就像常量函数 y=-273 一样,选项卡几乎立即耗尽 1.5gb 内存并冻结。但是,如果至少有一条使用稍微不同的数据构建的其他数据线,假设 y=-273.1 一切正常。
有人知道发生了什么事吗?
我提到的另一个问题是错误的:
Uncaught TypeError: Cannot read property 'each' of undefined nv.d3.js:5854
虽然好像对图表的生成没有什么影响
下面是我post代码的相关部分。
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;
});
一段时间后,我发现了问题所在。原来是nvd3库中voronoi的bug:
https://github.com/novus/nvd3/pull/448
在那个问题中提出了一个解决方案,这解决了我的巨大内存泄漏问题。事实证明,它的出现是由于地块的点位于相同的坐标。