Выделение самого большого буфера без использования подкачки

В C / C ++ под Linux мне нужно выделить большой (несколько гигабайт) блок памяти для хранения данных в реальном времени от датчика, подключенного к порту Ethernet, и потоковой передачи данных со скоростью около 110 МБ / с. Я хотел бы выделить как можно больше памяти, чтобы максимально увеличить длину последовательности данных, которую я могу сохранить. Тем не менее, мне также нужно убедиться, что не произойдет подкачки диска, поскольку возникающая в результате задержка и ограниченная пропускная способность доступа к диску приводят к переполнению (очень ограниченного) буфера датчика.

Как лучше всего определить, сколько памяти выделить? Ограничен ли я выделением блока немного меньшего размера, чем указанная свободная память, или я могу напрямую взаимодействовать с диспетчером виртуальной памяти Linux?


person Chris Johnson    schedule 14.07.2010    source источник
comment
Чисто из интереса, какой это датчик вы используете?   -  person Konrad    schedule 14.07.2010
comment
Дубликат stackoverflow.com/questions/2513505   -  person Björn Pollex    schedule 14.07.2010
comment
@ Space_C0wb0y: на самом деле это не так.   -  person Hasturkun    schedule 14.07.2010
comment
Получите датчик получше. Или переключитесь на подходящую ОС реального времени. ОС с виртуальной памятью не позволят вам делать то, что вы хотите, если только вы не сделаете что-то странное, например, использование RAM-диска в качестве места подкачки. Я видел 4 ГБ + ОЗУ на другой стороне интерфейса IDE. Правильное питание RAM. Очень быстро. Очень полезно для подрыва ОС, основанной на виртуальной памяти, и для кэширования всего этого в ОЗУ.   -  person Chris Becke    schedule 14.07.2010
comment
@Chris Becke: Linux не заставляет вас делать что-то странное, чтобы сделать буферы не заменяемыми; есть простой системный вызов, чтобы заблокировать их в физической памяти, или вы можете настроить систему вообще без диска подкачки, если хотите. И я обнаружил, что его поведение в реальном времени вполне удовлетворительно для ограничений реального времени порядка нескольких миллисекунд или дольше.   -  person Mike Seymour    schedule 14.07.2010
comment
@Konrad: это камера Dalsa Genie HM1400 @ Space_C0wb0y: спасибо за ссылку на соответствующий вопрос @Chris Becke: Традиционный способ решения этой проблемы - это аппаратный блок с именно тем, что вы предлагаете - встроенной ОС реального времени и большим количеством оперативной памяти. Но из моего бюджета ...   -  person Chris Johnson    schedule 14.07.2010


Ответы (4)


Что ж, под Linux вы можете использовать mlock () / mlockall (), чтобы сохранить диапазон адресов в физической памяти и предотвратить его подкачку. Процесс, использующий mlock, требует для этого нескольких привилегий, подробности есть у man mlock. Я не уверен в максимальном блоке mlock'able (он может отличаться от того, что кажется "свободным"), поэтому, вероятно, может помочь двоичный поиск (заблокируйте диапазон, если это не поможет, уменьшите размер области и т. Д.)

С другой стороны, 110 МБ / с не проблема для твердотельного накопителя. Твердотельный накопитель на 60 ГБ со скоростью записи 280 МБ / с стоит около 200 долларов. Просто скопируйте данные датчика в небольшой буфер записи и передайте их на SSD.

person Nordic Mainframe    schedule 14.07.2010

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

person Tomek Szpakowicz    schedule 14.07.2010
comment
К сожалению, это не специализированная система. Однако у него много оперативной памяти для других целей, поэтому отключение подкачки может быть вариантом. - person Chris Johnson; 14.07.2010
comment
Проверьте использование памяти в течение некоторого времени. Вы можете увидеть, что своп почти никогда не используется, если какое-то приложение не начинает безумно терять память. Я без проблем запускал настольные системы без подкачки. Но для более общего решения используйте mlock (2), как советовал Лютер. И не размещайте все как один непрерывный буфер. У диспетчера памяти могут возникнуть проблемы с ее выделением (или перераспределением). Используйте множество буферов меньшего размера, связанных в один каким-либо интерфейсом. Таким образом вы можете, например, настроить размер буфера во время выполнения. - person Tomek Szpakowicz; 14.07.2010
comment
Поднимите палец вверх за написание баффора: P! - person Cray; 22.05.2011

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

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

Если вы используете только доступную физическую память, вы вообще не должны страдать от подкачки. Использование большего количества приведет к тому, что память других процессов будет перемещена на диск - если эти процессы простаивают, это не должно создавать никаких проблем. Если они активны (то есть используют свою память время от времени), произойдет некоторая подкачка - вероятно, с гораздо меньшей скоростью, чем пропускная способность жесткого диска. Чем больше памяти вы используете, тем больше памяти активных процессов будет выгружено, и будет происходить больше активности HD - на этом этапе максимальный объем памяти, который вы могли бы использовать с приличной производительностью, в значительной степени является результатом проб и ошибок.

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

person adamk    schedule 14.07.2010
comment
Нет необходимости использовать memset(), чтобы обманом заставить систему выделить физическую память. Используйте mlock(), чтобы сделать это явно, и убедитесь, что он никогда не выгружается. - person Mike Seymour; 14.07.2010

Как лучше всего определить, сколько памяти выделить?

Из-за того, как используется виртуальная память, а не заменяемая память ядра, практически невозможно определить, какой объем установленной памяти доступен для приложения.

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

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

Сообщаемая свободная память на самом деле не является «свободной физической памятью». К несчастью.

или я могу более напрямую взаимодействовать с менеджером виртуальной памяти Linux?

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

Однако мне также нужно убедиться, что не будет подкачки диска.

По мере развития ядра Linux знания устаревают довольно быстро, поэтому отнеситесь к тому, что я говорю, с недоверием. Вы можете попробовать поиграть со следующим:

  1. Общая память SysV. Его вообще не меняют местами. См. man shmget.

  2. tmpfs - файловая система в памяти. Память была прикреплена к ОЗУ, по крайней мере, в ранних ядрах 2.6 и, следовательно, не подлежала замене. Чтобы использовать его в качестве памяти, создайте файл в tmpfs, write() что-нибудь в файле (для принудительного выделения памяти), а затем mmap () файл.

person Dummy00001    schedule 14.07.2010
comment
Просто для записей: tmpfs фактически заменяется. Есть еще один вариант rootfs, который никогда не будет заменен. Но только по этой причине с этим нужно быть очень осторожным и не переоценивать. - person Jens Gustedt; 14.07.2010