Jak uzyskać rozmiar obiektu JavaScript?


296

Chcę poznać rozmiar zajmowany przez obiekt JavaScript.

Weź następującą funkcję:

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

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

Teraz tworzę instancję student:

var stud = new Student();

żebym mógł robić takie rzeczy jak

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

itp.

Teraz studobiekt zajmie pewien rozmiar w pamięci. Ma trochę danych i więcej obiektów.

Jak dowiedzieć się, ile pamięci studzajmuje obiekt? Coś jak sizeof()w JavaScript? Byłoby naprawdę niesamowite, gdybym mógł to znaleźć w jednym wywołaniu funkcji, takim jak sizeof(stud).

Przeszukuję Internet od miesięcy - nie mogłem go znaleźć (zadane na kilku forach - brak odpowiedzi).


41
Istnieje (powstanie) wiele powodów, dla których muszę znaleźć rozmiar obiektu w JavaScript. Jestem nowy w JavaScript, więc nie przestrzegam najlepszych praktyk. Nadal się ich uczę. Opracowałem rozszerzenie firefox, które z pewnością wykorzystuje więcej pamięci niż powinno. Pracuję nad niektórymi sposobami (miejmy nadzieję) zmniejszenia zużycia pamięci. Mówię o tysiącach instancji wielu obiektów na zakładkę, więc pamięć ma znaczenie! Chodzi o to, że chcę wiedzieć, czy moje wysiłki na rzecz zmniejszenia pamięci rzeczywiście pomagają w zmniejszeniu pamięci .. i o ile.

1
Jeśli zbudowałeś rozszerzenie FF, radzę zbadać je na wyższym poziomie językowym niż JS - zobacz, jaki wpływ ma to na FF.
annakata

2
Język wyższego poziomu niż JS? co by to było w tym przypadku?

24
I tak nie ma znaczenia rozmiar. Tak to wykorzystujesz. PS: Co za stadnina!
Thomas Eding,

13
@SpencerRuport Powodem numer jeden dla znajomości rozmiaru obiektu są aplikacje działające w trybie html5 offline, w których czasami masz ograniczone miejsce do przechowywania (5-10 Mb może zostać szybko zjedzone w przypadku aplikacji intensywnie wykorzystujących dane).
David

Odpowiedzi:


181

Ponownie rozważyłem kod w mojej oryginalnej odpowiedzi . Usunąłem rekursję i usunąłem przypuszczalne istnienie.

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

35
możesz również pomyśleć o kluczach obiektowych
zupa

8
Każdy, kto wylądował tutaj, szukając najmniejszego typu dla celów fałsz / prawda, wydaje się niezdefiniowany / zerowy.
zupa

3
"よんもじ".lengthma 4 w JavaScript, ale czy jesteś pewien, że ma 8 bajtów, ponieważ kod go zwraca?
syockit

8
Tak. Znaki w JavaScript są przechowywane zgodnie ze specyfikacją 3. edycji ECMA-262 - bclary.com/2004/11/07/#a-4.3.16
thomas-peter

4
Ta funkcja nie liczy referencji ukrytych w zamknięciach. Na przykład var a={n:1}; var b={a:function(){return a}}; roughSizeOfObject(b)- tutaj bznajduje się odniesienie do a, ale roughSizeOfObject()zwraca 0.
Roman Pominov

116

Google Chrome Heap Profiler umożliwia sprawdzenie wykorzystania pamięci obiektów.

Musisz być w stanie zlokalizować obiekt w śladzie, co może być trudne. Po przypięciu obiektu do globalnego okna można go łatwo znaleźć w trybie listy „Ograniczenie”.

Na załączonym zrzucie ekranu utworzyłem w oknie obiekt o nazwie „testObj”. Następnie zlokalizowałem w profilerze (po nagraniu) i pokazuje pełny rozmiar obiektu i wszystkiego w nim pod „zachowanym rozmiarem”.

Więcej informacji na temat awarii pamięci .

Profiler do Chrome

Na powyższym zrzucie ekranu obiekt ma zachowany rozmiar 60. Myślę, że jednostka jest tutaj bajtami.


13
Ta odpowiedź rozwiązała mój problem wraz z: developers.google.com/chrome-developer-tools/docs/… . Szybka wskazówka: wykonaj szybką migawkę sterty, uruchom zadanie, które podejrzewasz, że przecieka, weź nową szybką migawkę sterty i wybierz comparisonwidok na dole. Widać, jakie obiekty zostały utworzone między dwoma migawkami.
Johnride

1
To prawdopodobnie najczystsze rozwiązanie.
Luca Steeb,

Porównanie, wspomniane przez @Johnride, jest teraz rozwijanym menu u góry.
frandroid

Shallow sizewydaje się 40 dla obu { a:"55c2067aee27593c03b7acbe", b:"55c2067aee27593c03b7acbe", c:null, d:undefined }i { c:null, d:undefined }obiektów. Czy to jest w porządku?
efkan

1
Możesz także użyć Google Chrome Heap Profiler z węzła. Jeśli masz węzeł v8 lub wyższy, uruchom go za pomocą node --inspectiw przeglądarce Chrome wpisz about:inspectna pasku adresu URL i poszukaj otwarcia Inspektora węzłów. Utwórz obiekt w węźle CLI, a następnie zrób migawkę sterty.
Gregor

74

Właśnie to napisałem, aby rozwiązać podobny (ish) problem. Nie robi dokładnie tego, czego możesz potrzebować, tzn. Nie bierze pod uwagę sposobu, w jaki interpreter przechowuje obiekt.

Ale jeśli używasz wersji V8, powinno to dać ci całkiem przybliżone przybliżenie, ponieważ niesamowite prototypowanie i ukryte klasy pochłaniają większość kosztów ogólnych.

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

1
@Liangliang Zheng - great point re nieskończona pętla, dzięki. Mam nadzieję, że nie masz nic przeciwko, jeśli ponownie go zagram i zaktualizuję mój po pracy (?)
Thomas-Peter

Zamierzam dziś wieczorem przetestować na stanowisku node.js i uzyskać lepsze współczynniki.
Thomas-Peter

Wiersz „bajty + = recurse (wartość [i])” zgłasza błąd w moim FF 14.01: NS_ERROR_FAILURE: Komponent zwrócił kod błędu: 0x80004005 (NS_ERROR_FAILURE) [nsIDOMHTMLInputElement.selectionStart]. Na jednym z moich obiektów, jeśli spróbuję innego, nie działa, może błąd przeglądarki lub kod nie działa dla każdego obiektu (ten, który nie działa, zawiera funkcje, ten, który działa, nie działa t)
TrySpace

1
Od jednego Toma do drugiego okazało się to bardzo przydatne jako przybliżony wskaźnik tego, gdzie muszę przyciąć talię mojego obiektu. Czy Twoja pani dowiedziała się o Twojej romansie z Javascriptem? Jest kochanką o wysokich wymaganiach alimentacyjnych.
Tom W Hall

4
To PHP (łyk), na które muszę uważać - już dawno przestałem ją kochać, ale ona płaci rachunki. W każdym razie, dzięki Tomowi, opinie, które lubią, są znacznie lepsze niż punkty reputacji.
Thomas-Peter

55

Czasami używam tego do oznaczania naprawdę dużych obiektów, które mogą trafiać do klienta z serwera. Nie reprezentuje miejsca w pamięci. To po prostu przybliża Cię do kosztu wysłania lub przechowywania.

Pamiętaj też, że jest powolny, tylko deweloper. Ale dla uzyskania odpowiedzi na pytanie z jednym wierszem kodu było to dla mnie przydatne.

roughObjSize = JSON.stringify(bigObject).length;

2
Z moich testów wynika, że ​​ta metoda jest znacznie szybsza niż wielkość obiektu w przypadku, ponieważ nie ma powolnego wywołania _.isObject () z lodash. Ponadto zwrócone rozmiary są dość porównywalne w przybliżeniu. Gist gist.github.com/owenallenaz/ff77fc98081708146495 .
Nucleon


5
Nie można używać z okrągłymi strukturami VM1409:1 Uncaught TypeError: Converting circular structure to JSON:( nadal jest przydatna
daje

nie jest to rozmiar binarny w bajtach, ale prosty w użyciu, aby uzyskać przybliżony rozmiar
datdinhquoc

Jest to całkiem świetne, jeśli 1) potrzebujesz tylko szacunkowego wyniku 2) wiesz, że nie masz żadnych okrągłych odniesień 3) możesz pominąć duże wartości i wprowadzić je osobno. Wszystkie były prawdziwe w moim przypadku, więc działa idealnie, miałem tylko jeden duży sznurek w jednym miejscu, na którym mogę po prostu zmierzyć długość.
OZZIE

43

Oto nieco bardziej kompaktowe rozwiązanie problemu:

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

3
więc to jest rozmiar w KB? czy bity?
vincent thorpe

2
@ vincent-thorpe Jest w bajtach.
Dan.

2
Fajny skrypt, jednak wymaga modyfikacji dla cyklicznych odwołań.
Jim Pedid

1
Właśnie przetestowałem twój algorytm na ogromnej tablicy danych w procesie węzłowym, raportuje 13 GB, ale węzeł zużywa 22 GB, masz pojęcie, skąd ta różnica? W pamięci nie ma już nic.
Josu Goñi

3
@ JosuGoñi, nie obliczają ile kosztuje sam obiekt, tylko jego wartość. Wszystkie obiekty zajmują więcej miejsca niż tylko ich wartość, w przeciwnym typeof ...razie nie działałyby.
Alexis Wilke

42

Istnieje moduł NPM, aby uzyskać rozmiar obiektu , można go zainstalować za pomocą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));

sizeof (new Date ()) === 0 i sizeof ({}) === 0. Czy to jest zamierzone?
Philipp Claßen

1
@ PhilippClaßen Oczywiście, że tak. Oba obiekty nie mają właściwości.
Robert,

18

Jest to hacky sposób, ale próbowałem go dwa razy z różnymi liczbami i wydaje się być spójny.

Możesz spróbować przydzielić ogromną liczbę obiektów, na przykład jeden lub dwa miliony obiektów, które chcesz. Umieść obiekty w tablicy, aby zapobiec ich zwolnieniu przez moduł wyrzucania elementów bezużytecznych (pamiętaj, że spowoduje to niewielki narzut pamięci z powodu tablicy, ale mam nadzieję, że nie powinno to mieć znaczenia, a poza tym, jeśli będziesz się martwić, że obiekty będą w pamięci , gdzieś je przechowujesz). Dodaj alert przed i po alokacji, aw każdym alercie sprawdź, ile pamięci zajmuje proces Firefox. Przed otwarciem strony z testem upewnij się, że masz nową instancję przeglądarki Firefox. Otwórz stronę, zwróć uwagę na użycie pamięci po wyświetleniu ostrzeżenia „przed”. Zamknij alert, poczekaj na przydzielenie pamięci. Odejmij nową pamięć od starszej i podziel ją przez liczbę przydziałów.

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

Próbowałem tego na swoim komputerze, a proces miał 48352 KB pamięci, gdy pojawił się alert „przed”. Po alokacji Firefox miał 440236 KB pamięci. Dla 2 milionów alokacji jest to około 200 bajtów na każdy obiekt.

Próbowałem jeszcze raz z alokacją 1 miliona i wynik był podobny: 196 bajtów na obiekt (przypuszczam, że dodatkowe dane w 2 mill zostały użyte dla Array).

Oto hacky sposób, który może ci pomóc. JavaScript nie zapewnia powodu „sizeof” z jakiegoś powodu: każda implementacja JavaScript jest inna. Na przykład w Google Chrome ta sama strona zużywa około 66 bajtów na każdy obiekt (przynajmniej na podstawie menedżera zadań).


Hej .. dzięki za technikę. Miałem to, ponieważ plan B nie zawierał żadnego bezpośredniego sposobu pomiaru zużycia pamięci.

4
Każda implementacja C i C ++ jest również inna. ;) Rozmiar typu danych w C lub C ++ jest specyficzny dla implementacji. Nie widzę powodu, dla którego JavaScript nie mógłby obsługiwać takiego operatora, choć nie służyłby temu samemu celowi ani nie miałby tego samego znaczenia, co w C lub C ++ (które są językami niższego poziomu i mierzą rzeczywisty rozmiar rozmiar typu danych w czasie kompilacji, w przeciwieństwie do zmiennej wielkości dynamicznego obiektu JavaScript w czasie wykonywania).
bambams

12

Przepraszam, że nie mogłem skomentować, więc kontynuuję pracę od tomwrong. Ta ulepszona wersja nie będzie liczyć obiektu więcej niż jeden raz, dlatego nie będzie nieskończonej pętli. Ponadto uważam, że klucz obiektu powinien być mniej więcej liczony.

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

Myślę, że jest to dokładniejsze, ponieważ zlicza klucze, chociaż liczy się klucz „__visited__”
Sam Hasler

Sprawdzanie typeof value === 'object'to za mało i będziesz mieć wyjątki, jeśli wartość to null.
floribon

To płonęło szybko dla mojego obiektu (co jestem całkiem pewny, że ma ponad 5 MB), w porównaniu z dowolną z duplikowanych odpowiedzi @ tomwrong. Był również bardziej dokładny (jak powiedział 3 MB lub mniej więcej), ale wciąż był zbyt daleko od rzeczywistości. Wszelkie wskazówki na temat tego, co może się nie liczyć?
cregox

Nie działa dla mnie. Obiekt levelzawiera dane, ale roughSizeOfObject(level)zwraca zero. (Oczywiście, mojego poziomu zmiennych nie należy mylić z twoim argumentem. Nie sądzę, że cieniowanie zmiennych powinno powodować tutaj problem, a także kiedy zmieniam nazwę „poziomu” w twoim skrypcie, otrzymuję ten sam wynik.) Zrzut ekranu : snipboard.io/G7E5yj.jpg
Luc

10

Mając ten sam problem. Szukałem w Google i chcę podzielić się tym rozwiązaniem ze społecznością Stackoverflow.

Ważne :

Użyłem funkcji udostępnionej przez Yan Qing na 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);

Co o tym myślisz?


3
To pomija funkcje. Jeśli dodam funkcję, obiekt nie będzie już wyświetlany jako większy
Don Rhummy

Nie liczy kluczy
ebg11

7

Chcę wiedzieć, czy moje wysiłki zmierzające do zmniejszenia pamięci rzeczywiście pomagają w zmniejszeniu pamięci

Kontynuując ten komentarz, oto, co powinieneś zrobić: Spróbuj wywołać problem z pamięcią - Napisz kod, który tworzy wszystkie te obiekty i poważnie zwiększ górny limit, dopóki nie napotkasz problemu (awaria przeglądarki, zawieszenie przeglądarki lub błąd Out-Of- błąd pamięci). Idealnie powinieneś powtórzyć ten eksperyment z różnymi przeglądarkami i innym systemem operacyjnym.

Teraz są dwie opcje: opcja 1 - Nie udało się stworzyć problemu z pamięcią. Dlatego martwisz się o nic. Nie masz problemu z pamięcią, a twój program jest w porządku.

opcja 2 - masz problem z pamięcią. Teraz zadaj sobie pytanie, czy limit, na którym wystąpił problem, jest rozsądny (innymi słowy: czy jest prawdopodobne, że ta liczba obiektów zostanie utworzona przy normalnym użyciu twojego kodu). Jeśli odpowiedź brzmi „nie”, to nic ci nie jest. W przeciwnym razie wiesz już, ile obiektów może utworzyć Twój kod. Przerób algorytm tak, aby nie przekroczył tego limitu.


Z punktu widzenia pamięci moje rozszerzenie dodaje pewną liczbę obiektów dla każdej strony / karty otwartej w przeglądarce Firefox. „Liczba” jest proporcjonalna do wielkości strony. Zakładając, że „zaawansowani” użytkownicy mają otwarte gdziekolwiek od 15 do 20 kart, a jeśli strona internetowa ma dużo treści, przeglądarka po pewnym czasie staje się powolna i frustrująco nie reaguje. Dzieje się tak nawet bez mojej wyraźnej próby zaakcentowania aplikacji. Mam plany przepisania kodu, który moim zdaniem ograniczy tworzenie wielu obiektów. Chciałem tylko mieć pewność, że nie. zredukowanych obiektów stanowiło coś, co jest tego warte

@Senthil: ale rozmiar obiektu nie ma znaczenia, chyba że znasz ilość dostępnej pamięci. Ponieważ ilość pamięci prawdopodobnie pozostanie tajemnicą, mówienie w kategoriach #obiektywów jest tak samo przydatne, jak mówienie w kategoriach #bytes
Itay Maman


5

Ta biblioteka JavaScript sizeof.jsrobi to samo. Uwzględnij to w ten sposób

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

Funkcja sizeof przyjmuje obiekt jako parametr i zwraca jego przybliżony rozmiar w bajtach. Na przykład:

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

Funkcja sizeof może obsługiwać obiekty, które zawierają wiele odniesień do innych obiektów i odwołania rekurencyjne.

Pierwotnie opublikowane tutaj .


Jest to wolniejsze i wydaje się być „mniej precyzyjne” niż @liangliang, w moim przypadku użycia.
cregox


2

Ogromne podziękowania dla wszystkich, którzy pracowali nad tym kodem!

Chciałem tylko dodać, że szukałem dokładnie tego samego, ale w moim przypadku jest to zarządzanie pamięcią podręczną przetworzonych obiektów, aby uniknąć konieczności ponownego analizowania i przetwarzania obiektów z wywołań ajax, które mogły być buforowane lub nie przez przeglądarkę. Jest to szczególnie przydatne w przypadku obiektów wymagających dużego przetwarzania, zwykle wszystkiego, co nie jest w formacie JSON, ale utrzymanie tych danych w pamięci podręcznej w dużym projekcie lub aplikacji / rozszerzeniu, które pozostają uruchomione przez długi czas, może być bardzo kosztowne. czas.

W każdym razie używam go do czegoś takiego jak:

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

Jest to uproszczony przykład i może zawierać pewne błędy, ale daje pomysł, ponieważ można go użyć do trzymania obiektów statycznych (zawartość się nie zmieni) z pewnym stopniem inteligencji. Może to znacznie ograniczyć wszelkie kosztowne wymagania przetwarzania, które obiekt musiałby być wyprodukowany w pierwszej kolejności.


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

1

Korzystam z karty Oś czasowa narzędzi deweloperskich Chrome , tworzę instancje coraz większej liczby obiektów i uzyskuję takie dobre oszacowania. Możesz użyć html takiego jak ten poniżej, jako bojlera, i zmodyfikować go, aby lepiej symulować cechy twoich obiektów (liczbę i typy właściwości itp.). Możesz kliknąć ikonę kosza na śmieci na dole tej karty narzędzi programistycznych, przed i po uruchomieniu.

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

Utworzenie wystąpienia 2 milionów obiektów o tylko jednej właściwości (tak jak w powyższym kodzie powyżej) prowadzi obecnie do przybliżonego obliczenia 50 bajtów na obiekt na moim Chromium. Zmiana kodu w celu utworzenia losowego ciągu na obiekt dodaje około 30 bajtów na obiekt itp. Mam nadzieję, że to pomaga.



-3

Myślę, że zapomniałeś dołączyć „tablicę”.

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

1
W JS tablica jest obiektem. W implementacjach mogą występować pewne optymalizacje, ale tablice i obiekty koncepcyjne są takie same.
Kris Walker,

-8

Ja wiem to nie jest absolutnie dobry sposób, żeby to zrobić, jeszcze it've pomógł mi kilka razy w przeszłości, aby uzyskać rozmiar pliku ok obiektu:

Napisz swój obiekt / odpowiedź do konsoli lub nowej karty, skopiuj wyniki do nowego pliku notatnika, zapisz go i sprawdź rozmiar pliku. Sam plik notatnika ma zaledwie kilka bajtów, dzięki czemu uzyskasz dość dokładny rozmiar pliku obiektu.


4
To jest całkowicie błędne. Na przykład rozważ liczbę 1/3 = 0,33333333333333333. Będzie to 18 bajtów przy użyciu twojego podejścia.
korCZis,

2
Powiedziałem, że to było przybliżone . Czasami nie obchodzi Cię, czy jest to 1 MB, czy 1,00001 MB, chcesz tylko oszacować, a następnie ta metoda jest w porządku.
Jeffrey Roosendaal

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.