Когда и как происходит смятие памяти mmap'ed?

В моем понимании, mmap'ing файла, который помещается в ОЗУ, будет похож на файл в памяти.

Скажем, что у нас есть 16G RAM, и мы сначала mmap 10G файл, который мы используем некоторое время. Это должно быть достаточно эффективным с точки зрения доступа. Если мы тогда mmap второй 10G файл, это приведет к тому, что первый будет заменен? Или его части? Если да, когда это произойдет? При вызове mmap или при доступе к области памяти только что загруженного файла?

И если мы хотим снова получить доступ к памяти указателя для первого файла, это заставит его загрузить файл подкачки снова? Итак, скажем, мы чередуем чтение между памятью, соответствующей первому файлу и второму файлу, что приведет к катастрофической производительности?

Наконец, если это правда, было бы лучше, чтобы mmap несколько файлов меньшего размера?

Ответ 1

Как уже обсуждалось, ваш файл будет доступен на страницах; на архитектуре x86_64 (и IA32), страница обычно составляет 4096 байт. Итак, очень мало, если какой-либо файл будет загружен в mmap. При первом доступе к какой-либо странице в любом файле ядро ​​сгенерирует ошибку страницы и загрузите часть своего файла. Ядро может предварительно выбирать страницы, поэтому может загружаться более одной страницы. Независимо от того, зависит ли это от вашего шаблона доступа.

В целом, ваша производительность должна быть хорошей, если ваш рабочий набор подходит в памяти. То есть, если вы только регулярно подключаете 3G файл к обоим файлам, если у вас есть 3G-RAM, доступный вашему процессу, все должно быть в порядке.

В 64-битной системе нет причины разбить файлы, и все будет в порядке, если нужные вам части будут соответствовать ОЗУ.

Обратите внимание, что если вы mmap существующего файла, для чтения этого файла не потребуется пространство подкачки. Когда объект поддерживается файлом файловой системы, ядро ​​может читать из этого файла, а не подкачки. Однако, если вы укажете MMAP_PRIVATE в своем вызове mmap, может потребоваться пространство подкачки для хранения измененных страниц, пока вы не вызовете msync.

Ответ 2

В вашем вопросе нет окончательного ответа, так как обмен файлами в ядре также выполняется, и каждое ядро ​​будет иметь другую реализацию (и сам linux предлагает разные профили в зависимости от вашего использования, RT, рабочего стола, сервера...)

Вообще говоря, все, что вы загружаете в память, выполняется с помощью страниц, поэтому ваш файл в формате mmap в памяти загружается (и выгружается) между страницами между всеми уровнями памяти (кэши, оперативная память и своп). Затем, если вы загрузите два 10 ГБ данных в память, у вас будут части как между ОЗУ, так и вашей Swap, и ядро ​​попытается сохранить в RAM страницы, которые вы, вероятно, будете использовать сейчас, и угадать, что вы будете загружать дальше.

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

Вы можете прочитать более подробную информацию о пейджинге ядра в теории виртуальной памяти: