Как массивы хранятся в виртуальной памяти?

Если у вас есть массив

int arr[100];

Как именно это хранится на современной машине, которая явно использует виртуальную память?

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

Но тогда эта страница хранится на ДИСКЕ или в ОЗУ?


person Brijendar Bakchodia    schedule 09.09.2018    source источник


Ответы (2)


Таким образом, данные могут находиться в разных местах, где они могут изменяться автоматически (под действием операционной системы), и при работе в обычных программах вам вообще не нужно об этом знать.

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

Однако предположим, что массив действительно создан. Виртуальная память создается для создания иллюзии того, что процесс использует исключительно физическую память и/или что у него больше памяти, чем на самом деле доступно в виде физической памяти. Цель этой иллюзии состоит в том, что процессы не должны беспокоиться о том, где на самом деле находятся их данные. И подавляющее большинство нормальных процессов могут этим пренебречь.

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

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

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

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

При отсутствии таких конкретных запросов местонахождение данных зависит от ряда факторов. Если вы объявите статический массив int и инициализируете его данными времени компиляции, данные могут появиться в разделе исполняемого файла, который в конечном итоге генерируется. В некоторых системах при запуске исполняемого файла система загружает в память не весь файл. Он загружает различные части данных из исполняемого файла только тогда, когда на них есть ссылка. Таким образом, эти данные могут изначально находиться на диске. После загрузки в память, если система загружена другими вещами, которым нужна память, система может выбросить эти данные из памяти, чтобы они снова существовали только в исполняемом файле на диске.

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

Как правило, расположение данных может меняться со временем.

person Eric Postpischil    schedule 09.09.2018
comment
отличный ответ! поскольку это было помечено java, вы можете запустить виртуальную машину с -XX:+AlwaysPreTouch, чтобы предварительно коснуться каждой страницы нулями, если это действительно необходимо. И обычно вас гораздо больше заботит (если вы, конечно), если некоторые данные находятся в той же строке кэша, а не на странице, скорее всего. - person Eugene; 09.09.2018
comment
Итак, если массив изначально создан, сохранен в ОЗУ и к нему осуществляется доступ, сохраняется ли он затем в CPU CACHE, чтобы позже мы могли получить еще более быстрый доступ? - person Brijendar Bakchodia; 09.09.2018
comment
@BrijendarBakchodia: Кэш обычно автоматически управляется процессором (ами). Когда процессор загружает что-то из основной памяти, он обычно сохраняет копию в кеше для будущих загрузок или сохранений. Когда процессор сохраняет что-то в памяти, он также может создать копию в кэше. Однако существует ряд вариаций схем кэширования, их слишком много, чтобы обсуждать в комментарии, и, вероятно, слишком много для одного вопроса о переполнении стека. Обычно, когда вещи находятся в кеше, они являются копиями основной памяти; данные в кеше не удаляются из основной памяти. - person Eric Postpischil; 09.09.2018
comment
Хорошо, я вижу. Например, можно ли хранить в кеше структуру бинарного дерева? Struxt имеет левые правые указатели, поэтому я полагаю, что каждый раз индексировать tlb дорого. С другой стороны, массив хранится непрерывно, поэтому его можно кэшировать? - person Brijendar Bakchodia; 10.09.2018
comment
@BrijendarBakchodia: Кэш не используется в качестве памяти, к которой вы можете обращаться и хранить определенные вещи. Я могу только предложить вам поискать учебники, учебники и справочную информацию о том, как работает кеш. Это слишком большая тема для комментариев Stack Overflow. - person Eric Postpischil; 10.09.2018

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

Вам не обязательно использовать пейджинг. Вы можете отключить пейджинг.

Если у нас есть страница размером 4 КБ, этот массив arr уместится на 1 странице.

Он может поместиться на странице размером 4 КБ, но, скорее всего, он не будет выровнен по (или около) границе 4 КБ, поэтому в действительности он, вероятно, будет храниться на двух страницах.

Эта страница хранится на ДИСКЕ или в ОЗУ?

Массивы ничем не отличаются от других структур данных. Они хранятся в памяти (ОЗУ), если ОС не выгружает их на ДИСК, если ей не хватает памяти.

person Andreas    schedule 09.09.2018
comment
Вероятность того, что массив из 100 восьмибайтовых int с требованием выравнивания в восемь байтов, выделенных для местоположения со случайным выбором из равномерного распределения потенциальных смещений страниц, охватывает границу страницы, составляет 99/(4096/8) = 99/512. Для четырехбайтового int это 99/1024. Утверждение в этом ответе, что массив «вероятно, будет храниться на двух страницах», неверно. - person Eric Postpischil; 09.09.2018
comment
@EricPostpischil int составляет 4 байта, поэтому не знаю, откуда взялся этот восьмибайтовый int, но вы правы, я прочитал int[100] как int[1000]. int[100] скорее всего находится на 1 странице, а не на 2 страницах. - person Andreas; 09.09.2018
comment
Это был пример, показывающий вычисления для объектов в целом. - person Eric Postpischil; 09.09.2018
comment
Спасибо. Теперь мне интересно, если я получу доступ к этому массиву, будет ли он сохранен в кеше ЦП, чтобы следующий доступ мог быть быстрым? Предположим, я линейно сканирую массив в своем коде. - person Brijendar Bakchodia; 10.09.2018