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
オブジェクトがどれだけのメモリを占有しているかを調べるにはどうすればよいですか? JavaScriptのsizeof()
のようなものは? sizeof(stud)
のような単一の関数呼び出しで見つけることができれば、それは本当に素晴らしいことです。
私は何か月もインターネットを検索していましたが、見つけることができませんでした(2、3のフォーラムで質問しました - 返事はありません)。
私は 元の答え にコードを書き直しました。再帰を削除し、想定される存在のオーバーヘッドを削除しました。
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;
}
Google Chrome Heap Profilerでは、オブジェクトメモリの使用状況を調べることができます。
注意が必要なトレース内のオブジェクトを見つけることができる必要があります。オブジェクトをWindowグローバルに固定すると、 "Containment"リストモードから簡単に見つけることができます。
添付のスクリーンショットで、私はウィンドウ上に "testObj"というオブジェクトを作成しました。私はそれからプロファイラーに(記録をした後に)置かれ、それはオブジェクトのフルサイズと "保持サイズ"の下のその中の全てを示しています。
メモリ故障の詳細 。
上のスクリーンショットでは、オブジェクトの保持サイズは60です。ここでの単位はバイトです。
私はちょうどこれを似たような(ish)問題を解決するために書いた。それはあなたが探しているかもしれないことを正確には行いません、すなわちそれはインタプリタがどのようにオブジェクトを格納するかを考慮に入れません。
しかし、もしあなたが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 );
}
サーバからクライアントに送信される可能性がある本当に大きなオブジェクトにフラグを付けるために、これを使用することがあります。メモリ内のフットプリントを表すものではありません。それを送信するか、または保存するのに要する費用とほぼ同じ金額になります。
また、遅いです、開発者のみです。しかし、1行のコードでボールパークの答えを得るのにそれは私にとって役に立ちました。
roughObjSize = JSON.stringify(bigObject).length;
object 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));
パーティーには少し遅れましたが、ここでは問題に対するもう少しコンパクトな解決策を示します。
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);
これはハックな方法ですが、私は異なる数でそれを二度試しました、そしてそれは一貫しているようです。
あなたができることは、あなたが望む種類の100万個あるいは200万個のオブジェクトのように、巨大なオブジェクトの数を試して割り当てることです。オブジェクトを配列に配置して、ガベージコレクタがそれらを解放しないようにします(これにより、配列によるメモリのオーバーヘッドがわずかに増えることに注意してください)。 、あなたはそれらをどこかに保存します。割り当ての前後にアラートを追加し、各アラートでFirefoxプロセスが使用しているメモリ量を確認します。テスト用のページを開く前に、新しいFirefoxインスタンスがあることを確認してください。ページを開き、 "before"アラートが表示された後のメモリ使用量をメモします。警告を閉じ、メモリが割り当てられるのを待ちます。古いメモリから新しいメモリを引き、割り当て量で割ります。例:
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の余分なデータがArrayのために使われたと思います)。
だから、これはあなたを助けるかもしれないハッキーな方法です。 JavaScriptは「sizeof」メソッドを提供していません。それは、JavaScriptの実装がそれぞれ異なるからです。たとえばGoogle Chromeでは、同じページで各オブジェクトに約66バイトが使用されます(少なくともタスクマネージャから判断すると)。
申し訳ありませんが私はコメントできなかったので、私はただ間違ったところから作業を続けます。この拡張バージョンは、オブジェクトを複数回カウントすることはないため、無限ループは発生しません。さらに、オブジェクトのキーも大まかに数えるべきだと思います。
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);
同じ問題を抱えている。私はGoogleで検索し、このソリューションをstackoverflowコミュニティと共有したいと思います。
重要:
GithubでYan Qingと共有している機能を使用しました 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);
あなたはそれについてどう思いますか?
私の記憶の減少の努力が実際に記憶の減少に役立つかどうか知りたいです。
メモリの問題を起こす - これらすべてのオブジェクトを作成し、問題に遭遇するまで上限を徐々に増加させるコードを書く(ブラウザがクラッシュする、ブラウザがフリーズする、またはOut-Of-が発生する)。メモリエラー)。理想的にはあなたは異なるブラウザと異なるオペレーティングシステムでこの実験を繰り返すべきです。
2つの選択肢があります:選択肢1 - あなたはメモリの問題を引き起こすことに成功しませんでした。したがって、あなたは何も心配していません。メモリの問題はなく、プログラムは問題ありません。
オプション2 - あなたはメモリの問題を抱えていました。それでは、問題が発生した制限が妥当かどうかを自問してみてください(つまり、この量のオブジェクトが通常のコード使用で作成される可能性が高いです)。答えが 'いいえ'であれば大丈夫です。それ以外の場合は、コードで作成できるオブジェクトの数がわかりました。この制限に違反しないようにアルゴリズムを修正してください。
このJavascriptライブラリsizeof.js
も同じことをします。このように含める
<script type="text/javascript" src="sizeof.js"></script>
Sizeof関数は、オブジェクトをパラメータとして受け取り、そのおよそのサイズをバイト数で返します。例えば:
// define an object
var object =
{
'boolean' : true,
'number' : 1,
'string' : 'a',
'array' : [1, 2, 3]
};
// determine the size of the object
var size = sizeof(object);
Sizeof関数は、他のオブジェクトへの複数の参照と再帰的参照を含むオブジェクトを処理できます。
あなたの主な関心事があなたのFirefox拡張のメモリ使用量であるならば、私はMozilla開発者と相談することを勧めます。
Mozillaはそのウィキで メモリリークを分析するためのツールのリスト を提供しています。
Chrome開発者ツールにはこの機能があります。この記事はとても参考になり、あなたが望むことをしてくれます。 https://developers.google.com/chrome-developer-tools/docs/heap-profiling
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;
}
これのためにコードに取り組んできたみんなに感謝します!
私はまったく同じことを探していることを付け加えたかったのですが、私の場合は、キャッシュされているかどうかにかかわらず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
},
};
これは単純化した例であり、多少のエラーがあるかもしれませんが、ある程度の知能をもって静的なオブジェクトを保持するために使うことができるので(内容は変わらない)、それはアイデアを与えます。これは、対象物が最初に製造されなければならないという高価な処理要件を大幅に削減することができる。
私は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バイトほど追加されます。これが役に立つことを願います。
プログラムでaproxを確認する必要がある場合。あなたはまた、このライブラリをチェックすることができますオブジェクトのサイズ http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/ 私はオブジェクトのサイズに使用することができました。
それ以外の場合は、Chrome/Firefox Heap Profilerを使用することをお勧めします。