objetos - prototype javascript ejemplos
¿Cómo obtener el tamaño de un objeto JavaScript? (19)
Quiero saber el tamaño ocupado por un objeto de JavaScript.
Tome la siguiente función:
function Marks(){
this.maxMarks = 100;
}
function Student(){
this.firstName = "firstName";
this.lastName = "lastName";
this.marks = new Marks();
}
Ahora hago una instancia del student
:
var stud = new Student();
para que yo pueda hacer cosas como
stud.firstName = "new Firstname";
alert(stud.firstName);
stud.marks.maxMarks = 200;
etc.
Ahora, el objeto stud
ocupará algún tamaño en la memoria. Tiene algunos datos y más objetos.
¿Cómo puedo saber la cantidad de memoria que ocupa el objeto stud
? Algo como un sizeof()
en JavaScript? Sería realmente increíble si pudiera encontrarlo en una sola función de llamada como sizeof(stud)
.
He estado buscando en Internet durante meses, no pude encontrarlo (lo consulté en un par de foros, sin respuestas).
Quiero saber si mis esfuerzos de reducción de memoria realmente ayudan a reducir la memoria
A continuación de este comentario, esto es lo que debe hacer: Trate de producir un problema de memoria: escriba un código que cree todos estos objetos y aumente el límite superior hasta que se encuentre con un problema (bloqueo del navegador, bloqueo del navegador o un Out-Of- error de memoria). Lo ideal es que repitas este experimento con diferentes navegadores y diferentes sistemas operativos.
Ahora hay dos opciones: opción 1: no tuvo éxito en producir el problema de la memoria. Por lo tanto, te estás preocupando por nada. No tienes un problema de memoria y tu programa está bien.
Opción 2- obtuviste un problema de memoria Ahora pregúntese si el límite en el que ocurrió el problema es razonable (en otras palabras: es probable que esta cantidad de objetos se cree con el uso normal de su código). Si la respuesta es ''No'', entonces estás bien. De lo contrario, ahora sabrá cuántos objetos puede crear su código. Reproduzca el algoritmo de manera que no supere este límite.
A veces, uso esto para marcar objetos realmente grandes que podrían estar yendo al cliente desde el servidor. No representa la huella en memoria. Solo le proporciona aproximadamente lo que costaría enviarlo o almacenarlo.
También tenga en cuenta, es lento, dev sólo. Pero para obtener una respuesta aproximada con una línea de código me ha sido útil.
roughObjSize = JSON.stringify(bigObject).length;
Acabo de escribir esto para resolver un problema similar (ish). No hace exactamente lo que puede estar buscando, es decir, no tiene en cuenta cómo el intérprete almacena el objeto.
Pero, si estás utilizando V8, debería darte una aproximación bastante buena, ya que la asombrosa creación de prototipos y las clases ocultas absorben la mayor parte de los gastos generales.
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 );
}
Creo que te olvidaste de incluir ''array''.
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";
}
},
El Google Chrome Heap Profiler le permite inspeccionar el uso de la memoria de objetos.
Debe poder ubicar el objeto en la traza, lo que puede ser complicado. Si coloca el objeto en la ventana global, es bastante fácil encontrarlo en el modo de listado "Contención".
En la captura de pantalla adjunta, creé un objeto llamado "testObj" en la ventana. Luego me ubiqué en el generador de perfiles (después de hacer una grabación) y muestra el tamaño completo del objeto y todo lo que contiene debajo de "tamaño retenido".
Más detalles sobre las averías de memoria .
En la captura de pantalla anterior, el objeto muestra un tamaño retenido de 60. Creo que la unidad es bytes aquí.
Esta biblioteca de Javascript sizeof.js
hace lo mismo. Incluyelo asi
<script type="text/javascript" src="sizeof.js"></script>
La función sizeof toma un objeto como parámetro y devuelve su tamaño aproximado en bytes. Por ejemplo:
// 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);
La función sizeof puede manejar objetos que contienen múltiples referencias a otros objetos y referencias recursivas.
Este es un método hacky, pero lo intenté dos veces con números diferentes y parece ser consistente.
Lo que puede hacer es tratar de asignar una gran cantidad de objetos, como uno o dos millones de objetos del tipo que desee. Coloque los objetos en una matriz para evitar que el recolector de basura los libere (tenga en cuenta que esto agregará una pequeña sobrecarga de memoria debido a la matriz, pero espero que esto no importe y además si va a preocuparse de que haya objetos en la memoria) , los guardas en algún lugar). Agregue una alerta antes y después de la asignación y en cada alerta verifique cuánta memoria está tomando el proceso de Firefox. Antes de abrir la página con la prueba, asegúrese de tener una nueva instancia de Firefox. Abra la página, tenga en cuenta el uso de la memoria después de que se muestre la alerta "antes". Cierre la alerta, espere a que se asigne la memoria. Reste la memoria nueva de la anterior y divídala por la cantidad de asignaciones. Ejemplo:
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'');
Intenté esto en mi computadora y el proceso tenía 48352K de memoria cuando se mostraba la alerta "antes". Después de la asignación, Firefox tenía 440236K de memoria. Para asignaciones de 2 millones, esto es aproximadamente 200 bytes para cada objeto.
Lo intenté de nuevo con 1 millón de asignaciones y el resultado fue similar: 196 bytes por objeto (supongo que los datos adicionales en 2mill se usaron para Array).
Entonces, aquí hay un método hacky que podría ayudarte. JavaScript no proporciona un método "sizeof" por una razón: cada implementación de JavaScript es diferente. En Google Chrome, por ejemplo, la misma página utiliza aproximadamente 66 bytes para cada objeto (al menos desde el administrador de tareas).
Hay un módulo NPM para obtener el tamaño del objeto , puede instalarlo con 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));
He vuelto a factorizar el código en mi respuesta original . He eliminado la recursión y eliminado la supuesta sobrecarga de existencia.
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;
}
Las herramientas de desarrollo de Chrome tienen esta funcionalidad. Encontré este artículo muy útil y hace exactamente lo que quiere: developers.google.com/chrome-developer-tools/docs/…
Lo siento, no pude comentar, así que solo continúo el trabajo de TomWrong. Esta versión mejorada no contará el objeto más de una vez, por lo tanto no habrá un bucle infinito. Además, creo que la clave de un objeto también debe contarse, aproximadamente.
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);
Muchas gracias a todos los que han estado trabajando en el código para esto!
Solo quería agregar que he estado buscando exactamente lo mismo, pero en mi caso es para administrar un caché de objetos procesados para evitar tener que volver a analizar y procesar objetos de llamadas ajax que pueden o no haber sido cacheadas. por el navegador. Esto es especialmente útil para los objetos que requieren mucho procesamiento, generalmente cualquier cosa que no esté en formato JSON, pero puede ser muy costoso mantener estos elementos en caché en un proyecto grande o una aplicación / extensión que se deja en ejecución durante mucho tiempo. hora.
De todos modos, lo uso para algo como:
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
},
};
Es un ejemplo simplista y puede tener algunos errores, pero da la idea, ya que puede usarlo para aferrarse a objetos estáticos (los contenidos no cambiarán) con cierto grado de inteligencia. Esto puede reducir significativamente los costosos requisitos de procesamiento que el objeto tuvo que producir en primer lugar.
Si necesita verificar programáticamente por aprox. tamaño de los objetos también puede consultar esta biblioteca http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/ que he podido usar para el tamaño de los objetos.
De lo contrario, sugiero usar Chrome / Firefox Heap Profiler.
Si su principal preocupación es el uso de memoria de su extensión de Firefox, sugiero que consulte con los desarrolladores de Mozilla.
Mozilla proporciona en su wiki una lista de herramientas para analizar las fugas de memoria .
Teniendo el mismo problema. Busqué en Google y quiero compartir con la comunidad esta solución.
Importante :
Usé la función compartida por Yan Qing en 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);
¿Qué piensa usted al respecto?
Un poco tarde para la fiesta, pero aquí hay una solución un poco más compacta al problema:
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);
Utilizo la pestaña Línea de tiempo de las herramientas de desarrollo de Chrome, ejemplifico cantidades cada vez mayores de objetos y obtengo buenas estimaciones de este tipo. Puede usar html como este a continuación, como plantilla, y modificarlo para simular mejor las características de sus objetos (número y tipos de propiedades, etc.). Es posible que desee hacer clic en el icono de bit de papelera en la parte inferior de la pestaña de herramientas de desarrollo, antes y después de una ejecución.
<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>
Instalar 2 millones de objetos de solo una propiedad cada uno (como en este código anterior) lleva a un cálculo aproximado de 50 bytes por objeto, en mi Chromium, ahora mismo. Cambiar el código para crear una cadena aleatoria por objeto agrega unos 30 bytes por objeto, etc. Espero que esto ayude.
Sé que esta no es la forma correcta de hacerlo, pero me ha ayudado varias veces en el pasado para obtener el tamaño aproximado del archivo de objeto:
Escriba su objeto / respuesta en la consola o una nueva pestaña, copie los resultados en un nuevo archivo de bloc de notas, guárdelo y verifique el tamaño del archivo. El archivo de la libreta de notas tiene solo unos pocos bytes, por lo que obtendrá un tamaño de archivo de objeto bastante preciso.
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;
}