JavaScriptのprototypeとメモリ 本当にメモリ節約してるのか見てみた


今回はJavaScriptのprototypeとメモリを見るプロファイラの話です。

JavaScriptはまだまだ経験が浅いので上記の2つの要素はどちらも慣れていません。流石にまずいと思うので、少し触ってみることに。今回はプロファイラを使ってprototypeで本当にメモリ節約になっているかを確認することがゴールです。

サンプルコード

// Person class
function Person(name){
  this.name = name;
  this.data = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...'; //すごく長い文字列
  this.introduceOneself = function(){
    console.log('Hi! My name is ' + this.name + '.');
  }
}

// PersonWithPrototype class
function PersonWithPrototype(name){
  this.name = name;
}
PersonWithPrototype.prototype.data = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...'; //すごく長い文字列
PersonWithPrototype.prototype.introduceOneself = function(){
  console.log('Hi! My name is ' + this.name + '.');
};

// Global object
var personArray = [];
var personWithPrototypeArray = [];

function someAction() {
  for(var i=0; i<100; i++){
    // Create object via Constructor.
    var p = new Person('name' + i);
    personArray.push(p);

    var pwp = new PersonWithPrototype('name' + i);
    personWithPrototypeArray.push(pwp);
  }
}

上記をapp.jsとして保存して、後は適当なHTMLでscriptタグで読み込み、onClickとかでsomeAction()を実行するようにすれば準備完了です。

someAction()が実行されたとき、PersonとPersonWithPrototypeが同じ数だけnewされます。

Chromeのプロファイラで見てみる

ツール -> デベロッパーツール を開きます。

chorome_developertools

まずはページにアクセスしてボタンを押してオブジェクトを生成します。次に以下の画面のようにProfilesからTake Heap Snapshotを選択して、Take Snapshotボタンを押します。

profiles

すると以下のように結果が出るので、検索ボックスに今回みたいPersonと入力するとお目当てのものが出ます。

profile_result

出ました!Retained Sizeの部分を見ると、prototypeを利用していないPersonの方がメモリを消費していることが分かります。実際にもっと細かく見ていくとPersonの中身は@番号がバラバラですが、PersonWithPrototypeの中身の__proto__は@番号がどれも同じです。同じオブジェクトを参照しているのでメモリ消費が少ないという訳ですね。

他にも色々機能はありますが、大体jvisualvmと同じような感じでした。これからはJavaScript開発でもじゃんじゃんプロファイラを使っていきたいと思います!

prototypeも別に文法が難しいわけでも無いし、ひな形的な用途だと分かってしまえば簡単ですね。こちらも正しく使いこなしてJavaScript中級者へ成長していきたいです。