15

Situation: I'm working on a pretty decently complex single page Backbone app that could potentially be running for 8-12+ hours straight. Because of this, there's a need to ensure that the application won't leak and have a reputation for crashing after X hours or slow down dramatically.

The Application: The app is built on Backbone (mv*), Zepto (similar to jquery), Curl (amd loader) & Mustache (templating).

Problem: I've just conquered the event listeners. The garbage collector seems to be doing a fine job cleaning these guys up, but the DOM Node Count won't stop climbing.

Questions:

  • Is there a proper way to dispose of DOM Nodes so that they will be properly garbage collected, or is this DOM Node Count a running total that will never decrease?
  • Does anybody know of any of these frameworks to poorly handle DOM Nodes? Possibly Mustache?
  • Is the DOM Node Count even a reliable figure?

I'm really just looking for a head start on my adventure to stop these DOM Nodes from rising. Any help or guidance would be greatly appreciated (and accordingly upvoted).

I assumed that once the event listeners were properly disposed of that the DOM Node Count would just manage itself, but this doesn't seem to be the case.

Tests


Poorly Managed DOM Node Count

  • First Test: 6.8 minutes, 110,000 DOM Nodes

Edit: Without the Timeline recording, I reran the same script to randomly mash links and took a screenshot at around the 7 minute mark. After GC came through I had these results.

Poorly Managed DOM Node Count

  • Second Test: 7.1 minutes, 141,000 DOM Nodes (Without the timeline recording)

Edit: After Fix:

DOM Node Count under control After Upgrade Backbone and using listenTo and stopListening everywhere

  • 7 minutes: 6,926 DOM Nodes (see marked answer below).
  • 20 minutes: 6,000 DOM Nodes, 20 Event Listeners, Memory 20 MB.
  • 25 minutes: 11,600 DOM Nodes, 44 Listeners, Memory 21.7 MB.
  • 28 minutes: 9,000 DOM Nodes, 22 Event Listeners, Memory 21.7 MB.
  • 30 minutes: 13,700 DOM Nodes, 123 Event Listeners, Memory 21.7.
  • 31 minutes: 7,040 DOM Nodes, 30 Listeners, Memory 21.7.
4

4 に答える 4

6

修正されました!- バックボーンをアップグレード。(読み続けて)

Backbone 0.9.2 から Backbone 0.9.10 にアップグレードし、すべてのビュー/モデル/コレクションに listenTo と stopListening を実装しました。結果は OMGFANTASTIC です。

同じストレス テストを 7 分間実行した後の結果は次のとおりです。 ここに画像の説明を入力

結果: 7.0 分、6,926 DOM ノード (タイムライン記録なし)、イベント リスナー数はBLUE BLADES OF GRASSのように見えます。私はショックを受けています。メモリ使用量も、以前のテストと比較して驚くほど低くなっています。

18 分後: イベント リスナー数は同じで、154 を超えることはなく、DOM ノード数は常に 25,000 未満のままです。明らかにいくつかの機能がすり抜けています (まだ使用されているバックボーン以外のコンポーネントがいくつかあります) が、その改善は驚くべきものです。

結論: このバージョンの Backbone が登場する前は、Backbone 自体のリスナーのクリーンアップがうまくいきませんでした。DOM へのリスナーは正常に処理されましたが、モデル/ビュー/コレクション間では処理されませんでした。関連するコールバックの多くはバックボーン ビューに関連付けられていたため、ガベージ コレクターが DOM ノードを解放できなかったと推測されます。Backbone 内の多数のばらばらなイベント リスナー/コールバック (DOM へのバインディングだけではない) は、ガベージ コレクションできない多数のばらばらな DOM ノードを作成します。

これが Backbone をアップグレードする十分な理由ではない場合、私には何が何なのかわかりません ;o

于 2013-03-13T00:38:28.893 に答える
3

DOM ノード数の増加は、(通常はページのコードで) メモリ リークの主な兆候です。だからあなたはそれに対して戦う必要があります。標準的な手法は、この質問への回答で説明されています。

スナップショット コンテンツの詳細が多すぎます。そして、この 3 つのスナップショット スキーマは、スナップショットの重要でない部分を除外し、リークの候補のみを表示するのに役立ちます。

Chrome Canary など、最新バージョンの Chrome を実行していることを確認してください。拡張機能のない単一のタブを持つ新しいインスタンスである必要があります。コンソールにエラー メッセージが表示されず、ブレークポイントも表示されず、例外で停止しないと便利です。これらのすべてがページに影響を与え、結果としてスナップショットのコンテンツに影響を与える可能性があるからです。

この投稿はあなたにとっても興味深いかもしれません。

于 2013-02-28T05:47:14.383 に答える
0

ジャンクを避ける別の方法を見つけた

render: function() {
  this.$el.empty();
  var container = document.createDocumentFragment();
  // render each subview, appending to our root element
  _.each(this._views, function(subview) {
     container.appendChild(subview.render().el)
  });
  this.$el.append(container);
}

ここを参照してくださいhttp://ozkatz.github.io/voiding-common-backbonejs-pitfalls.html

于 2014-01-24T02:19:45.257 に答える