Как получить размер объекта JavaScript? - PullRequest
243 голосов
/ 08 августа 2009

Я хочу знать размер, занимаемый объектом JavaScript.

Возьмите следующую функцию:

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

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

Теперь я создаю экземпляр student:

var stud = new Student();

чтобы я мог делать такие вещи, как

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

и т.д.

Теперь объект stud будет занимать некоторый размер в памяти. У него есть некоторые данные и больше объектов.

Как узнать, сколько памяти занимает объект stud? Что-то вроде sizeof() в JavaScript? Было бы действительно здорово, если бы я мог найти это в одном вызове функции, например sizeof(stud).

Я искал в Интернете несколько месяцев - не смог его найти (спросили на нескольких форумах - ответов нет).

Ответы [ 19 ]

155 голосов
/ 10 августа 2012

Я изменил код в моем оригинальном ответе . Я удалил рекурсию и удалил предполагаемые накладные расходы на существование.

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;
}
97 голосов
/ 13 сентября 2012

Профилировщик кучи Google Chrome позволяет проверять использование памяти объекта.

Вы должны быть в состоянии найти объект в трассировке, что может быть сложно. Если вы прикрепите объект к глобальному окну, его будет легко найти в режиме списка «Сдерживание».

На прикрепленном скриншоте я создал объект с именем «testObj» в окне. Затем я расположился в профилировщике (после создания записи), и он отображает полный размер объекта и все, что в нем, в «сохраненном размере».

Подробнее о поломках памяти .

Chrome profiler

На приведенном выше снимке экрана объект показывает оставшийся размер 60. Я полагаю, что единица измерения - это байты.

67 голосов
/ 15 июня 2011

Я только что написал это, чтобы решить аналогичную проблему. Он точно не делает то, что вы ищете, то есть не учитывает, как интерпретатор хранит объект.

Но, если вы используете V8, это должно дать вам довольно хорошее приближение, так как классные прототипы и скрытые классы поглощают большую часть накладных расходов.

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 );
}
46 голосов
/ 28 января 2015

Иногда я использую это для пометки действительно больших объектов, которые могут отправляться клиенту с сервера. Это не представляет в памяти след. Он просто дает вам примерно столько, сколько стоило бы отправить его или сохранить.

Также обратите внимание, что это медленно, только для разработчиков. Но для получения приблизительного ответа с одной строкой кода это было полезно для меня.

roughObjSize = JSON.stringify(bigObject).length;
37 голосов
/ 18 мая 2014

Существует модуль NPM для получения объекта размером , вы можете установить его с 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));
31 голосов
/ 01 апреля 2015

Немного опоздал на вечеринку, но вот несколько более компактное решение проблемы:

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);
17 голосов
/ 08 августа 2009

Это хакерский метод, но я пробовал его дважды с разными числами, и, похоже, он соответствует.

Что вы можете сделать, это попытаться выделить огромное количество объектов, например, один или два миллиона объектов того типа, который вам нужен. Поместите объекты в массив, чтобы сборщик мусора не освободил их (обратите внимание, что это приведет к небольшим накладным расходам памяти из-за массива, но я надеюсь, что это не должно иметь значения, кроме того, если вы будете беспокоиться о том, что объекты находятся в памяти храните их где-нибудь). Добавьте предупреждение до и после выделения и в каждом предупреждении проверьте, сколько памяти занимает процесс Firefox. Прежде чем открыть страницу с тестом, убедитесь, что у вас есть свежий экземпляр Firefox. Откройте страницу, обратите внимание на использование памяти после появления предупреждения «до». Закройте оповещение, дождитесь выделения памяти. Вычтите новую память из старой и разделите ее на сумму выделений. Пример:

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

Я попытался сделать это на своем компьютере, и у процесса было 48352 КБ памяти, когда было показано предупреждение «до». После выделения Firefox имел 440236 КБ памяти. Для 2 миллионов выделений это около 200 байтов для каждого объекта.

Я попробовал еще раз с выделением 1 млн., И результат был аналогичным: 196 байт на объект (я полагаю, что дополнительные данные в 2mill использовались для массива).

Итак, вот хакерский метод, который может вам помочь. JavaScript не предоставляет метод «sizeof» по причине: каждая реализация JavaScript отличается. Например, в Google Chrome эта же страница использует около 66 байт для каждого объекта (судя по крайней мере из диспетчера задач).

11 голосов
/ 16 июня 2011

Извините, я не смог прокомментировать, поэтому я просто продолжаю работу от tomwrong. Эта расширенная версия не будет считать объект более одного раза, таким образом, нет бесконечного цикла. Кроме того, я считаю, что ключ объекта также должен быть посчитан примерно.

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);
8 голосов
/ 08 января 2017

Имея ту же проблему. Я искал в Google и хочу поделиться с сообществом stackoverflow этим решением.

Важно :

Я использовал функцию, совместно используемую Ян Цин на 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);

Что вы думаете об этом?

6 голосов
/ 08 августа 2009

Я хочу знать, действительно ли мои усилия по уменьшению памяти помогают уменьшить память

После этого комментария вы должны сделать следующее: Попробуйте создать проблему с памятью - напишите код, который создает все эти объекты и постепенно увеличивает верхний предел, пока не столкнетесь с проблемой (сбой браузера, зависание браузера или ошибка нехватки памяти). В идеале вы должны повторить этот эксперимент с разными браузерами и разными операционными системами.

Теперь есть два варианта: вариант 1 - вам не удалось создать проблему с памятью. Следовательно, вы беспокоитесь ни за что. У вас нет проблем с памятью, и ваша программа в порядке.

вариант 2 - у вас проблема с памятью. Теперь спросите себя, является ли предел, при котором возникла проблема, разумным (другими словами: вероятно, что это количество объектов будет создано при нормальном использовании вашего кода). Если ответ «Нет», то все в порядке. В противном случае вы теперь знаете, сколько объектов может создать ваш код. Переработайте алгоритм так, чтобы он не нарушал этот предел.

...