我对 javascript 还很陌生,我无法在某些代码中找到内存泄漏,这些代码每秒都会使用 ajax 数据更新一个谷歌图表。
我的代码(简化为一个小测试用例):
function TimeLine(id, max) {
this.chart = new google.visualization.LineChart(document.getElementById(id));
this.vals = new google.visualization.DataTable();
this.vals.addColumn('number', 'Index');
for (var i = 2; i < arguments.length; i++) {
this.vals.addColumn('number', arguments[i]);
}
this.numCols = arguments.length - 2;
this.max = max;
this.index = 0;
this.resourceOptions = {
'title': 'Memory allocation',
'width': 360,
'height': 300
};
}
TimeLine.prototype.Add = function () {
if (this.vals.getNumberOfRows() > this.max) {
this.vals.removeRow(0);
}
var row = [this.index];
for (var i = 0; i < arguments.length; i++) {
row.push(arguments[i]);
}
this.vals.addRow(row);
this.chart.draw(this.vals, this.options);
this.index++;
};
function onLoad() {
window.Timeline = new TimeLine('gauges', 15, 'Alloc');
drawCharts();
}
function drawCharts() {
window.Timeline.Add(window.Timeline.index%3);
setTimeout(drawCharts, 1000);
}
google.load('visualization', '1.0', {
'packages': ['corechart']
});
google.setOnLoadCallback(onLoad);
我在 64 位 Ubuntu 上使用 chrome 版本 29.0.1547.62。
我将图表包装在一个对象中(希望)让我更容易推理范围和垃圾收集,因为我不太习惯 JS 范围规则。我在 SO 上看到了很多类似的问题,但据我所知,我的代码不应该产生泄漏。使用内存时间线,我可以看到每次调用 drawCharts 时内存都在攀升,并且大部分内存似乎是 gc'd,但大约一个小时后,该选项卡的内存高达 300 MB,并且它一直在攀升,直到标签崩溃。目标是能够长时间保持此选项卡作为监视系统,以监控我们其中一台服务器上的当前负载,但目前我只能保持它几个小时,然后它就会被杀死。
我尝试在配置文件选项卡中使用堆快照,如果我在几次调用 drawCharts 之前和之后比较快照,似乎泄漏的对象是图表本身的 SVG 元素,但我可能错误地解释了这些结果。
我已经重现了这个问题:
大约 20 分钟后,chrome 中的 about:memory 页面将开始显示对我来说大约 150 MB 的高内存消耗。通过将 setTimeout 缩短为 100 毫秒,可以更快地看到这种效果。
编辑:固定内存使用统计