384

JavaScriptオブジェクトが占めるサイズを知りたい。

次の機能を実行します。

function Marks(){
  this.maxMarks = 100;
}

function Student(){
  this.firstName = "firstName";
  this.lastName = "lastName";
  this.marks = new Marks();
}

今、私はインスタンス化しますstudent

var stud = new Student();

私が次のようなことができるように

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

これで、studオブジェクトはメモリ内である程度のサイズを占有します。いくつかのデータとより多くのオブジェクトがあります。

studオブジェクトが占有しているメモリの量を確認するにはどうすればよいですか?sizeof()JavaScriptのようなものですか?のような単一の関数呼び出しでそれを見つけることができれば、それは本当に素晴らしいことsizeof(stud)です。

私は何ヶ月もインターネットを検索してきましたが、見つかりませんでした(いくつかのフォーラムで尋ねられましたが、返信はありません)。

4

22 に答える 22

213

元の回答でコードをリファクタリングしました。再帰を削除し、想定される存在のオーバーヘッドを削除しました。

function roughSizeOfObject( object ) {

    var objectList = [];
    var stack = [ object ];
    var bytes = 0;

    while ( stack.length ) {
        var value = stack.pop();

        if ( typeof value === 'boolean' ) {
            bytes += 4;
        }
        else if ( typeof value === 'string' ) {
            bytes += value.length * 2;
        }
        else if ( typeof value === 'number' ) {
            bytes += 8;
        }
        else if
        (
            typeof value === 'object'
            && objectList.indexOf( value ) === -1
        )
        {
            objectList.push( value );

            for( var i in value ) {
                stack.push( value[ i ] );
            }
        }
    }
    return bytes;
}
于 2012-08-10T10:55:02.963 に答える
148

Google Chrome ヒープ プロファイラーを使用すると、オブジェクトのメモリ使用量を調べることができます。

トリッキーな場合があるトレースでオブジェクトを見つけることができる必要があります。オブジェクトを Window グローバルに固定すると、"Containment" リスト モードから非常に簡単に見つけることができます。

添付のスクリーンショットでは、ウィンドウに「testObj」というオブジェクトを作成しました。次に、(記録を作成した後) プロファイラーに配置すると、オブジェクトのフルサイズとその中のすべてが「保持サイズ」の下に表示されます。

メモリ内訳の詳細

Chrome プロファイラ

上のスクリーンショットでは、オブジェクトは 60 の保持サイズを示しています。単位はバイトだと思います。

于 2012-09-13T14:28:22.503 に答える
81

私はこれを書いたのは、同様の(っぽい)問題を解決するためです。それはあなたが探しているかもしれないことを正確に行いません、すなわちそれはインタプリタがオブジェクトをどのように保存するかを考慮に入れません。

ただし、V8を使用している場合は、すばらしいプロトタイピングと非表示のクラスがオーバーヘッドの大部分をなめるので、かなり大丈夫な概算が得られるはずです。

function roughSizeOfObject( object ) {

    var objectList = [];

    var recurse = function( value )
    {
        var bytes = 0;

        if ( typeof value === 'boolean' ) {
            bytes = 4;
        }
        else if ( typeof value === 'string' ) {
            bytes = value.length * 2;
        }
        else if ( typeof value === 'number' ) {
            bytes = 8;
        }
        else if
        (
            typeof value === 'object'
            && objectList.indexOf( value ) === -1
        )
        {
            objectList[ objectList.length ] = value;

            for( i in value ) {
                bytes+= 8; // an assumed existence overhead
                bytes+= recurse( value[i] )
            }
        }

        return bytes;
    }

    return recurse( object );
}
于 2011-06-14T23:30:53.723 に答える
74

サーバーからクライアントに送信される可能性のある非常に大きなオブジェクトにフラグを立てるために、これを使用することがあります。メモリ内フットプリントを表すものではありません。送信または保管するのにかかるおおよその費用がわかります。

また、遅いことに注意してください。開発のみです。しかし、1行のコードで大まかな答えを得るため、私にとっては役に立ちました。

roughObjSize = JSON.stringify(bigObject).length;
于 2015-01-28T05:42:06.010 に答える
69

問題に対するもう少しコンパクトな解決策を次に示します。

const typeSizes = {
  "undefined": () => 0,
  "boolean": () => 4,
  "number": () => 8,
  "string": item => 2 * item.length,
  "object": item => !item ? 0 : Object
    .keys(item)
    .reduce((total, key) => sizeOf(key) + sizeOf(item[key]) + total, 0)
};

const sizeOf = value => typeSizes[typeof value](value);
于 2015-04-01T09:32:22.007 に答える
55

オブジェクト sizeof を取得する NPM モジュールがあり、次のコマンドでインストールできますnpm install object-sizeof

  var sizeof = require('object-sizeof');

  // 2B per character, 6 chars total => 12B
  console.log(sizeof({abc: 'def'}));

  // 8B for Number => 8B
  console.log(sizeof(12345));

  var param = { 
    'a': 1, 
    'b': 2, 
    'c': {
      'd': 4
    }
  };
  // 4 one two-bytes char strings and 3 eighth-bytes numbers => 32B
  console.log(sizeof(param));
于 2014-05-18T11:46:49.413 に答える
18

これはハックな方法ですが、異なる数値で 2 回試してみましたが、一貫しているようです。

できることは、100 万から 200 万の、必要な種類のオブジェクトなど、膨大な数のオブジェクトを割り当てようとすることです。オブジェクトを配列に入れて、ガベージ コレクターがオブジェクトを解放しないようにします (これにより、配列のためにメモリ オーバーヘッドがわずかに追加されることに注意してください。ただし、これが問題にならないことを願っています。 、どこかに保存します)。割り当ての前後にアラートを追加し、各アラートで Firefox プロセスが使用しているメモリ量を確認します。テストでページを開く前に、新しい Firefox インスタンスがあることを確認してください。ページを開き、「前」のアラートが表示された後のメモリ使用量に注意してください。アラートを閉じ、メモリが割り当てられるまで待ちます。古いメモリから新しいメモリを引き、割り当て量で割ります。

function Marks()
{
  this.maxMarks = 100;
}

function Student()
{
  this.firstName = "firstName";
  this.lastName = "lastName";
  this.marks = new Marks();
}

var manyObjects = new Array();
alert('before');
for (var i=0; i<2000000; i++)
    manyObjects[i] = new Student();
alert('after');

私は自分のコンピューターでこれを試しましたが、「前」のアラートが表示されたとき、プロセスには 48352K のメモリがありました。割り当て後、Firefox には 440236K のメモリがありました。200 万の割り当ての場合、これはオブジェクトごとに約 200 バイトです。

100 万回の割り当てで再試行したところ、結果は似ていました。オブジェクトあたり 196 バイトです (2mill の余分なデータが配列に使用されたと思います)。

だから、ここにあなたを助けるかもしれないハッキーな方法があります. JavaScript が「sizeof」メソッドを提供していないのには理由があります。JavaScript の実装はそれぞれ異なります。たとえば、Google Chrome では、同じページが各オブジェクトに約 66 バイトを使用します (少なくともタスク マネージャーから判断すると)。

于 2009-08-08T09:57:04.097 に答える
12

申し訳ありませんがコメントできませんでしたので、tomwrong から作業を続けます。この強化されたバージョンは、オブジェクトを 2 回以上カウントしないため、無限ループは発生しません。さらに、オブジェクトのキーも大まかに数えるべきだと思います。

function roughSizeOfObject( value, level ) {
    if(level == undefined) level = 0;
    var bytes = 0;

    if ( typeof value === 'boolean' ) {
        bytes = 4;
    }
    else if ( typeof value === 'string' ) {
        bytes = value.length * 2;
    }
    else if ( typeof value === 'number' ) {
        bytes = 8;
    }
    else if ( typeof value === 'object' ) {
        if(value['__visited__']) return 0;
        value['__visited__'] = 1;
        for( i in value ) {
            bytes += i.length * 2;
            bytes+= 8; // an assumed existence overhead
            bytes+= roughSizeOfObject( value[i], 1 )
        }
    }

    if(level == 0){
        clear__visited__(value);
    }
    return bytes;
}

function clear__visited__(value){
    if(typeof value == 'object'){
        delete value['__visited__'];
        for(var i in value){
            clear__visited__(value[i]);
        }
    }
}

roughSizeOfObject(a);
于 2011-06-16T06:03:01.810 に答える
12

同じ問題があります。Google で検索しましたが、このソリューションをスタックオーバーフロー コミュニティと共有したいと思います。

重要:

Yan Qingが github で 共有している関数を使用しましたhttps://gist.github.com/zensh/4975495

function memorySizeOf(obj) {
    var bytes = 0;

    function sizeOf(obj) {
        if(obj !== null && obj !== undefined) {
            switch(typeof obj) {
            case 'number':
                bytes += 8;
                break;
            case 'string':
                bytes += obj.length * 2;
                break;
            case 'boolean':
                bytes += 4;
                break;
            case 'object':
                var objClass = Object.prototype.toString.call(obj).slice(8, -1);
                if(objClass === 'Object' || objClass === 'Array') {
                    for(var key in obj) {
                        if(!obj.hasOwnProperty(key)) continue;
                        sizeOf(obj[key]);
                    }
                } else bytes += obj.toString().length * 2;
                break;
            }
        }
        return bytes;
    };

    function formatByteSize(bytes) {
        if(bytes < 1024) return bytes + " bytes";
        else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KiB";
        else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MiB";
        else return(bytes / 1073741824).toFixed(3) + " GiB";
    };

    return formatByteSize(sizeOf(obj));
};


var sizeOfStudentObject = memorySizeOf({Student: {firstName: 'firstName', lastName: 'lastName', marks: 10}});
console.log(sizeOfStudentObject);

あなたはそれについてどう思いますか?

于 2017-01-08T10:44:12.350 に答える
7

メモリ削減の努力が実際にメモリ削減に役立つかどうか知りたい

このコメントに続いて、次のことを行う必要があります: メモリの問題を作成してみてください - これらすべてのオブジェクトを作成するコードを記述し、問題 (ブラウザのクラッシュ、ブラウザのフリーズ、または Out-Of-メモリエラー)。理想的には、さまざまなブラウザーとさまざまなオペレーティング システムでこの実験を繰り返す必要があります。

現在、2 つのオプションがあります。 オプション 1 - メモリの問題をうまく生成できませんでした。したがって、あなたは何も心配していません。メモリの問題はなく、プログラムは問題ありません。

オプション 2 - メモリの問題が発生しました。ここで、問題が発生した制限が妥当かどうかを自問してください (つまり、コードの通常の使用でこの量のオブジェクトが作成される可能性があるかどうか)。答えが「いいえ」の場合は問題ありません。それ以外の場合は、コードで作成できるオブジェクトの数がわかりました。この制限に違反しないようにアルゴリズムを作り直してください。

于 2009-08-08T09:34:35.907 に答える
5

Firefox拡張機能のメモリ使用量が主な懸念事項である場合は、Mozilla開発者に確認することをお勧めします。

Mozillaは、そのwikiで、メモリリークを分析するためのツールのリストを提供しています。

于 2010-01-09T11:50:41.120 に答える
5

Chrome 開発者ツールにはこの機能があります。この記事は非常に役に立ち、あなたが望むことを正確に行います: https://developers.google.com/chrome-developer-tools/docs/heap-profiling

于 2013-01-07T17:45:54.387 に答える
2

このためのコードに取り組んでいるすべての人に感謝します!

まったく同じものを探していたことを追加したかっただけですが、私の場合は、処理されたオブジェクトのキャッシュを管理して、キャッシュされているかどうかにかかわらず、ajax 呼び出しからオブジェクトを再解析して処理する必要がないようにするためです。ブラウザによって。これは、多くの処理を必要とするオブジェクト (通常は JSON 形式ではないもの) に特に役立ちますが、これらのものを大規模なプロジェクトや長期間実行されているアプリ/拡張機能にキャッシュしておくと、非常にコストがかかる可能性があります。時間。

とにかく、私はそれを次のようなものに使用します:

var myCache = {
    cache: {},
    order: [],
    size: 0,
    maxSize: 2 * 1024 * 1024, // 2mb

    add: function(key, object) {
        // Otherwise add new object
        var size = this.getObjectSize(object);
        if (size > this.maxSize) return; // Can't store this object

        var total = this.size + size;

        // Check for existing entry, as replacing it will free up space
        if (typeof(this.cache[key]) !== 'undefined') {
            for (var i = 0; i < this.order.length; ++i) {
                var entry = this.order[i];
                if (entry.key === key) {
                    total -= entry.size;
                    this.order.splice(i, 1);
                    break;
                }
            }
        }

        while (total > this.maxSize) {
            var entry = this.order.shift();
            delete this.cache[entry.key];
            total -= entry.size;
        }

        this.cache[key] = object;
        this.order.push({ size: size, key: key });
        this.size = total;
    },

    get: function(key) {
        var value = this.cache[key];
        if (typeof(value) !== 'undefined') { // Return this key for longer
            for (var i = 0; i < this.order.length; ++i) {
                var entry = this.order[i];
                if (entry.key === key) {
                    this.order.splice(i, 1);
                    this.order.push(entry);
                    break;
                }
            }
        }
        return value;
    },

    getObjectSize: function(object) {
        // Code from above estimating functions
    },
};

これは単純な例であり、いくつかのエラーがある可能性がありますが、ある程度の知性を備えた静的オブジェクト (コンテンツは変更されません) を保持するために使用できるため、アイデアが得られます。これにより、最初にオブジェクトを生成する必要があった高価な処理要件を大幅に削減できます。

于 2013-04-06T11:54:18.877 に答える
1

Chrome 開発ツールの[タイムライン] タブを使用して、ますます大量のオブジェクトをインスタンス化し、そのような適切な見積もりを取得します。以下のような html をボイラープレートとして使用し、それを変更して、オブジェクトの特性 (プロパティの数とタイプなど) をより適切にシミュレートできます。実行の前後に、その開発ツール タブの下部にあるごみ箱アイコンをクリックすることをお勧めします。

<html>
<script>
var size = 1000*100
window.onload = function() {
  document.getElementById("quantifier").value = size
}

function scaffold()
{
  console.log("processing Scaffold...");
  a = new Array
}

function start()
{
  size = document.getElementById("quantifier").value
  console.log("Starting... quantifier is " + size);
  console.log("starting test")
  for (i=0; i<size; i++){
    a[i]={"some" : "thing"}
  }
  console.log("done...")
}

function tearDown()
{
  console.log("processing teardown");
  a.length=0
}

</script>
<body>
    <span style="color:green;">Quantifier:</span>
    <input id="quantifier" style="color:green;" type="text"></input>
    <button onclick="scaffold()">Scaffold</button>
    <button onclick="start()">Start</button>
    <button onclick="tearDown()">Clean</button>
    <br/>
</body>
</html>

(上記のコードのように) 1 つのプロパティだけを持つ 200 万個のオブジェクトをインスタンス化すると、現在、私の Chromium では、オブジェクトあたり 50 バイトという大まかな計算になります。オブジェクトごとにランダムな文字列を作成するようにコードを変更すると、オブジェクトごとに約 30 バイトが追加されます。

于 2013-12-11T23:51:24.263 に答える
1
function sizeOf(parent_data, size)
{
    for (var prop in parent_data)
    {
        let value = parent_data[prop];

        if (typeof value === 'boolean')
        {
            size += 4;
        }
        else if (typeof value === 'string')
        {
            size += value.length * 2;
        }
        else if (typeof value === 'number')
        {
             size += 8;
        }
        else
        {      
            let oldSize = size;
            size += sizeOf(value, oldSize) - oldSize;
        }
    }

    return size;
}


function roughSizeOfObject(object)
{   
    let size = 0;
    for each (let prop in object)
    {    
        size += sizeOf(prop, 0);
    } // for..
    return size;
}
于 2011-10-12T21:06:38.110 に答える
-3

「配列」を含めるのを忘れたと思います。

  typeOf : function(value) {
        var s = typeof value;
        if (s === 'object')
        {
            if (value)
            {
                if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length')) && typeof value.splice === 'function')
                {
                    s = 'array';
                }
            }
            else
            {
                s = 'null';
            }
        }
        return s;
    },

   estimateSizeOfObject: function(value, level)
    {
        if(undefined === level)
            level = 0;

        var bytes = 0;

        if ('boolean' === typeOf(value))
            bytes = 4;
        else if ('string' === typeOf(value))
            bytes = value.length * 2;
        else if ('number' === typeOf(value))
            bytes = 8;
        else if ('object' === typeOf(value) || 'array' === typeOf(value))
        {
            for(var i in value)
            {
                bytes += i.length * 2;
                bytes+= 8; // an assumed existence overhead
                bytes+= estimateSizeOfObject(value[i], 1)
            }
        }
        return bytes;
    },

   formatByteSize : function(bytes)
    {
        if (bytes < 1024)
            return bytes + " bytes";
        else
        {
            var floatNum = bytes/1024;
            return floatNum.toFixed(2) + " kb";
        }
    },
于 2011-11-04T19:26:59.373 に答える
-7

これが絶対に正しい方法ではないことはわかっていますが、過去に数回、おおよそのオブジェクトファイルサイズを取得するのに役立ちました

オブジェクト/応答をコンソールまたは新しいタブに書き込み、結果を新しいメモ帳ファイルにコピーして保存し、ファイル サイズを確認します。メモ帳ファイル自体は数バイトなので、かなり正確なオブジェクト ファイル サイズを取得できます。

于 2016-03-27T21:32:28.347 に答える