JavaScriptのメモリ消費について

0 件のコメント
今回は、メモ書き...

テーマはJavaScriptのメモリ消費についてです。

JavaScriptのメモリモデルはガベージコレクションという技術を用いています。
この手法は、ガベージコレクター(以下、GC)が最適と判断したタイミングでメモリの開放を行います。

問題点としては、下記があげられます。
・タイミングが制御できない
・GCの処理中は、プログラムが利用可能な処理時間を奪う

要は、メモリ消費が大きいWebアプリはGCが頻発し、パフォーマンス劣化に繋がるよってこと。

GCの頻度はどうやって確認する?

下記の画像は、YahooのトップページをDeveloper ToolsのTimelineタブでレコーディングしたものです。
山になっている水色部分がメモリの使用量で、一回ガクッと下がっています。
これがGCのタイミングで、ギザギザになってるほどGCの頻度が高いです。
(「バージョン 39.0.2159.0 canary (64-bit)」の画面です。)
図1. Developer ToolsのTimeline
ちゃんと確認したいのであれば、「GC」でフィルタするとことによっていつGCが発生したのかが確認できます。
図2. Developer ToolsのTimeline

GCの対象は?

JavaScript内ではすべての値がオブジェクトグラフに属しており、グラフにはルートが存在します。
そのルートからの参照がなくなった時点で、値はガベージコレクションの対象になります。

(そして、GCの処理中はオブジェクトグラフがルートから順に走査される間はページのスクリプト実行は中断されるって感じになる。)

GCの頻度を下げるにはどうしたらいいか?


  • メモリリークについて理解する

これについては説明が長くなりそうなので、下記の記事が非常に参考になります。
要は、不必要なクロージャに使用を避ける&循環参照を避けるってことがポイント。

【JavaScript】メモリの浪費を避けるコーディング
http://utage.headwaters.co.jp/blog/?p=1116

JavaScript アプリケーションのメモリー・リークを理解する
http://www.ibm.com/developerworks/jp/web/library/wa-jsmemory/


  • 大量のオブジェクトを作成/破棄することをなるべくしないようにすればよい

スタティックメモリJavaScriptというテクニック
(があるらしい。こういう実装したことないので知識だけ書いておきます。)

1. 同じ型を持つオブジェクトを必要な分だけセットして保持しておく、オブジェクトプールと呼ばれるものを作る。
2. 新しいオブジェクトが必要となった場合、システムのヒープメモリから取ってくるのではなく、プール内の使用されていないオブジェクトを再利用する。
3. 不要になったオブジェクトは、メインメモリではなくプールに返却する。

つまり、最初にオブジェクトをゴソッと作って、必要な場合はゴソッと作った中のものを使う。

【メリット】
フレーム毎に生成/破棄されるオブジェクトの数を必要最低限に抑えることができる

【デメリット】
初期化時の挙動が重い
メモリをあまり使用していないときも、使用メモリ量は減らない

(その他..)
また、
'hoge'.slice() とか 'hoge'.substr() とか非破壊関数は新しく配列・文字列を作って返すので注意すべし。

終わりに

ここに書いたことは、
担当している案件で動作が遅いとか、パフォーマンスチューニングして?って言われたときに気にするポイントの1つです。

ネットワーク部分以外のチューニングとしては、他に描画処理のパフォーマンスチューニングやJavaScriptのコード最適化(JSXみたいな)などがあります。
今後記事にできたらいいなーと思います。

以上!

参考

オブジェクトプールを使った静的メモリ JavaScript
http://www.html5rocks.com/ja/tutorials/speed/static-mem-pools/

Gmail スケールの効率的メモリ管理術
http://www.html5rocks.com/ja/tutorials/memory/effectivemanagement/

0 件のコメント :

コメントを投稿