2017-02-22 10 views
0

Рассмотрим следующие два варианта:В V8 почему массив preallocated потребляет меньше памяти?

const mb_before = process.memoryUsage().heapUsed/1024/1024; 
    const n = 15849; 
    const o = 115; 
    const entries = []; 
    for (var i = 0; i < n; i++) { 
    const subarr = []; 
    for (var j = 0; j < o; j++) { 
     subarr.push(Math.random()); 
    } 
    entries.push(subarr); 
    } 
    const mb_after = process.memoryUsage().heapUsed/1024/1024; 
    console.log('arr using ' + (mb_after - mb_before) + ' megabyte'); 
    // arr using 15.110992431640625 megabyte 

и

const mb_before = process.memoryUsage().heapUsed/1024/1024; 
    const n = 15849; 
    const o = 115; 
    const entries = new Array(n); 
    for (var i = 0; i < n; i++) { 
    const subarr = new Array(o); 
    for (var j = 0; j < o; j++) { 
     subarr[j] = Math.random(); 
    } 
    entries[i] = subarr; 
    } 
    const mb_after = process.memoryUsage().heapUsed/1024/1024; 
    console.log('arr using ' + (mb_after - mb_before) + ' megabyte'); 
    // arr using 12.118911743164062 megabyte 

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

+0

Одним словом? Оптимизация. –

+0

@ T.J.Crowder спасибо за исправление; все равно хотел бы знать, как можно оптимизировать сохранение количества данных по-разному на основе метода создания массива. – Tom

+0

Извините, это не значит, что мой удаленный комментарий как * исправление *, как коллегиальная шутка. Извините, если это не получилось. –

ответ

2

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

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

+1

(разработчик V8 здесь) Это правильно. Когда вы используете конструктор 'Array (n)', V8 может выделять ровно столько места, сколько вам нужно. Когда вы создаете пустой массив (используя '[]' или 'new Array()') и добавляете к нему элементы, V8 увеличивает хранилище в кусках, поэтому в то время, когда вы перестаете добавлять элементы, все равно могут быть некоторые неиспользованные предварительно выделенный резервный магазин. – jmrk

1

Я не считаю это неожиданным. Хотя стандартные массивы aren't really arrays at all *, двигатели JavaScript по умолчанию оптимизированы: рассматривая их так, как если бы они были действительно массивами, когда они могут.

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

В вашем втором примере вы предоставили V8 большую старую подсказку перед тем, как большой вы собираетесь создавать массив. Поэтому разумно, чтобы V8 использовал эту информацию для оптимизации распределения, которое он делает для базового истинного массива.


* (это пост на моей анемии маленького блог)

Смежные вопросы