378 votes

Taille de l'objet JavaScript

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

Prenez la fonction suivante -

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

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

Maintenant j'instancie l'étudiant

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, stud L'objet occupera une certaine taille en mémoire. Il contient des données et d'autres objets.

Comment puis-je savoir combien de mémoire le stud l'objet occupe ?

quelque chose comme un sizeof() en JavaScript ?

Ce serait vraiment génial si je pouvais le trouver en un seul appel de fonction, par exemple

sizeof(stud)

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

2voto

Haravikk Points 445

Un grand merci à tous ceux qui ont travaillé sur le code de ce projet !

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

Bref, je l'utilise pour quelque chose du genre :

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

Il s'agit d'un exemple simpliste qui peut comporter quelques erreurs, mais il donne l'idée, car vous pouvez l'utiliser pour retenir des objets statiques (dont le contenu ne change pas) avec un certain degré d'intelligence. Cela peut réduire considérablement les besoins de traitement coûteux pour lesquels l'objet a dû être produit en premier lieu.

1voto

Boris Rayskiy Points 11
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;
}

1voto

matt Points 946

J'utilise les "Chrome dev tools". Onglet Ligne de temps instanciez des quantités de plus en plus grandes d'objets, et obtenez de bonnes estimations comme ça. Vous pouvez utiliser un 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 de la corbeille en bas de l'onglet Dev Tools, avant et après une exécution.

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

L'instanciation de 2 millions d'objets d'une seule propriété chacun (comme dans le code ci-dessus) conduit à un calcul approximatif de 50 octets par objet, sur mon Chromium, en ce moment. En modifiant le code pour créer une chaîne aléatoire par objet, on ajoute environ 30 octets par objet, etc. J'espère que cela vous aidera.

1voto

Alex M Points 1

Si vous avez besoin de vérifier par programme la taille approximative 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 de tas de Chrome/Firefox.

-3voto

fchas15 Points 1

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X