В C/C++ в соответствии с Linux я должен выделить большой блок (на несколько гигабайтов) памяти для хранения данных реального времени от датчика, подключенного к порту Ethernet и данным потоковой передачи приблизительно в 110MB/s. Я хотел бы выделить самый большой возможный объем памяти, максимизировать длину последовательности данных, которую я могу сохранить. Однако я также должен удостовериться, что не будет никакого обмена с диском, так как получающаяся задержка и ограниченная пропускная способность доступа к диску заставляет датчик (очень ограниченный) буфер переполняться.
Что лучший способ состоит в том, чтобы определить сколько памяти для выделения? Я ограничен просто выделением немного меньшего блока, чем свободная память, о которой сообщают, или я могу взаимодействовать через интерфейс более непосредственно с диспетчером виртуальной памяти Linux?
Ну, в Linux вы можете использовать mlock () / mlockall () для сохранения диапазона адресов в физической памяти и предотвращения его выгрузки. Процесс, использующий mlock, требует для этого нескольких привилегий, подробности есть у man mlock. Я не уверен в максимальном блоке mlock'able (он может отличаться от того, что кажется "свободным"), поэтому, вероятно, может помочь двоичный поиск (заблокируйте диапазон, если это не поможет, уменьшите размер области и т. Д.)
С другой стороны, 110 МБ / с не проблема для твердотельного накопителя. SSD на 60 ГБ со скоростью записи 280 МБ / с стоит около 200 долларов. Просто скопируйте данные датчика в небольшой буфер записи и передайте их на SSD.
Если вы malloc
необходимый объем памяти и записываете в него с такой скоростью, вы все равно получите снижение производительности из-за всех ошибок страниц (т. Е. Сопоставление каждого страница виртуальной памяти в физическую память, что также может включать в себя замену памяти других процессов).
Чтобы избежать этого, вы можете memset
весь выделенный буфер в 0 перед тем, как начать чтение с датчика, чтобы вся необходимая виртуальная память отображалась в физической памяти.
Если вы используете только доступную физическую память, подкачка вообще не будет выполняться. Использование большего количества приведет к тому, что память других процессов будет перемещена на диск - если эти процессы простаивают, это не должно создавать никаких проблем. Если они активны (то есть используют свою память время от времени), произойдет некоторая подкачка - вероятно, с гораздо меньшей скоростью, чем пропускная способность жесткого диска. Чем больше памяти вы используете, тем больше памяти активных процессов будет выгружено, и будет происходить больше активности HD - на этом этапе максимальный объем памяти, который вы могли бы использовать с приличной производительностью, в значительной степени является результатом проб и ошибок.
Используя больше доступной физической памяти, вы определенно вызовете своппинг со скоростью записи в память, и этого невозможно избежать.
Какой лучший способ определить, сколько памяти выделить?
Из-за того, как используется виртуальная память, не заменяемая память ядра, практически невозможно определить, к какому объему установленной памяти может обращаться приложение.
Лучшее, что я могу придумать, это позволить пользователю настраивать, сколько памяти использовать для буферизации.
Ограничиваюсь ли я просто выделением блока чуть меньшего размера, чем заявленная свободная память,
Заявленная свободная память на самом деле не является "свободной физической памятью". К сожалению.
или я могу более непосредственно взаимодействовать с менеджером виртуальной памяти linux?
Это можно сделать, используя пользовательский драйвер устройства, выделяя память непосредственно в пространстве ядра и предоставляя доступ к ней через mmap()
. Обычно это не рекомендуется, но в специализированных случаях, таких как ваш, может сработать.
Однако, я также должен быть уверен, что не будет никакой замены дисков
В темпах развития ядра Linux знания устаревают довольно быстро, так что примите с долей соли то, что я здесь говорю. Вы можете попробовать поиграть со следующим:
SysV разделяемая память. Обычно она не заменяется. См. man shmget
.
tmpfs - файловая система в памяти. Эта память была прикреплена к оперативной памяти, по крайней мере, в ранних версиях ядра 2.6, и поэтому не могла быть заменена. Чтобы использовать ее как память, создайте файл на tmpfs, запишите()
что-нибудь в файл (чтобы заставить память быть фактически выделенной), а затем mmap() файл.
После выделения памяти вы можете
echo 0 > /proc/sys/vm/swappiness
попросить ядро отдать предпочтение освобождению памяти из кеша вместо подкачки.
Всего 0,2 доллара
Если компьютерная система предназначена для получения данных от вашего датчика, вы можете просто отключить подкачку. Затем выделите как можно больший буфер, оставив в системе достаточно памяти только для основных инструментов.