Сохраненный размер в снимке памяти Chrome - что именно сохраняется? - PullRequest
0 голосов
/ 27 мая 2020

Chrome docs говорит, что сохраненный размер - это «размер памяти, которая освобождается после удаления самого объекта вместе с его зависимыми объектами, которые были недоступны из G *. 1017 * корней ", что вполне справедливо. Однако даже для простых объектов оставшийся размер часто в 3 раза меньше мелкого размера. Я понимаю, что V8 необходимо хранить ссылку на скрытую форму, возможно, некоторые данные для G C и так далее, но иногда объекты имеют сотни дополнительных «сохраненных» байтов, что кажется проблемой, когда вам нужно иметь миллионы таких объекты. Давайте посмотрим на простой пример:

class TestObject {
    constructor( x, y, z ) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

window.arr = [];
for ( let i = 0; i < 100000; i++ ) {
    window.arr.push( new TestObject( Math.random(), Math.random(), Math.random() ) );
}

Вот снимок памяти:

Memory snapshot, shallow size is 24 bytes and retained size is 60 bytes

Мелкий размер - 24 байта, что идеально соответствует тому факту, что мы храним 3 x 8-байтовых двойных. «Дополнительный» размер равен 36 байтам, что позволяет хранить 9 х 4-байтовых указателей (при условии, что сжатие указателей включено). Если мы добавим три дополнительных свойства, дополнительный размер будет 72 (!) Байта, поэтому он зависит от количества свойств. Что там хранится? Можно ли избежать таких огромных накладных расходов на память?

1 Ответ

3 голосов
/ 27 мая 2020

Здесь разработчик V8.

Мелкий размер - это сам объект, состоящий из стандартного заголовка объекта (3 указателя) и 3 внутренних свойств объекта, которые снова являются указателями. Это 6 (сжатых) указателей по 4 байта каждый = 24 байта.

Дополнительный сохраненный размер - это хранилище для трех свойств. Каждый из них представляет собой «HeapNumber», состоящий из 4-байтового указателя карты и 8-байтовой полезной нагрузки. Итак, 3 свойства умножить на 12 байтов = 36 байтов. (Вооружившись этим знанием, неудивительно, что с другими тремя свойствами, которые предположительно также являются числами, это удваивается до 72).

В сумме каждый объект занимает 24 + 36 = 60 байтов.

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

Один Идея экономии памяти (если вы чувствуете, что это важно) состоит в том, чтобы «транспонировать» вашу организацию данных: вместо 1 массива, содержащего 100 000 объектов с 3 числами в каждом, у вас может быть 1 объект, содержащий 3 массива по 100 000 чисел в каждом. В зависимости от вашего варианта использования это может быть или не быть осуществимым подходом: если приходят тройки чисел и go много, то хранить их в одном огромном массиве будет неприятно; тогда как если это набор данных stati c, то обе модели могут быть довольно эквивалентными по удобству использования. Если бы вы сделали это, вы бы избежали повторяющихся накладных расходов на каждый объект; кроме того, массивы могут хранить двойные числа в строке (при условии, что весь массив содержит только числа), поэтому вы сможете хранить те же числа 300K с общим потреблением памяти всего лишь 2,4 МБ.

Если вы попытаетесь заменить объекты с 3 свойствами множеством небольших TypedArrays, вы увидите значительное увеличение использования памяти, потому что TypedArrays имеет гораздо большие накладные расходы на объект, чем простые объекты. Они ориентированы на использование нескольких больших массивов, а не маленьких.

...