Comment obtenir la taille d'un objet JavaScript?

je veux connaître la taille occupée par un objet JavaScript.

prendre la fonction suivante:

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

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

maintenant j'instancie le student :

var stud = new Student();

pour que je puisse faire des choses comme

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

etc.

maintenant, l'objet stud va occuper une certaine taille en mémoire. Il dispose de quelques données et des objets plus.

Comment savoir comment beaucoup de mémoire occupe l'objet stud ? Quelque chose comme un sizeof() en JavaScript? Ce serait vraiment génial si je pouvais le trouver dans un seul appel de fonction comme sizeof(stud) .

j'ai cherché sur Internet pendant des mois-je ne l'ai pas trouvé (demandé dans quelques forums-pas de réponses).

204
demandé sur Xufox 2009-08-08 11:58:17

19 réponses

j'ai recalculé le code dans ma réponse originale . J'ai enlevé la récursion et enlevé l'existence supposée au-dessus.

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;
}
139
répondu thomas-peter 2017-05-23 12:18:23

le profileur GoogleChrome tas vous permet d'inspecter l'utilisation de la mémoire objet.

vous devez être en mesure de localiser l'objet dans la trace qui peut être délicate. Si vous épinglez l'objet à la fenêtre globale, il est assez facile de le trouver à partir du mode de listing "containing".

dans la capture d'écran ci-jointe, j'ai créé un objet appelé" testObj " sur la fenêtre. J'ai alors localisé dans le profileur (après avoir fait un enregistrement) et il montre la taille complète du objet et tout ce qui s'y trouve sous "Taille retenue".

Plus de détails sur la mémoire de pannes .

Chrome profiler

dans la capture d'écran ci-dessus, l'objet montre une taille retenue de 60. Je crois que l'unité est octets ici.

82
répondu Guy Bedford 2017-10-03 11:33:45

je viens d'écrire ceci pour résoudre un problème similaire (ish). Il ne fait pas exactement ce que vous cherchez, c'est-à-dire qu'il ne tient pas compte de la façon dont l'interprète stocke l'objet.

mais, si vous utilisez V8, il devrait vous donner une approximation assez bien que le prototypage impressionnant et les classes cachées léchent la plupart de la tête.

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 );
}
64
répondu thomas-peter 2014-01-29 15:08:10

Parfois, je l'utilise pour signaler des objets vraiment gros qui pourraient aller au client à partir du serveur. Il ne représente pas l'empreinte de mémoire. Il vous donne juste approximativement ce que ça coûterait de l'envoyer, ou de le stocker.

note aussi, c'est lent, dev seulement. Mais pour obtenir une réponse approximative avec une ligne de code, ça m'a été utile.

roughObjSize = JSON.stringify(bigObject).length;
39
répondu zstew 2015-09-30 22:43:14

Il ya un module NPM pour obtenir la taille de l'objet , vous pouvez l'installer avec 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));
30
répondu Andrei Karpushonak 2018-07-16 14:20:16

un peu tard pour le parti, Mais voici une solution un peu plus compacte au problème:

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);
18
répondu Dan 2018-06-13 10:37:39

c'est une méthode hacky, mais je l'ai essayé deux fois avec des nombres différents et il semble être cohérent.

Ce que vous pouvez faire est d'essayer et d'allouer un énorme nombre d'objets, comme une ou deux millions d'objets que vous le souhaitez. Mettez les objets dans un tableau pour empêcher le collecteur d'ordures de les libérer (notez que cela ajoutera une légère mémoire au-dessus à cause du tableau, mais j'espère que cela ne devrait pas avoir d'importance et en plus si vous êtes va s'inquiéter des objets étant dans la mémoire, vous les stocker quelque part). Ajouter une alerte avant et après l'attribution et dans chaque alerte vérifier combien de mémoire le processus Firefox prend. Avant d'ouvrir la page avec le test, assurez-vous d'avoir une nouvelle instance Firefox. Ouvrez la page, notez l'utilisation de la mémoire après que l'alerte" avant " est affichée. Fermer l'alerte, attendez que la mémoire allouée. Soustraire la nouvelle mémoire de l'ancienne et de le diviser par le montant des allocations. Exemple:

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');

j'ai essayé cela dans mon ordinateur et le processus avait 48352K de mémoire quand l'alerte" avant " a été montrée. Après l'attribution, Firefox avait 440236K de mémoire. Pour 2millions d'attributions, cela représente environ 200 octets pour chaque objet.

j'ai essayé à nouveau avec 1million d'allocations et le résultat était similaire: 196 octets par objet (je suppose que les données supplémentaires dans 2mill a été utilisé pour le tableau).

donc, voici une méthode hacky qui pourrait vous aider. JavaScript ne fournit pas de méthode "sizeof" pour une raison: chaque implémentation JavaScript est différente. Dans Google Chrome par exemple, la même page utilise environ 66 octets pour chaque objet (à en juger par le Gestionnaire des tâches au moins).

16
répondu Bad Sector 2011-08-30 00:24:27

Désolé Je ne pouvais pas commenter, donc je continue le travail de tomwrong. Cette version améliorée ne comptera pas d'objet plus d'une fois, donc pas de boucle infinie. De plus, je pense que la clé d'un objet devrait aussi être comptée, à peu près.

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);
10
répondu Liangliang Zheng 2011-06-16 06:03:01

je veux savoir si mes efforts de réduction de la mémoire aident réellement à réduire la mémoire

Suite à ce commentaire, voici ce que vous devez faire: Essayez de produire un problème de mémoire - code D'écriture qui crée tous ces objets et augmenter graudally la limite supérieure jusqu'à ce que vous rencontriez un problème (plantage du navigateur, GEL du navigateur ou une erreur de mémoire). Idéalement, vous devriez répéter cette expérience avec différents navigateurs et différents le système d'exploitation.

maintenant il y a deux options: option 1 - Vous n'avez pas réussi à produire le problème de mémoire. Par conséquent, vous vous inquiétez pour rien. Tu n'as pas de problème de mémoire et ton programme va bien.

option 2-vous avez eu un problème de mémoire. Maintenant, demandez-vous si la limite à laquelle le problème s'est produit est raisonnable (en d'autres termes: est-il probable que cette quantité d'objets sera créée à l'utilisation normale de votre code). Si la réponse est "Non" alors vous êtes bien. Sinon, vous savez maintenant combien d'Objets votre code peut créer. Retravailler l'algorithme de manière à ne pas dépasser cette limite.

5
répondu Itay Maman 2009-08-08 09:34:35

si votre principale préoccupation est l'utilisation de la mémoire de votre extension Firefox, je suggère de vérifier avec les développeurs Mozilla.

Mozilla fournit sur son wiki une liste d'outils pour analyser les fuites de mémoire .

4
répondu Vincent Robert 2010-01-09 11:50:41

Chrome developer tools possède cette fonctionnalité. J'ai trouvé cet article très utile et fait exactement ce que vous voulez: https://developers.google.com/chrome-developer-tools/docs/heap-profiling

4
répondu benja2729 2013-01-07 17:45:54

cette bibliothèque Javascript sizeof.js fait la même chose. L'inclure comme ce

<script type="text/javascript" src="sizeof.js"></script>

la fonction sizeof prend un objet comme paramètre et renvoie sa taille approximative en octets. Par exemple:

// 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 fonction sizeof peut gérer les objets qui contiennent des références multiples à d'autres objets et des références récursives.

publié à l'Origine ici .

4
répondu Jayram Singh 2014-05-13 06:47:25

ayant le même problème. J'ai cherché sur Google et je veux partager avec la communauté stackoverflow cette solution.

Important :

j'ai utilisé la fonction partagée par Yan Qing sur 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'en pensez-vous?

4
répondu Ala Eddine JEBALI 2017-01-08 10:44:12
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;
}
2
répondu Boris Rayskiy 2011-10-12 21:06:38

merci à tous ceux qui ont travaillé sur le code pour cela!

je voulais juste ajouter que je cherchais exactement la même chose, mais dans mon cas c'est pour gérer un cache d'objets traités pour éviter d'avoir à re-analyser et traiter des objets provenant d'appels ajax qui peuvent ou non avoir été mis en cache par le navigateur. Cela est particulièrement utile pour les objets qui nécessitent beaucoup de traitement, généralement tout ce qui n'est pas dans le format JSON, mais il peut obtenir très coûteux pour garder ces choses en cache dans un grand projet ou une application/extension qui est laissé en marche pendant une longue période.

de toute façon, je l'utilise pour quelque chose comme:

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
    },
};

C'est un exemple simpliste et peut avoir quelques erreurs, mais il donne l'idée, comme vous pouvez l'utiliser pour accrocher des objets statiques (contenu ne changera pas) avec un certain degré d'intelligence. Cela peut réduire de manière significative les exigences de traitement coûteux que l'objet a dû être produit en premier lieu.

1
répondu Haravikk 2013-04-06 14:42:05

j'utilise Chrome dev tools' Timeline tab , instancie de plus en plus de grandes quantités d'objets, et obtenir de bonnes estimations comme cela. Vous pouvez utiliser html comme celui ci-dessous, comme boilerplate, et le modifier pour mieux simuler les caractéristiques de vos objets (nombre et types de propriétés, etc...). Vous pouvez cliquer sur l'icône trash bit au bas de l'onglet dev tools, avant et après un passage.

<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>

Instanciation de 2 millions de dollars les objets d'une seule propriété (comme dans le code ci-dessus) conduit à un calcul approximatif de 50 octets par objet, sur mon Chrome, maintenant. Changer le code pour créer une chaîne de caractères aléatoire par objet ajoute environ 30 octets par objet, etc. Espérons que cette aide.

1
répondu matanster 2013-12-12 00:17:03

si vous avez besoin de vérifier programmatically pour aprox. taille des objets vous pouvez également consulter cette bibliothèque http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects / que j'ai pu utiliser pour la taille des objets.

sinon je suggère D'utiliser le profileur tas Chrome/Firefox.

1
répondu Alex M 2014-06-26 12:50:51

je crois que vous avez oublié d'inclure '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";
        }
    },
-3
répondu fchas15 2011-11-04 19:26:59

je savoir ce n'est absolument pas le droit de le faire, encore qu'il ai aidé moi à quelques reprises dans le passé pour obtenir l'env objet de la taille de fichier:

écrivez votre objet / réponse à la console ou à un nouvel onglet, copiez les résultats dans un nouveau fichier Bloc-notes, enregistrez-le et vérifiez la taille du fichier. Le fichier notepad lui-même n'est que de quelques octets, donc vous obtiendrez une taille de fichier objet assez précise.

-6
répondu Jeffrey Roosendaal 2016-03-27 21:32:28