Как получить размер объекта 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 ]

5 голосов
/ 13 мая 2014

Эта библиотека Javascript sizeof.js делает то же самое. Включите это как это

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

Функция sizeof принимает объект в качестве параметра и возвращает его приблизительный размер в байтах. Например:

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

Функция sizeof может обрабатывать объекты, которые содержат несколько ссылок на другие объекты и рекурсивные ссылки.

Первоначально опубликовано здесь .

4 голосов
/ 07 января 2013

Инструменты разработчика Chrome обладают этой функциональностью. Я нашел эту статью очень полезной и делает именно то, что вы хотите: https://developers.google.com/chrome-developer-tools/docs/heap-profiling

4 голосов
/ 09 января 2010

Если ваша основная проблема - использование памяти расширением Firefox, я советую проверить с разработчиками Mozilla.

Mozilla предоставляет в своей вики список инструментов для анализа утечек памяти .

2 голосов
/ 13 октября 2011
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;
}
2 голосов
/ 06 апреля 2013

Большое спасибо всем, кто работал над кодом для этого!

Я просто хотел добавить, что я искал точно такую ​​же вещь, но в моем случае это для управления кэшем обработанных объектов, чтобы избежать необходимости повторного анализа и обработки объектов из вызовов ajax, которые могут или не могут были кэшированы браузером. Это особенно полезно для объектов, которые требуют большой обработки, обычно всего, что не в формате JSON, но может оказаться очень дорогостоящим хранить эти вещи в большом проекте или в приложении / расширении, которое долго работает время.

Во всяком случае, я использую его для чего-то вроде:

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

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

1 голос
/ 26 июня 2014

Если вам нужно программно проверить aprox. Размер объектов вы также можете проверить эту библиотеку http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/, которую я смог использовать для размера объектов.

В противном случае я предлагаю использовать Chrome / Firefox Heap Profiler.

1 голос
/ 12 декабря 2013

Я использую Chrome dev tools ' Вкладка временной шкалы , создаю экземпляры все большего количества объектов и получаю такие хорошие оценки. Вы можете использовать html, подобный приведенному ниже, в качестве примера и изменить его, чтобы лучше имитировать характеристики ваших объектов (количество и типы свойств и т. Д.). Возможно, вы захотите щелкнуть значок мусорного ведра в нижней части вкладки инструментов разработчика, до и после запуска.

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

Создание 2 миллионов объектов только с одним свойством каждый (как в этом коде выше) приводит к грубому вычислению 50 байтов на объект, на моем Chromium, прямо сейчас. Изменение кода для создания случайной строки для объекта добавляет около 30 байт на объект и т. Д. Надеюсь, это поможет.

0 голосов
/ 28 марта 2016

Я знаю это абсолютно неправильный способ сделать это, но в прошлом я несколько раз помогал мне получить приблизительный размер объектного файла:

Запишите ваш объект / ответ на консоль или новую вкладку, скопируйте результаты в новый файл блокнота, сохраните его и проверьте размер файла. Сам файл блокнота занимает всего несколько байтов, поэтому вы получите довольно точный размер объектного файла.

0 голосов
/ 04 ноября 2011

Я полагаю, вы забыли включить 'массив'.

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