创建新图表时nvd3内存泄漏

时间:2015-04-13 19:54:55

标签: javascript d3.js memory-leaks nvd3.js linechart

我从谷歌图表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

虽然它似乎对图表的生成没有任何影响。

下面我发布相关的代码部分。

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;
});

1 个答案:

答案 0 :(得分:0)

过了一段时间,我发现了问题。原来这是nvd3库中voronoi的一个错误:

https://github.com/novus/nvd3/pull/448

在该问题中提出了一个解决方案,这解决了我的巨大内存泄漏问题。事实证明,这是因为在相同的坐标处得到了图的点。