如何获得JavaScript对象的大小?
我想知道JavaScript对象占用的大小。
采取以下function:
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
物体占据多less内存? 像JavaScript中的sizeof()
? 如果我能用sizeof(stud)
这样的单个函数调用它,那真是太棒了。
我一直在互联网上search几个月 – 无法find它(在几个论坛问 – 没有答复)。
我在原来的答案中重新考虑了代码。 我已经删除了recursion,并删除了假定的存在开销。
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; }
我只是写这个来解决一个类似的问题。 它并不完全符合你的要求,也就是说它没有考虑到解释器如何存储对象。
但是,如果你使用的是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 ); }
Google Chrome堆分析器允许您检查对象内存的使用情况。
您需要能够在棘手的踪迹中find对象。 如果将对象固定到Window全局,则可以很容易地从“Containment”列表模式中find。
在附件的截图中,我在窗口上创build了一个名为“testObj”的对象。 然后,我在探查器中(进行logging之后),显示对象的全部大小以及“保留大小”下的所有内容。
关于内存故障的更多细节 。
在上面的截图中,对象显示保留的大小为60.我相信这里的单位是字节。
有时候我会用这个来标记可能从服务器上传到客户端的大对象。 它不代表内存占用。 它只是让你大概花费什么发送或存储它。
另外请注意,它是缓慢的,开发只。 但是为了获得一行代码的球场答案,这对我很有用。
roughObjSize = JSON.stringify(bigObject).length;
有一个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));
这是一个hacky的方法,但我试了两次不同的数字,它似乎是一致的。
你可以做的就是尝试和分配大量的对象,比如你想要的一百万或者两百万个对象。 把对象放在一个数组中,以防止垃圾收集器释放它们(请注意,由于数组,这会增加一些内存开销,但是我希望这不是问题,除此之外,如果你要担心内存中的对象,你把它们存储在某个地方)。 在分配之前和之后添加警报,并在每个警报中检查Firefox进程正在使用多less内存。 在testing打开页面之前,请确保您有一个全新的Firefox实例。 打开页面,注意显示“之前”警报之后的内存使用情况。 closures警报,等待内存分配。 从旧的减去新的内存,并除以分配的金额。 例:
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');
我在我的电脑中试过这个,当显示“before”警报时,这个过程有48352K的内存。 分配之后,Firefox有440236K的内存。 对于2百万分配,每个对象大约有200个字节。
我再次尝试100万次的分配,结果是相似的:每个对象196个字节(我假设2mill中的额外数据用于数组)。
所以,这是一个可能帮助你的黑客方法。 JavaScript没有提供“sizeof”方法,原因是:每个JavaScript实现都是不同的。 例如在谷歌浏览器中,同一页面每个对象使用大约66个字节(至less从任务pipe理器判断)。
对不起,我不能评论,所以我只是继续从tomwrong的工作。 这个增强版本不会多次计算对象,因此不会有无限循环。 另外,我认为一个对象的关键也应该大致计数。
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);
晚会有点晚,但是这里有一个稍微更紧凑的解决scheme:
const typeSizes = { "undefined": () => 0, "boolean": () => 4, "number": () => 8, "string": item => 2 * item.length, "object": item => Object .keys(item || {}) .reduce((total, key) => sizeOf(key) + sizeOf(item[key]) + total, 0) }; const sizeOf = value => typeSizes[typeof value](value);
这个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函数可以处理包含对其他对象和recursion引用的多个引用的对象。
最初在这里发表 。
有同样的问题。 我在Google上search,我想与这个解决scheme分享与stackoverflow社区。
重要 :
我使用了阎青在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);
我想知道如果我的记忆减less努力实际上有助于减less记忆
继续这个评论,这是你应该做的:尝试产生一个内存问题 – 编写代码,创build所有这些对象,graudally增加上限,直到你遇到了一个问题(浏览器崩溃,浏览器冻结或Out-Of-内存错误)。 理想情况下,您应该使用不同的浏览器和不同的操作系统重复此实验。
现在有两个选项:选项1 – 您没有成功地产生内存问题。 因此,你不用担心。 你没有内存问题,你的程序是好的。
选项2-你确实得到一个内存问题。 现在问自己,问题发生的极限是否合理(换句话说,在正常使用你的代码的过程中是否可能创build这个数量的对象)。 如果答案是“否”,那么你很好。 否则,你现在知道你的代码可以创build多less个对象。 重做algorithm,使其不违反这个限制。
如果您主要关心的是Firefox扩展的内存使用情况,我build议您与Mozilla开发人员联系。
Mozilla在其wiki上提供了分析内存泄漏的工具列表 。
Chrome开发人员工具具有此function。 我发现这篇文章非常有帮助,而且完全按照你的要求: 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; }
非常感谢大家一直在为此编写代码!
我只是想补充一点,我一直在寻找完全相同的东西,但在我的情况下,这是为了pipe理caching的处理对象,以避免必须重新parsing和处理可能或可能没有被caching的Ajax调用对象由浏览器。 这对需要大量处理的对象(通常是不是JSON格式的对象)特别有用,但是将这些东西caching在一个大的项目或一个长时间运行的应用程序/扩展中会花费很多代价时间。
无论如何,我用它的东西是这样的:
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 }, };
这是一个简单的例子,可能有一些错误,但是它给出了这个想法,你可以使用它来保持静态对象(内容不会改变),并具有一定程度的智能。 这可以显着地减less对象必须首先生产的任何昂贵的处理要求。
我使用Chrome开发工具的“ 时间轴”选项卡 ,实例化越来越多的对象,并得到这样的好估计。 你可以像下面这样使用html作为样板,并修改它以更好地模拟对象的特性(数量和属性的types等)。 您可能想要在运行前后单击该开发工具选项卡底部的垃圾位图标。
<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>
实例化200万只有一个属性的对象(就像上面的代码一样),导致在我的Chromium上,每个对象有50个字节的粗略计算。 改变代码为每个对象创build一个随机string,每个对象增加大约30个字节,等等。希望这有助于。
如果你需要编程检查aprox。 大小的对象,你也可以检查这个库http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/ ,我已经能够用于对象的大小。
否则,我build议使用Chrome / Firefox堆分析器。
我相信你忘了包括'数组'。
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"; } },
我知道这绝对不是正确的做法,但过去几次帮助我获得大致的目标文件大小:
将您的对象/响应写入控制台或新选项卡,将结果复制到新的记事本文件,保存并检查文件大小。 记事本文件本身只是几个字节,所以你会得到一个相当准确的对象文件大小。