452 Stimmen

Wie kann man die Größe eines JavaScript-Objekts ermitteln?

Ich möchte die von einem JavaScript-Objekt belegte Größe wissen.

Nehmen Sie die folgende Funktion:

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

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

Jetzt instanziere ich die student :

var stud = new Student();

so dass ich Dinge tun kann wie

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

usw.

Nun, die stud Objekt wird eine gewisse Größe im Speicher belegen. Es enthält einige Daten und weitere Objekte.

Wie kann ich herausfinden, wie viel Speicherplatz die stud Objekt einnimmt? Etwas wie ein sizeof() in JavaScript? Es wäre wirklich toll, wenn ich es mit einem einzigen Funktionsaufruf herausfinden könnte, z.B. sizeof(stud) .

Ich habe das Internet monatelang durchsucht und konnte es nicht finden (ich habe in einigen Foren gefragt - keine Antworten).

61voto

Andrei Karpushonak Punkte 8630

Es gibt eine NPM-Modul zum Abrufen der Objektgröße sizeof können Sie es installieren mit 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));

18voto

Bad Sector Punkte 732

Das ist eine etwas umständliche Methode, aber ich habe sie zweimal mit verschiedenen Zahlen ausprobiert und sie scheint konsistent zu sein.

Was Sie tun können, ist zu versuchen, einen énorme Anzahl der Objekte, z. B. eine oder zwei Millionen Objekte der von Ihnen gewünschten Art. Legen Sie die Objekte in ein Array, um den Garbage Collector daran zu hindern, sie freizugeben (beachten Sie, dass dies aufgrund des Arrays zu einem leichten Speicher-Overhead führt, aber ich hoffe, dass dies keine Rolle spielt, und außerdem, wenn Sie sich um die Objekte im Speicher sorgen, speichern Sie sie irgendwo). Fügen Sie eine Meldung vor und nach der Zuweisung hinzu und überprüfen Sie in jeder Meldung, wie viel Speicher der Firefox-Prozess benötigt. Bevor Sie die Seite mit dem Test öffnen, stellen Sie sicher, dass Sie eine neue Firefox-Instanz haben. Öffnen Sie die Seite und notieren Sie den Speicherverbrauch, nachdem die "Vorher"-Warnung angezeigt wurde. Schließen Sie die Meldung und warten Sie, bis der Speicher zugewiesen wird. Ziehen Sie den neuen Speicher vom älteren ab und teilen Sie ihn durch die Anzahl der Zuweisungen. Beispiel:

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

Ich habe dies auf meinem Computer ausprobiert und der Prozess hatte 48352K Speicher, als die "Vorher"-Meldung angezeigt wurde. Nach der Zuweisung hatte Firefox 440236K Speicher. Bei 2 Millionen Zuweisungen sind das etwa 200 Byte für jedes Objekt.

Ich versuchte es erneut mit 1 Million Zuweisungen und das Ergebnis war ähnlich: 196 Bytes pro Objekt (ich nehme an, die zusätzlichen Daten in 2mill wurde für Array verwendet).

Hier ist also eine Methode, die Ihnen helfen könnte. JavaScript bietet nicht ohne Grund eine "sizeof"-Methode: Jede JavaScript-Implementierung ist anders. In Google Chrome zum Beispiel verwendet dieselbe Seite etwa 66 Bytes für jedes Objekt (zumindest dem Task-Manager nach zu urteilen).

14voto

Liangliang Zheng Punkte 1703

Tut mir leid, dass ich keinen Kommentar abgeben konnte, also setze ich einfach die Arbeit von tomwrong fort. Diese verbesserte Version zählt die Objekte nur einmal, also keine Endlosschleife. Außerdem denke ich, dass der Schlüssel eines Objekts auch gezählt werden sollte, ungefähr.

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

13voto

Ala Eddine JEBALI Punkte 5683

Ich habe das gleiche Problem. Ich suchte auf Google und ich möchte mit Stackoverflow-Community diese Lösung zu teilen.

Wichtig :

Ich habe die Funktion verwendet, die von Yan Qing o 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);

Was halten Sie davon?

8voto

Itay Maman Punkte 29121

Ich möchte wissen, ob meine Bemühungen zur Gedächtnisreduzierung tatsächlich dazu beitragen, das Gedächtnis zu reduzieren.

Im Anschluss an diesen Kommentar sollten Sie Folgendes tun: Versuchen Sie, ein Speicherproblem zu erzeugen - Schreiben Sie einen Code, der all diese Objekte erzeugt, und erhöhen Sie die Obergrenze so lange, bis Sie auf ein Problem stoßen (Absturz des Browsers, Einfrieren des Browsers oder ein Out-Of-Memory-Fehler). Idealerweise sollten Sie dieses Experiment mit verschiedenen Browsern und verschiedenen Betriebssystemen wiederholen.

Jetzt gibt es zwei Möglichkeiten: Option 1 - Sie haben es nicht geschafft, das Speicherproblem zu erzeugen. Sie machen sich also umsonst Sorgen. Sie haben kein Speicherproblem und Ihr Programm ist in Ordnung.

Option 2: Sie haben ein Speicherproblem. Fragen Sie sich nun, ob die Grenze, bei der das Problem auftrat, vernünftig ist (mit anderen Worten: ist es wahrscheinlich, dass diese Menge an Objekten bei normaler Verwendung Ihres Codes erstellt wird). Wenn die Antwort "Nein" lautet, ist alles in Ordnung. Ansonsten wissen Sie jetzt, wie viele Objekte Ihr Code erzeugen kann. Überarbeiten Sie den Algorithmus so, dass er diese Grenze nicht überschreitet.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X