Marionette と requirejs を使用して作成されたダッシュボード Web アプリがあります。このアプリでは、Google ビジュアライゼーション API を使用してチャートを生成します。開発を開始してしばらくすると、メモリ リークが発生していることに気付きました。Chrome Canary のタスク マネージャーでは、グラフが描画および削除されるとメモリが増加するのがわかります。メモリが減少することはありません。増加するだけです。いくつかのヒープ スナップショットを取り、分離された dom ツリーが多数あることを確認しました。これらはすべて、svg 要素やその他の生成されたチャートを参照しています。
現在、私のビューとサブビューの残りは、マリオネット固有のメソッドによってクリーンアップされており、残っているのは、これらのチャートから切り離された dom 要素だけです。
チャートを含むビューの onClose メソッドにいくつかのクリーンアップ コードを実装しようとしました。
- google の clearChart メソッド
- html ノードでの jquery empty() および remove()
- JavaScriptの削除機能
分離された dom ツリーが表示され続け、メモリが増加し続けるため、この継ぎ目はどれも役に立ちません。
誰もこの問題に直面しましたか?
編集
チャート ビューのソース コードは次のとおりです。
define(['jquery', 'underscore', 'backbone', 'dispatchers/event-dispatcher', 'utils/utils', 'utils/chart-utils', 'goog!visualization,1,packages:[corechart], matchMedia'], function($, _, Backbone, eventDispatcher, utils, chartUtils) {
'use strict';
var MallKPIChart = Marionette.ItemView.extend({
template: _.template('<div></div>'),
onShow: function() {
var self = this;
self.$el.height(self.$el.width() / 2.5);
var data = self.options.data;
var range = self.options.range;
var chartData = new google.visualization.DataTable();
chartData.addColumn('string', 'date');
chartData.addColumn('number', 'Visits');
chartData.addColumn('number', 'Average Visits');
$.each(data['data'], function(i, object) {
var row = [utils.timeConverter(parseInt(object['timestamp'], 10) / 1000, range), object['count'], data['average']];
chartData.addRow(row);
});
var titleFontSize, pointSize, lineWidth, fontSize;
if (window.matchMedia('all and (max-width: 1024px)').matches) {
titleFontSize = 10;
pointSize = 1;
lineWidth = 0.8;
fontSize = 8;
} else {
titleFontSize = 15;
pointSize = 4;
lineWidth = 2;
fontSize = 10;
}
var options = {
title: self.options.title,
titleTextStyle: {
color: '#747474',
fontName: '"Open Sans"',
fontSize: titleFontSize
},
fontSize: fontSize,
chartArea: {
'width': '78%',
'height': '58%',
'left': '12%'
},
colors: ['#E87013'],
backgroundColor: 'transparent',
areaOpacity: 0.25,
animation: {
duration: 1000,
easing: 'out',
},
pointSize: pointSize,
lineWidth: lineWidth,
hAxis: {
format: 'd/MM/y',
textPosition: 'out',
baselineColor: '#747474',
gridlines: {
color: '#efeeed'
},
textStyle: {
color: '#747474'
},
maxTextLines: 1
},
vAxis: {
textPosition: 'out',
textStyle: {
color: '#747474'
},
baselineColor: '#747474',
gridlines: {
color: '#efeeed'
},
maxValue: self.options.max,
minValue: 0
},
series: {
1: {
type: 'line',
color: '#DE309C',
pointSize: 0,
lineWidth: lineWidth
}
},
legend: {
position: 'top',
alignment: 'end'
},
curveType: 'function'
};
self.chart = new google.visualization.AreaChart(self.$el[0]);
self.chart.draw(chartData, options);
return self;
},
onClose: function() {
var self = this;
self.chart.clearChart();
self.chart = null;
},
});
return MallKPIChart;
});
チャート インスタンスが初期化され、次のように marionette.layout 領域に表示されます。
self.visitsChart.show(new MallKPIChart({
title: 'SHOPPING CENTRE VISITS',
data: self.mallKPI.get('captures'),
range: self.range
}));
そして、これは分離された svg 要素を含むヒープ スナップショットのスクリーンショットです (ビューを閉じたり開いたりすると、スナップショットのサイズが大きくなります)