JavaScriptにおいてメモリ管理は基本的にエンジン任せなのであまり意識することは無いかもしれませんが、メモリリークの調査やパフォーマンスの実験のためにメモリ情報をJavaScriptから扱いたいときがあると思います。

<!--more-->メモリリーク調査は専用のソフトウェアなどがあるので、

そちらを使うのでもいいかもしれませんが、new Dateを使った実行時間の記録みたいにJavaScript内からメモリ情報を取得して計測できるとおもしろいと思うので、ブラウザ毎にやる方法を調べてみました。

調べてみるとWebkit系ブラウザ(Chromeとsafari)はデバッグモード時にJavaScriptからメモリ情報を取得する方法がありました。

Webkit系

Chrome、safari両方ともデフォルトではメモリ情報を扱うことはできないので起動オプションを設定する必要があります。
Chromeの場合は起動引数に–enable-memory-infoというオプションをつけることで有効になります。

* Linux: /opt/google/chrome/google-chrome --enable-memory-info
* Windows XP:  "C:Documents and Settings<ユーザー名>LocalSettingsApplicationDataGoogleChromeApplicationchrome.exe"  --enable-memory-info
* Windows Vista以降: "C:Users<ユーザー名>AppDataLocalGoogleChromeApplicationchrome.exe"  --enable-memory-info
* MacOS: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --enable-memory-info

safariの場合はplistの設定を変えることで同じく有効にできるそうですが、Windows版はよくわからないのとMac持ってないので確かめていません。

MacOS: Open ~/Library/Preferences/com.apple.Safari.plist file for editing, and add & set enabled a boolean preference WebKitMemoryInfoEnabled (pic)

mrdoob/stats.js – GitHub

使い方

上記のようにmemory-infoの機能を有効にした状態で、JavaScriptからwindow.webkitPerformance.memory.usedJSHeapSizeなどを取得するとヒープメモリの情報が返ってくるようになります。(無効の場合は常に0が返ってくるようです)
コンソールからもwindow.webkitPerformance.memory.usedJSHeapSizeとかたたけば値が返ってくると思います。
(console.memoryでも一応可能)

window.webkitPerformance.memory [object MemoryInfo]
window.webkitPerformance.memory.usedJSHeapSize
window.webkitPerformance.memory.totalJSHeapSize

使い方の例

(function() {
    if (webkitPerformance && webkitPerformance.memory.usedJSHeapSize) {
        console.log("==Start==",
                "used : " + webkitPerformance.memory.usedJSHeapSize,
                "total : " + window.webkitPerformance.memory.totalJSHeapSize);
        var res1 = [],res2 = [];
        var start = webkitPerformance.memory.usedJSHeapSize;
        for (var i = 0; i < 1000; i++) {
            res1[i] = new Date().getTime();
        }
        console.log("new Date : ", webkitPerformance.memory.usedJSHeapSize - start);
        var start2 = webkitPerformance.memory.usedJSHeapSize;
        for (var i = 0; i < 1000; i++) {
            res2[i] = Date.now();
        }
        console.log("Date.now : ", webkitPerformance.memory.usedJSHeapSize - start2);
        console.log("==END==",
                "used : " + webkitPerformance.memory.usedJSHeapSize,
                "total : " + window.webkitPerformance.memory.totalJSHeapSize);
    }
})();

歴史的背景 – 余談

上で見てるとわかりますが、memory InfoはwebkitPerformanceオブジェクト、つまりTiming APIなどが入ってるところに実装されています。しかし、Web Performance Working Groupを見てもメモリ情報については書いてありません。(見つからなかった)

いつ実装されたのかを探すと、[webkit-dev] On adding ‘console.memory’ API (and about the whole ‘consolというメーリングリストで追加されたのが告知されていました。
このときはconsole.memoryとなっていて、webkitPerformance以下ではなくconsole以下に実装されていたようです。
なので現在はconsole.memoryとwindow.webkitPerformance.memoryのどちらの方法でも参照できるようです。
そして、わざわざwebkitPerformanceに移してるので、Web Timing APIの一部としてやってくのかもしれません。
(memory Infoの話はstats.jsの作者が詳しそう)

Firefox

Webkit系では実装として載っているのでいいのですが、Firefoxでも似たような事はできないかと探してみたところFirefoxプロセスのメモリ情報はXPCOMで取得できるようだったので、content(いわゆる普通のWebサイト内)でもその情報を扱えるようにするuserChrome.jsを書いてみました。(uc :: Add-ons for FirefoxなどuserChromeを実行できるアドオンを入れてからインストール)
コードは584.js(ucjs_MemoryMonitor.uc.js) – Firefox用スクリプトアップローダー(新)を参考にしました。

ただし、このスクリプトはセキュリティ的に問題ありまくりなので、通常のプロファイルで使うのはやめておいた方がいいですよ。

このuserChrome.jsをインストールした状態で、window.getMemoryInfo()とすると

{
    "mapped": mapped,
    "allocated": allocated,
    "committed": committed,
    "dirty": dirty
}

上のようなメモリ情報のオブジェクトが返ってくるようになります。おそらくこのメモリ情報はFirefoxのプロセス全体としてのものなので、webkitPerformance.memoryとは意味が異なるため同一視してはいけないと思います。
恐らくabout:memoryに載っているメモリ情報と同じだと思うので、about:memoryが実装されたFirefox3.6から使えるものかもしれない。
このスクリプトはcontent権限からChrome権限(何でもできる特権)のコードを呼んでいるので、逆を言えばこれを悪意ある方法でついてしまえばChrome権限で何でもされてしまうのでデバッグ専用のプロファイルなどで使用して、信頼できるサイト内だけで使ってください。(もっと詳しい方が安全な実装してくれればいいのですが…)

以上でJavaScriptからメモリ情報を扱う方法の紹介は終わります。
他のブラウザor方法でもできるやり方があったら教えてください。JavaScript Advent Calendar 26日目の記事でした。

gist: 754908 – メモリ情報をcontentスコープから取得できるように拡張- GitHub : https://gist.github.com/754908

mrdoob/stats.js – GitHub : https://github.com/mrdoob/stats.js