Wie erhalte ich die Größe eines JavaScript-Objekts?

296

Ich möchte wissen, wie groß ein JavaScript-Objekt ist.

Übernehmen Sie die folgende Funktion:

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

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

Jetzt instanziiere ich das student:

var stud = new Student();

damit ich solche Sachen machen kann

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

etc.

Jetzt nimmt das studObjekt eine gewisse Größe im Speicher ein. Es hat einige Daten und mehr Objekte.

Wie finde ich heraus, wie viel Speicher das studObjekt belegt? So etwas wie ein sizeof()in JavaScript? Es wäre wirklich großartig, wenn ich es in einem einzigen Funktionsaufruf wie herausfinden könnte sizeof(stud).

Ich habe monatelang im Internet gesucht - konnte es nicht finden (in einigen Foren gefragt - keine Antworten).

user4642212
quelle
41
Es gibt (wird auftreten) viele Gründe, warum ich die Größe eines Objekts in JavaScript ermitteln muss. Ich bin neu in JavaScript und befolge daher nicht die Best Practices. Ich lerne sie immer noch. Ich habe eine Firefox-Erweiterung entwickelt, die sicher mehr Speicher benötigt, als sie sollte. Ich arbeite an einigen Möglichkeiten, um (hoffentlich) die Speichernutzung zu reduzieren. Ich spreche über Tausende von Instanzen, viele Objekte pro Registerkarte, also ist Speicher wichtig! Die Sache ist, ich möchte wissen, ob meine Bemühungen zur Reduzierung des Gedächtnisses tatsächlich dazu beitragen, das Gedächtnis zu reduzieren. Und um wie viel.
1
Wenn Sie eine FF-Erweiterung erstellt haben, empfehle ich Ihnen, eine höhere Sprachstufe als JS zu untersuchen - sehen Sie, welche Auswirkungen dies auf FF selbst hat.
Annakata
2
Höhere Sprache als JS? Was wäre das in diesem Fall?
24
Es ist sowieso nicht die Größe, die zählt. So benutzt du es. PS: Was für ein Hengst!
Thomas Eding
13
@SpencerRuport Der Hauptgrund für die Kenntnis der Objektgröße ist für HTML5-Offline-fähige Anwendungen, bei denen der Speicherplatz manchmal begrenzt ist (5-10 MB können für eine datenintensive Anwendung schnell aufgebraucht werden).
David

Antworten:

181

Ich habe den Code in meiner ursprünglichen Antwort neu berücksichtigt . Ich habe die Rekursion entfernt und den angenommenen Existenzaufwand entfernt.

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;
}
thomas-peter
quelle
35
Vielleicht möchten Sie auch an die Objektschlüssel denken
zupa
8
Jeder, der hier gelandet ist und nach dem kleinsten Typ für die Zwecke von false / true gesucht hat, scheint undefiniert / null zu sein.
Zupa
3
"よんもじ".lengthist 4 in Javascript, aber sind Sie sicher, dass es 8 Bytes sind, da Ihr Code es zurückgibt?
Syockit
8
Ja. Zeichen in JavaScript werden gemäß ECMA-262 3rd Edition Specification gespeichert - bclary.com/2004/11/07/#a-4.3.16
thomas-peter
4
Diese Funktion zählt keine Referenzen, die in Abschlüssen versteckt sind. Zum Beispiel var a={n:1}; var b={a:function(){return a}}; roughSizeOfObject(b)- hier wird bverwiesen a, aber roughSizeOfObject()zurückgegeben 0.
Roman Pominov
117

Mit dem Google Chrome Heap Profiler können Sie die Verwendung des Objektspeichers überprüfen.

Sie müssen in der Lage sein, das Objekt in der Ablaufverfolgung zu finden, was schwierig sein kann. Wenn Sie das Objekt an das globale Fenster anheften, ist es im Listenmodus "Containment" ziemlich einfach zu finden.

Im angehängten Screenshot habe ich im Fenster ein Objekt namens "testObj" erstellt. Ich habe mich dann im Profiler befunden (nachdem ich eine Aufnahme gemacht habe) und es zeigt die volle Größe des Objekts und alles darin unter "beibehaltene Größe".

Weitere Details zu den Speicherausfällen .

Chrome-Profiler

Im obigen Screenshot zeigt das Objekt eine beibehaltene Größe von 60. Ich glaube, die Einheit besteht hier aus Bytes.

Guy Bedford
quelle
13
Diese Antwort löste mein Problem zusammen mit: developer.google.com/chrome-developer-tools/docs/… . Schneller Tipp: Machen Sie einen schnellen Heap-Snapshot, führen Sie die Aufgabe aus, von der Sie vermuten, dass sie undicht ist, machen Sie einen neuen schnellen Heap-Snapshot und wählen Sie die comparisonAnsicht unten aus. Es wird deutlich, welche Objekte zwischen den beiden Schnappschüssen erstellt wurden.
Johnride
1
Dies ist wahrscheinlich die sauberste Lösung.
Luca Steeb
Der von @Johnride erwähnte Vergleich ist jetzt ein Pulldown-Menü oben.
frandroid
Shallow sizescheint , als 40 für beide { a:"55c2067aee27593c03b7acbe", b:"55c2067aee27593c03b7acbe", c:null, d:undefined }und { c:null, d:undefined }Objekte. Ist es o.k?
Efkan
1
Sie können den Google Chrome Heap Profiler auch vom Knoten aus verwenden. Wenn Sie Node v8 oder höher haben, starten Sie ihn mit node --inspectund in Chrome geben Sie ihn about:inspectin die URL-Leiste ein und suchen Sie nach dem Öffnen des Node Inspector. Erstellen Sie Ihr Objekt in der Knoten-CLI und erstellen Sie dann einen Heap-Snapshot.
Gregor
74

Ich habe dies gerade geschrieben, um ein ähnliches (ish) Problem zu lösen. Es macht nicht genau das, wonach Sie suchen, dh es berücksichtigt nicht, wie der Interpreter das Objekt speichert.

Wenn Sie jedoch V8 verwenden, sollte dies eine ziemlich gute Annäherung sein, da das großartige Prototyping und die versteckten Klassen den größten Teil des Overheads ausmachen.

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 );
}
thomas-peter
quelle
1
@Liangliang Zheng - toller Punkt für Endlosschleife, danke. Ich hoffe, es macht dir nichts aus, wenn ich es ein bisschen wieder
aufführe
Ich werde dies heute Abend mit node.js testen und einige bessere Koeffizienten erhalten.
Thomas-Peter
Die Zeile 'bytes + = recurse (value [i])' löst einen Fehler in meinem FF 14.01 aus: NS_ERROR_FAILURE: Von der Komponente zurückgegebener Fehlercode: 0x80004005 (NS_ERROR_FAILURE) [nsIDOMHTMLInputElement.selectionStart]. Wenn ich auf einem meiner Objekte ein anderes versuche, ist dies möglicherweise nicht der Fall, möglicherweise ein Browserfehler, oder der Code funktioniert nicht für jedes Objekt (das nicht funktionierende enthält Funktionen, das funktionierende nicht). t)
TrySpace
1
Von einem Tom zum anderen war dies ein sehr nützlicher Indikator dafür, wo ich meine Objekttaille kürzen musste. Hat Ihre Frau von Ihrer Affäre mit Javascript erfahren? Sie ist eine wartungsintensive Geliebte.
Tom W Hall
4
Es ist PHP (Schluck), auf das ich achten muss - ich habe vor langer Zeit aufgehört, sie zu lieben, aber sie bezahlt die Rechnungen. Wie auch immer, danke Tom, Feedback, das gefällt, ist viel besser als Reputationspunkte.
Thomas-Peter
55

Manchmal benutze ich dies, um wirklich große Objekte zu kennzeichnen, die möglicherweise vom Server an den Client gesendet werden. Es repräsentiert nicht den Footprint im Speicher. Sie erhalten nur ungefähr das, was es kosten würde, es zu senden oder zu speichern.

Beachten Sie auch, dass es langsam ist, nur Entwickler. Aber um eine Standardantwort mit einer Codezeile zu erhalten, war es für mich nützlich.

roughObjSize = JSON.stringify(bigObject).length;
zstew
quelle
2
Aus meinen Tests geht hervor, dass diese Methode erheblich schneller ist als die Objektgröße des Falls, da sie nicht den langsamen Aufruf von _.isObject () von lodash enthält. Darüber hinaus sind die zurückgegebenen Größen für grobe Schätzungen ziemlich vergleichbar. Gist gist.github.com/owenallenaz/ff77fc98081708146495 .
Nucleon
3
Schade, dass es aufbricht, wenn das Objekt zu groß ist . :(
Cregox
5
Kann nicht mit kreisförmigen Strukturen verwendet werden VM1409:1 Uncaught TypeError: Converting circular structure to JSON:( immer noch nützlich
givanse
Dies ist keine binäre Größe in Bytes, sondern einfach zu verwenden, um die ungefähre Größe zu erhalten
datdinhquoc
Dies ist ziemlich gut, wenn 1) Sie nur eine Schätzung des Baseballstadions benötigen 2) Sie wissen, dass Sie keine Zirkelverweise haben 3) Sie große Werte weglassen und sie separat anzeigen können. All dies stimmte in meinem Fall, funktioniert also perfekt. Ich hatte nur eine große Saite an einer Stelle, an der ich nur die Länge messen kann.
OZZIE
44

Hier ist eine etwas kompaktere Lösung für das Problem:

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);
Dan
quelle
3
Das ist also die Größe in KB? oder Bits?
Vincent Thorpe
2
@ Vincent-Thorpe Es ist in Bytes.
Dan
2
Schönes Skript, muss jedoch für zyklische Referenzen geändert werden.
Jim Pedid
1
Ich habe gerade Ihren Algorithmus an einem riesigen Datenfeld innerhalb eines Knotenprozesses getestet. Er meldet 13 GB, aber der Knoten verbraucht 22 GB. Haben Sie eine Vorstellung davon, woher der Unterschied kommt? Es ist nichts mehr im Gedächtnis.
Josu Goñi
3
@ JosuGoñi, sie berechnen nicht, wie viel das Objekt selbst nimmt, sondern nur seinen Wert. Alle Objekte benötigen mehr Platz als nur ihren Wert, sonst typeof ...würden sie nicht funktionieren.
Alexis Wilke
42

Es gibt ein NPM-Modul zum Abrufen der Objektgröße , mit dem Sie es installieren könnennpm 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));
Andrei Karpushonak
quelle
sizeof (new Date ()) === 0 und sizeof ({}) === 0. Ist das beabsichtigt?
Philipp Claßen
1
@ PhilippClaßen Offensichtlich ist es. Beide Objekte haben keine Eigenschaften.
Robert
18

Dies ist eine hackige Methode, aber ich habe es zweimal mit verschiedenen Zahlen versucht und es scheint konsistent zu sein.

Sie können versuchen, eine große Anzahl von Objekten zuzuweisen , z. B. ein oder zwei Millionen Objekte der gewünschten Art. Platzieren Sie die Objekte in einem Array, um zu verhindern, dass der Garbage Collector sie freigibt (beachten Sie, dass dies aufgrund des Arrays einen leichten Speicheraufwand verursacht, aber ich hoffe, dass dies keine Rolle spielt und außerdem, wenn Sie sich Sorgen machen, dass sich Objekte im Speicher befinden , Sie speichern sie irgendwo). Fügen Sie vor und nach der Zuweisung eine Warnung hinzu und überprüfen Sie in jeder Warnung, wie viel Speicher der Firefox-Prozess belegt. Stellen Sie vor dem Öffnen der Seite mit dem Test sicher, dass Sie über eine neue Firefox-Instanz verfügen. Öffnen Sie die Seite und beachten Sie die Speichernutzung, nachdem die Warnung "Vorher" angezeigt wurde. Schließen Sie die Warnung und warten Sie, bis der Speicher zugewiesen wurde. Subtrahieren Sie den neuen Speicher vom älteren und dividieren Sie ihn durch die Anzahl der Zuordnungen.

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 versucht und der Prozess hatte 48352 KB Speicher, als die Warnung "Vorher" angezeigt wurde. Nach der Zuweisung hatte Firefox 440236 KB Speicher. Bei 2 Millionen Zuordnungen sind dies ungefähr 200 Bytes für jedes Objekt.

Ich habe es erneut mit 1 Million Zuordnungen versucht und das Ergebnis war ähnlich: 196 Bytes pro Objekt (ich nehme an, die zusätzlichen Daten in 2 Mill wurden für Array verwendet).

Hier ist eine hackige Methode, die Ihnen helfen könnte. JavaScript bietet aus einem bestimmten Grund keine "sizeof" -Methode: Jede JavaScript-Implementierung ist anders. In Google Chrome verwendet dieselbe Seite beispielsweise ungefähr 66 Byte für jedes Objekt (zumindest nach dem Task-Manager).

Schlechter Sektor
quelle
Hey .. danke für die Technik. Ich hatte das als Plan B, falls es keinen direkten Weg gab, die Speichernutzung zu messen.
4
Jede C- und C ++ - Implementierung ist ebenfalls unterschiedlich. ;) Die Größe eines Datentyps in C oder C ++ ist implementierungsspezifisch. Ich sehe keinen Grund, warum JavaScript einen solchen Operator nicht unterstützen könnte, obwohl es nicht den gleichen Zweck erfüllen oder die gleiche Bedeutung haben würde wie in C oder C ++ (die untergeordnete Sprachen sind und die tatsächliche Größe eines festen Operators messen). Größe Datentyp zur Kompilierungszeit im Gegensatz zur variablen Größe eines dynamischen JavaScript-Objekts zur Laufzeit).
Bambams
12

Entschuldigung, ich konnte keinen Kommentar abgeben, also setze ich einfach die Arbeit von Tomwrong fort. Diese erweiterte Version zählt Objekte nicht mehr als einmal, also keine Endlosschleife. Außerdem denke ich, dass der Schlüssel eines Objekts ungefähr gezählt werden sollte.

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);
Liangliang Zheng
quelle
Ich denke, dies ist genauer, da es die Schlüssel zählt, obwohl es den Schlüssel '__visited__' zählt
Sam Hasler
Das Überprüfen typeof value === 'object'reicht nicht aus und Sie haben Ausnahmen, wenn der Wert ist null.
Floribon
Dies war für mein Objekt (von dem ich ziemlich sicher bin, dass es weit über 5 MB liegt) sehr schnell, im Vergleich zu den betrogenen Antworten von @ tomwrong. Es war auch genauer (wie es 3 MB oder so sagte), aber immer noch viel zu weit von der Realität entfernt. Irgendwelche Hinweise darauf, was es möglicherweise nicht zählt?
Cregox
Funktioniert bei mir nicht Das Objekt levelenthält Daten, roughSizeOfObject(level)gibt jedoch Null zurück. (Meine variable Ebene ist natürlich nicht mit Ihrem Argument zu verwechseln. Ich denke nicht, dass das Abschatten von Variablen hier ein Problem verursachen sollte, und auch wenn ich die Ebene in Ihrem Skript umbenenne, erhalte ich das gleiche Ergebnis.) Screenshot : snipboard.io/G7E5yj.jpg
Luc
10

Das gleiche Problem haben. Ich habe bei Google gesucht und möchte diese Lösung mit der Stackoverflow-Community teilen.

Wichtig :

Ich habe die von Yan Qing auf github https://gist.github.com/zensh/4975495 gemeinsam genutzte Funktion verwendet

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 denkst du darüber?

Ala Eddine JEBALI
quelle
3
Dies vermisst Funktionen. Wenn ich eine Funktion hinzufüge, wird das Objekt nicht größer
angezeigt
Zählt keine Schlüssel
ebg11
7

Ich möchte wissen, ob meine Bemühungen zur Reduzierung des Gedächtnisses tatsächlich zur Reduzierung des Gedächtnisses beitragen

Im Anschluss an diesen Kommentar sollten Sie Folgendes tun: Versuchen Sie, ein Speicherproblem zu erzeugen - Schreiben Sie Code, der alle diese Objekte erstellt, und erhöhen Sie die Obergrenze grafisch, bis Sie auf ein Problem stoßen (Browserabsturz, Einfrieren des Browsers oder ein Out-Of-). Speicherfehler). Idealerweise sollten Sie dieses Experiment mit verschiedenen Browsern und verschiedenen Betriebssystemen wiederholen.

Jetzt gibt es zwei Möglichkeiten: Option 1 - Es ist Ihnen nicht gelungen, das Speicherproblem zu erzeugen. Daher sorgen Sie sich um nichts. Sie haben kein Speicherproblem und Ihr Programm ist in Ordnung.

Option 2: Sie haben ein Speicherproblem. Fragen Sie sich nun, ob die Grenze, an der das Problem aufgetreten ist, angemessen ist (mit anderen Worten: Ist es wahrscheinlich, dass diese Anzahl von Objekten bei normaler Verwendung Ihres Codes erstellt wird)? Wenn die Antwort "Nein" lautet, geht es Ihnen gut. Ansonsten wissen Sie jetzt, wie viele Objekte Ihr Code erstellen kann. Überarbeiten Sie den Algorithmus so, dass er diese Grenze nicht überschreitet.

Itay Maman
quelle
Unter dem Gesichtspunkt des Speichers fügt meine Erweiterung eine Reihe von Objekten für jede Seite / Registerkarte hinzu, die in Firefox geöffnet ist. Die "Zahl" ist proportional zur Größe der Seite. Angenommen, "Power" -Benutzer haben zwischen 15 und 20 Registerkarten geöffnet, und wenn die Webseite viele Inhalte enthält, reagiert der Browser nach einiger Zeit langsam und reagiert frustrierend nicht mehr. Dies geschieht auch ohne dass ich explizit versuche, die App zu betonen. Ich habe vor, den Code neu zu schreiben, von dem ich denke, dass er die Objekterstellung erheblich reduzieren wird. Ich wollte nur sicher sein, dass die Nr. Die
@Senthil: Die Objektgröße hat jedoch keine Bedeutung, es sei denn, Sie kennen die Menge des verfügbaren Speichers. Da die Menge an Speicher wahrscheinlich ein Rätsel bleibt, ist das Sprechen in Bezug auf #Objekte genauso nützlich wie das Sprechen in Bezug auf #Bytes
Itay Maman
5

Diese Javascript-Bibliothek sizeof.jsmacht das Gleiche. Schließen Sie es so ein

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

Die Funktion sizeof verwendet ein Objekt als Parameter und gibt seine ungefähre Größe in Byte zurück. Beispielsweise:

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

Die Funktion sizeof kann Objekte verarbeiten, die mehrere Verweise auf andere Objekte und rekursive Verweise enthalten.

Ursprünglich hier veröffentlicht .

Jayram
quelle
Dies ist langsamer und scheint in meinem Anwendungsfall "weniger genau" zu sein als bei @liangliang.
Cregox
2

Vielen Dank an alle, die dafür an Code gearbeitet haben!

Ich wollte nur hinzufügen, dass ich genau das Gleiche gesucht habe, aber in meinem Fall dient es dazu, einen Cache mit verarbeiteten Objekten zu verwalten, um zu vermeiden, dass Objekte aus Ajax-Aufrufen, die möglicherweise zwischengespeichert wurden oder nicht, erneut analysiert und verarbeitet werden müssen vom Browser. Dies ist besonders nützlich für Objekte, die viel Verarbeitung erfordern, normalerweise alles, was nicht im JSON-Format vorliegt. Es kann jedoch sehr kostspielig werden, diese Dinge in einem großen Projekt oder einer App / Erweiterung zwischenzuspeichern, die noch lange ausgeführt wird Zeit.

Wie auch immer, ich benutze es für so etwas wie:

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 ist ein vereinfachtes Beispiel und kann einige Fehler enthalten, aber es gibt die Idee, da Sie es verwenden können, um statische Objekte (Inhalte ändern sich nicht) mit einem gewissen Maß an Intelligenz festzuhalten. Dies kann die teuren Verarbeitungsanforderungen, die das Objekt überhaupt stellen musste, erheblich reduzieren.

Haravikk
quelle
1
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;
}
Boris Rayskiy
quelle
1

Ich verwende die Registerkarte " Zeitleiste" der Chrome-Entwicklungstools , instanziiere immer mehr Objekte und erhalte solche guten Schätzungen. Sie können HTML wie dieses unten als Boilerplate verwenden und es ändern, um die Eigenschaften Ihrer Objekte (Anzahl und Art der Eigenschaften usw.) besser zu simulieren. Möglicherweise möchten Sie vor und nach einem Lauf auf das Papierkorbsit-Symbol unten auf der Registerkarte "Entwicklungswerkzeuge" klicken.

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

Das Instanziieren von 2 Millionen Objekten mit jeweils nur einer Eigenschaft (wie in diesem Code oben) führt derzeit zu einer groben Berechnung von 50 Bytes pro Objekt auf meinem Chromium. Durch Ändern des Codes zum Erstellen einer zufälligen Zeichenfolge pro Objekt werden etwa 30 Byte pro Objekt usw. hinzugefügt. Ich hoffe, dies hilft.

Matanster
quelle
-3

Ich glaube, Sie haben vergessen, 'Array' einzuschließen.

  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";
        }
    },
fchas15
quelle
1
In JS ist ein Array ein Objekt. Möglicherweise gibt es einige Optimierungen bei Implementierungen, aber konzeptionell sind Arrays und Objekte identisch.
Kris Walker
-8

Ich weiß, dass dies absolut nicht der richtige Weg ist, aber es hat mir in der Vergangenheit einige Male geholfen, die ungefähre Objektdateigröße zu ermitteln:

Schreiben Sie Ihr Objekt / Ihre Antwort in die Konsole oder auf eine neue Registerkarte, kopieren Sie die Ergebnisse in eine neue Editor-Datei, speichern Sie sie und überprüfen Sie die Dateigröße. Die Editor-Datei selbst besteht nur aus wenigen Bytes, sodass Sie eine ziemlich genaue Größe der Objektdatei erhalten.

Jeffrey Roosendaal
quelle
4
Das ist völlig falsch. Betrachten Sie zum Beispiel die Nummer 1/3 = 0,3333333333333333. Bei Ihrem Ansatz sind es 18 Bytes.
korCZis
2
Ich sagte, es sei ungefähr . Manchmal ist es Ihnen egal, ob es 1 MB oder 1,00001 MB ist, Sie möchten nur eine Schätzung wissen, dann ist diese Methode vollkommen in Ordnung.
Jeffrey Roosendaal
Freche Lösung X]
Lapys