Memory leak in google line charts

2019-03-01 08:38发布

问题:

I have been doing lot research on this memory leak in Google charts library. Didnt found any thing thats helping my situation. Not sure whats the updates on this one so far. I saw google chart dev team is trying to fix it and release a new updates.

I'm using line chart and the data is coming from websockets. which is constantly updating.

Thanks in advance

P.S below is the code I use to getting data from websockets. when the socket is connected the drawChart function is called every second. Meaning the whole line chart is redrawn

function drawVisualization() {

        var data = new google.visualization.DataTable();
        data.addColumn('string', 'data');
        data.addColumn('number', 'date');

        var data_test = new google.visualization.DataTable();
        data_test.addColumn('string', 'data test');
        data_test.addColumn('number', 'date test');

        for(var i=0; i<valueArr.length; i+=2) {

          if (i>=120) {
            data.removeRow(0);
            valueArr.splice(0, 2);
            timeArr.splice(0, 2);
          }

          data.addRow([timeArr[i], valueArr[i]]);
        }

        for(var i=1; i<valueArr.length; i+=2) {

            if (i>=120) {
              data_test.removeRow(0);
              valueArr.splice(0, 2);
              timeArr.splice(0, 2);
            }

            data_test.addRow([timeArr[i], valueArr[i]]);
        }

        //console.log(valueArr);
        // use a DataView to 0-out all the values in the data set for the initial draw
        var view = new google.visualization.DataView(data);
        var view_test = new google.visualization.DataView(data_test);

        // Create and draw the plot
        var chart = new google.visualization.LineChart(document.getElementById('visualization'));
        var chart_test = new google.visualization.LineChart(document.getElementById('visualization_test'));

        var options = {
            title:" ",
            width: 960,
            height: 460,
            bar: { groupWidth: "40%" },
            legend: { position: "bottom" },
            animation: {"startup": true},
            curveType: 'function',
            lineWidth: 3,
            backgroundColor: '#f9f9f9',
            colors: ['red'],
            tooltip: {
                textStyle: {
                  color: 'red',
                  italic: true
                },
                showColorCode: true
            },
            animation: {
                startup: true,
                easing: 'inAndOut',
                //duration: 500
            },
            vAxis: {
                title: '',
                gridlines: {
                  count: 8,
                  color: '#999'
                }
                /*minValue: 1.3,
                maxValue: 1.4*/
            },
            hAxis: {
              title: 'Time Stamp'
            },
        };

        //stay in sockets
        var runOnce = google.visualization.events.addListener(chart, 'ready', function () {
            google.visualization.events.removeListener(runOnce);
            chart.draw(data, options);
            chart_test.draw(data, options);
        });

        chart.draw(view, options);
        chart_test.draw(view_test, options);
}

function init() {
try {
    socket = new WebSocket(portal);
    //console.log('WebSocket status '+socket.readyState);
    socket.onopen = function(msg) {
        //console.log("Welcome - status "+this.readyState);
    };


    socket.onmessage = function(msg) {
        parseData(msg);
        drawVisualization();

    };

    socket.onclose = function(msg) {
        console.log("Disconnected - status "+this.readyState);
    };
}
catch(ex){
    console.log(ex);
}
}

回答1:

beginning with drawing only one chart, you might setup similar to following snippet...

this should draw the same chart with new data, only after the previous draw has finished...

function init() {
  var getData = true;

  var chart = new google.visualization.LineChart(document.getElementById('visualization'));
  google.visualization.events.addListener(chart, 'ready', function () {
    getData = true;
  });

  var options = {
    title:" ",
    width: 960,
    height: 460,
    bar: { groupWidth: "40%" },
    legend: { position: "bottom" },
    animation: {"startup": true},
    curveType: 'function',
    lineWidth: 3,
    backgroundColor: '#f9f9f9',
    colors: ['red'],
    tooltip: {
      textStyle: {
        color: 'red',
        italic: true
      },
      showColorCode: true
    },
    animation: {
      startup: true,
      easing: 'inAndOut',
      //duration: 500
    },
    vAxis: {
      title: '',
      gridlines: {
        count: 8,
        color: '#999'
      }
      /*minValue: 1.3,
      maxValue: 1.4*/
    },
    hAxis: {
      title: 'Time Stamp'
    },
  };

  // if you want data from previous draws, declare here...
  var data = new google.visualization.DataTable();
  data.addColumn('string', 'Time');
  data.addColumn('number', 'Value');
  // or see below...

  // msg = object with arrays from parseData
  function drawVisualization(msg) {

    // if you ** don't ** want data from previous draws, declare here instead...
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Time');
    data.addColumn('number', 'Value');
    // ---<

    for (var i = 0; i < msg.valueArr.length; i++) {
      data.addRow([msg.timeArr[i], msg.valueArr[i]]);
    }

    chart.draw(data, options);
  }

  function parseData(msg) {
    //... declare timeArr & valueArr locally here

    return {
      timeArr: timeArr,
      valueArr: valueArr
    };
  }

  function startData() {
    try {
      socket = new WebSocket(portal);
      //console.log('WebSocket status '+socket.readyState);

      socket.onopen = function(msg) {
        //console.log("Welcome - status "+this.readyState);
      };

      socket.onmessage = function(msg) {
        if (getData) {
          getData = false;

          // pass object with arrays from parseData
          drawVisualization(parseData(msg));
        }
      };

      socket.onclose = function(msg) {
        //console.log("Disconnected - status "+this.readyState);
      };
    }
    catch(ex){
      console.log(ex);
    }
  }
  startData();
}