LINUX.ORG.RU

Вопрос про mmap() файлов в память.

 


2

4

Предположим у меня есть файл большого размера с данными в некоторой древовидной структуре.

Необходимо в режиме read only иметь быстрый случайный доступ к разным узлам дерева, но при этом не хотелось бы, что процесс отъедал много реальной оперативной памяти, так как есть другой процесс, которому она нужна. Думаю замапить весь файл в память с помощью функции mmap().

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

Или я слишком много хочу от ОС?

мимокрокодил

Проверь через mincore(2)

anonymous
()

Правильно ли я понимаю, что ОС будет автоматически подгружать в память странички по мере чтения и только те, к которым обратились?

Нет. ОС будет умничать - например, если ты последовательно обратился к нескольким смежным страницам, она наверняка сделает readahead.

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

Да, ОС будет это делать.

tailgunner ★★★★★
()

Всё правильно понимаешь. Есть ещё вызовы mincore, madvise которыми можно более гибко управлять процессом.

slovazap ★★★★★
()

Будет медленней, чем если просто руками читать, что нужно. Если по дереву ходить очень активно, то с mmap вообще кататония наступит.

mv ★★★★★
()
Ответ на: комментарий от tailgunner

Нет. ОС будет умничать - например, если ты последовательно обратился к нескольким смежным страницам, она наверняка сделает readahead.

Не сделает, если предварительно пометить регион как MADV_RANDOM

ttnl ★★★★★
()
Ответ на: комментарий от ttnl

ОС будет умничать - например, если ты последовательно обратился к нескольким смежным страницам, она наверняка сделает readahead.

Не сделает, если предварительно пометить регион как MADV_RANDOM

man madvise

«The kernel is free to ignore the advice.»

Кроме того, у ядра наверняка есть и другие способы умничать. Гарантий нет,

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от ttnl

Закладывайся на детали реализации

/fixed

Я помню, как юзеры пытались возмущаться «вы изменили поведение, так не честно!!!11», и то ли Линус, то ли Алан им объясняли: «поведение соответствует спеке, правьте свои программы».

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Закладывайся на детали реализации

LOL. Единственная функция MADV_RANDOM — препятствование RA. Предупреждение о необязательности исполнения, которое ты видишь в man, — для домохозяек, которые рискнут использовать этот флаг на устройствах, где он в принципе не поддерживается. Широко задокументирован. Не говори глупость, короче

ttnl ★★★★★
()

Выбираешь между mmap vs read или mm vs direct read?

В первом случае и то, и другое оседает в кэше страниц, и то, и другое вызывает reclaim. Путь от обработки page fault до получения страницы примерно такой же, как и при обычном read. Разница минимальна.

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

Я бы попробовал mmap. Думаю, принципиальной разницы не будет.

Также могу посоветовать засунуть файл в сжатый раздел в оперативной памяти, если влезет.

ttnl ★★★★★
()
Ответ на: комментарий от ttnl

В первом случае и то, и другое оседает в кэше страниц, и то, и другое вызывает reclaim. Путь от обработки page fault до получения страницы примерно такой же, как и при обычном read. Разница минимальна.

Забыл про обход развесистой mm_struct и TLB poisoning. Выстрелит при рандомном доступе на большом диапазоне адресов.

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

На NVMe может быть уже наоборот.

mv ★★★★★
()
Ответ на: комментарий от pathfinder

Ок, всем спасибо. Думаю совет с MADV_RANDOM будет весьма полезен.

Сделай оба варианта (mmap и read), результат может удивить.

mv ★★★★★
()
Ответ на: комментарий от mv

Забыл про обход развесистой mm_struct и TLB poisoning. Выстрелит при рандомном доступе на большом диапазоне адресов.

Несколько load'ов — это крохи по отношению к работе с диском и объемам прогоняемых данных. Все кэши будут со страшной скоростью мыться полезной нагрузкой. Доля работы с таблицей страниц будет меньше погрешности измерений.

ttnl ★★★★★
()
Ответ на: комментарий от ttnl

Предупреждение о необязательности исполнения, которое ты видишь в man, — для домохозяек

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

tailgunner ★★★★★
()
Ответ на: комментарий от hateyoufeel

Дреппер это был. В сраче про memcpy и перекрывающиеся регионы.

Нет. Срач с Дреппером о memcpy и сломе flash-плагина - это было недавно. А то, о чем я говорю, было давно. И там был не истеричка Дреппер, а кто-то из героев былых времен.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

то ли Линус, то ли Алан

Дреппер это был.

не Дреппер, а кто-то из героев былых времен.

Я знаю, твой год - он всего от зари до зари...
Мне тысяча лет, потому лишь что мне тридцать три.
(Ю. Кукин, 1965)
ABW ★★★★★
()
Ответ на: комментарий от ttnl

Несколько load'ов — это крохи по отношению к работе с диском и объемам прогоняемых данных. Все кэши будут со страшной скоростью мыться полезной нагрузкой. Доля работы с таблицей страниц будет меньше погрешности измерений.

Кэш не успеет вымыться до того, как TLB падёт. Особенно хорошо заметно, если железо не самое свежее (Ivy Bridge и древнее).

Я сетевой блочный девайс написал, упирается в 50 GbE сеть, а, линейно экстраполируя, в CPU упрётся где-то за 200 GbE. Это уже скорости младших DDR3. Диски очень быстрые нонче.

mv ★★★★★
()
17 октября 2020 г.
Ответ на: комментарий от mv

Будет медленней, чем если просто руками читать, что нужно. Если по дереву ходить очень активно, то с mmap вообще кататония наступит.

Обосновать можно? С чего бы это вдруг.

igloev
()
Ответ на: комментарий от tailgunner

man madvise
«The kernel is free to ignore the advice.»

А какое у вас ядро? В актуальном madvise(2) ничего об этом не сказано.

anonymous
()
Ответ на: комментарий от igloev

Обосновать можно? С чего бы это вдруг.

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

mv ★★★★★
()
Ответ на: комментарий от mv

А вот попробуй.

Думал может есть какое-то понимание внутренностей на тему «почему не mmap()».

Предположим, есть файл на 100 гигов. Он весь заmmap()-лен в память.

Есть индекс страниц этого файла и он всегда в malloc()-выделенной памяти процесса и никогда не освобождается.

100 гигов побито на какие-то страницы, скажем по 16 кб или около того. В памяти каждый 16-кб-ный ключ из файла, например.

Внимание вопрос: чем read() нужной страницы с нужной позиции лучше доступа к этой странице по указателю через mmap?

igloev
()
Ответ на: комментарий от igloev

https://www.akkadia.org/drepper/cpumemory.pdf Главу 4 «Virtual memory» прочитай, включая TLB, если хочется детального понимания.

Вкратце: TLB не резиновый, обход page table очень дорог, а с некоторых пор ещё и page fault очень дорог.

mv ★★★★★
()
Ответ на: комментарий от mv

а что если у тебя tlb и так перегружен

anonymous
()
Ответ на: комментарий от mv

или если ты работаешь только с небольшим количеством мелких участков файла

anonymous
()
Ответ на: комментарий от mv

https://www.akkadia.org/drepper/cpumemory.pdf Главу 4 «Virtual memory» прочитай, включая TLB, если хочется детального понимания.
Вкратце: TLB не резиновый, обход page table очень дорог, а с некоторых пор ещё и page fault очень дорог

Так а в чем отличие то? В лине давным давно используется унифицированный кэш, который работает и с read, и с mmap. Причем, и с тем и с другим ядро предпочитает выносить из кэша страницы не из соображений частоты/давности доступа, а из соображений высвобождения наиболее продолжительных сегментов — как раз для оптимизации трансляции адресов.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Наверное человек хотел сказать, что когда ты mmap() 10 гигабайт, то ты забиваешь TLB на соответствующее количество страниц. А когда ты имеешь buffer pool на 200MB и дочитываешь данныее через read только туда, то TLB отдыхает, потому что 200 меньше 10000. А в файловом кеше страниц больше чем оперативной памяти участвовать не будет.

igloev
()
Ответ на: комментарий от igloev

Наверное человек хотел сказать, что когда ты mmap() 10 гигабайт, то ты забиваешь TLB на соответствующее количество страниц. А когда ты имеешь buffer pool на 200MB и дочитываешь данныее через read только туда, то TLB отдыхает, потому что 200 меньше 10000

TLB — это кэш трансляции, потому при выполнении самого mmap TLB вообще никак не трогается. TLB забивается лишь при выполнении ввода-вывода и чтения из кэша. Однако же, трансляцию при вводе-выводе в кэш ты никак не уберешь, а для чтения из кэша отображать страницы нужно в любом случае.

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

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от anonymous

с PCID не обязательно же

При достаточно долгой работе системного вызова разницы нет. Так-то некоторые системные вызовы и вовсе без смены адресного пространства делаются. До Meltdown/Spectre некоторые ушлые и вовсе ось в одном пространстве с пользовательскими данными размещали.

byko3y ★★★★
()
Ответ на: комментарий от xtouqh

Не путаю. То, о чем я пишу, работало наоборот: ядро было в пространстве пользователя. Собственно, делать наоборот (пользователь в пространстве ядра) было нормой. потому и возник SMAP.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Извинияюсь, наверное не про TLB речь нужно было вести.

А про некую page table. Чем больше диапазон адресов мы мучаем, тем больше отдельных физических разрозненных страниц это может вовлекать в эти таблицы. Надо мне конечно разобраться как там всё внутри устроено, прежде чем такие вопросы задавать.

igloev
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.