【问题标题】:Google Chart Constant Redrawing Memory Increase谷歌图表常量重绘内存增加
【发布时间】:2014-08-02 20:53:39
【问题描述】:

我每秒都会根据新数据重新绘制图表,它工作得很好并且看起来很棒,但我注意到它会增加内存,例如每秒 1 MB 的使用量。有任何解决这个问题的方法吗?我注意到如果我只有静态图表,那么内存就会稳定下来,但是一旦我添加了不断重绘(为了更新数据),内存使用就永远不会停止。

起初我以为是因为我每次都在创建一个新的图表实例,所以我更改了代码,所以每次只重绘同一个实例,但这并没有太大帮助。

有人知道怎么解决吗?我需要先以某种方式转储旧图表吗?

google.setOnLoadCallback(test);

var chart;
var chartOptions;
var chartCreate;

function test() {
    chart = new google.visualization.DataTable();
    chart.addColumn('string', 'Lorem');
    chart.addColumn('number', 'Ipsum');
    chart.addRows([
            ['', 0]
    ]);
    chartOptions = {};
    chartCreate = new google.visualization.LineChart(document.getElementById('chartDiv'));
          chartCreate.draw(chart, chartOptions);
    ]);
}

function test2() {
    chart.removeRows(0, 5);
    for (var i = 0; i < dataSpaceArray.length; ++i) {
        chart.addRow([dataTimeArray[i], dataSpaceArray[i], dataSpeedArray[i]]);
    }
        chartCreate.draw(chart, chartOptions);
}

setTimeout(test2,1000)

【问题讨论】:

  • 重绘时的内存泄漏是一个已知问题。据我所知,您对此无能为力。可视化 API 开发团队知道并正在研究它。
  • 你有这方面的资料吗?这看起来很奇怪,这几乎意味着您无法更新图表中的数据。
  • 仅供参考,最新的候选发布版本(加载 v1.1 而不是 v1)包含一些内存泄漏问题的修复。
  • 调用google.load('visualization', '1', {packages: [/* packages list */], callback: drawChart});时,将1替换为1.1
  • 好的,谢谢!对于 1.1,泄漏(如果有)可以忽略不计。不过总体消耗更高(从 ~7MB 到 ~15MB)。在 pc 上工作,但在 Raspberry Pi 上非常缓慢(另一个故事:-)。你应该认为 1.1 是这个问题的一个很好的答案!

标签: javascript google-visualization


【解决方案1】:

我已经通过全局存储图表解决了这个问题。在绘制图表之前,您需要检查图表是否已经实例化。如果没有,创建新的图表对象,否则在绘制之前调用 clearChart() 方法。像这样:

//Store all chart objects in a global array to avoid memory leak
var charts = [];

function drawChart(chartName, element, data, chartOptions) {
   if (charts[chartName] === undefined || charts[chartName] === null) {
          charts[chartName] = new google.visualization.LineChart(group);
   } else {
          charts[chartName].clearChart();
   }
   charts[chartName].draw(dataTable, chartOptions);
}

【讨论】:

  • 确认这是可行的,但在 clearChart 之后我不得不再次实例化 - new google.visualization.LineChart(group);
【解决方案2】:

有同样的问题,可以通过在 Google 的 clearChart() 函数中添加几行来解决它。

W.clearChart = function() {

    //this fixes the leak
    hv = {};
    iv = {};
    jv = {};

    ...
};

更多详情:

  1. 这是我对其进行更改的 Google 文件:

https://www.google.com/uds/api/visualization/1.0/4086f2e8fc632adc52e6d6795a5637a4/format+en,default,corechart.I.js

  1. 下载此文件,进行上述更改。在您的代码中,添加一个脚本标签以从您的网络服务器加载上述文件并注释掉以下行:

    // google.load('visualization', '1', { packages: ['corechart'] });

  2. 内存会增加,但几分钟后会自行恢复。

  3. 我正在使用 clearChart(),但如果您不想清除图表,请创建自己的函数(例如 memoryLeakFix())并定期调用它。

  4. 这是一个测试页面(1.js 是第 1 步修改后的文件)。它基本上创建新图表并每 100 毫秒重绘一次。您会看到内存增加,但点击“停止”链接停止重绘并等待几分钟,内存就会减少。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js"      type="text/javascript"></script>
  <script src="https://www.google.com/jsapi"                                          type="text/javascript"></script>

  <script src="1.js"                                          type="text/javascript"></script>


  <script type="text/javascript">

      //init google charts
//        google.load('visualization', '1', { packages: ['corechart'] });
      google.load('visualization', '1', { packages: ['table'] });

  </script>


</head>
<body>

<a href='#' onclick='stop()'>Stop</a>
  <div class='chart'></div>

  <script>

      var chart; var table;

      function createChart(container)
      {
          if(chart != undefined)
              chart.clearChart();

          //init chart
          chart = new google.visualization.LineChart(container[0]);

          //init chart data
          if(table == undefined)
          {
              table = new google.visualization.DataTable();

              table.addColumn('datetime', 'Time');
              table.addColumn('number', 'Value');

              var count = 0;

              //periodically add rows
              setInterval(function()
              {
                  //add row
                  table.addRows([ [new Date(), count++]]);    
              }, 1000);


          }
      }


      //start redrawing
      var id = setInterval(function()
      {
          createChart($('.chart'));

          drawChart();
      }, 100);

      //stop redrawing
      function stop()
      {
          clearInterval(id);
      }

      //draw chart
      function drawChart()
      {
          chart.draw(table, { curveType: "function",

              width:      250, 
              height:     250,
              pointSize:  1,
              legend:     { position: 'none' },
              chartArea: { 'width': '90%', left: 50 },
          });
      }

  </script>   
</body>
</html>

【讨论】:

  • 我可以看到你令人印象深刻的 hack 可以避免一些内存泄漏。但人们应该意识到,这会在几个方面变得脆弱。当与其他重用图表的方式一起使用时,尤其是在仪表板中,可能会出现复杂情况。此外,当创建新版本的库时,类和内部变量的编译名称可能会有所不同。但希望新版本能够修复这些内存泄漏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-02
  • 2017-10-09
  • 1970-01-01
  • 2018-06-08
  • 1970-01-01
  • 2019-02-20
  • 1970-01-01
相关资源
最近更新 更多