[英]Allocating largest buffer without using swap
在Linux下的C / C ++中,我需要分配一个大的(几千兆字节)内存块,以便存储连接到以太网端口的传感器的实时数据和大约110MB / s的流数据。 我想分配尽可能多的内存,以最大化我可以存储的数据序列的长度。 但是,我还需要确保不会进行磁盘交换,因为产生的延迟和磁盘访问带宽有限会导致传感器(非常有限)的缓冲区溢出。
确定要分配多少内存的最佳方法是什么? 我仅限于分配比报告的可用内存稍小的块,还是可以更直接地与linux虚拟内存管理器连接?
好吧,在linux下你可以使用mlock()/ mlockall()来保持物理内存中的地址范围并防止它被换出。 使用mlock的过程需要一些特权来执行此操作,“man mlock”具有详细信息。 我不确定最大的mlock'able块(它可能与看似“免费”的块有所不同),所以可能二进制搜索可能有所帮助(锁定范围,如果失败则减小区域的大小等等。)
另一方面,对于固态硬盘来说,110MB / s并不是真正的问题。 一个60GB的SSD,写入速度为280MB / s,在拐角处的成本约为200美元。 只需将传感器数据复制到一个小的写入缓冲区中,然后将其传输到SSD。
如果计算机系统专用于从传感器接收数据,则可以简单地禁用交换。 然后分配尽可能大的缓冲区,在系统中留下足够的内存仅用于基本工具。
如果你malloc
的内存所需要的量,并在该速度写,你还是会被打到由于所有的页面错误(即虚拟内存的每个页面映射到物理内存,这也可能包括换出内存性能其他过程)。
为了避免这种情况,您可以在开始从传感器读取之前将整个分配的缓冲区memset
为0,以便将所有需要的虚拟内存映射到物理内存。
如果您只使用可用的物理内存,则根本不应该进行交换。 使用更多将导致其他进程的内存交换到磁盘 - 如果这些进程空闲,它不应该造成任何问题。 如果它们处于活动状态(即偶尔使用它们的内存),则会发生一些交换 - 可能比硬盘驱动器带宽低得多。 您使用的内存越多,更多活动进程的内存将被换出,并且会发生更多的HD活动 - 此时,您可以使用的最大内存量具有良好的性能,这几乎是试验和错误的结果。
通过使用超过可用的物理内存,您肯定会导致内存写入速率的交换,并且没有办法避免这种情况。
确定要分配多少内存的最佳方法是什么?
由于虚拟内存的使用方式,不可交换的内核内存,几乎不可能确定应用程序可以访问多少已安装的内存。
我能想到的最好的是允许用户配置用于缓冲的内存量。
我仅限于分配比报告的可用内存略小的块,
报道的免费内存并不是真正的“免费物理内存”。 不幸。
或者我可以更直接地与linux虚拟内存管理器连接?
这可以通过使用自定义设备驱动程序,直接在内核空间中分配内存并通过mmap()
提供对它的访问来完成。 一般不推荐,但适用于您的特殊情况。
但是,我还需要确保不会进行磁盘交换
随着Linux内核开发的步伐,知识变得非常快,所以我要说的就是我所说的。 您可以尝试使用以下内容:
SysV共享内存。 它通常不会被交换。 见man shmget
。
tmpfs - 内存中的文件系统。 至少在早期的2.6内核中,内存被固定到RAM,因此无法交换。 要将它用作内存,请在tmpfs上创建一个文件,在文件中write()
以强制实际分配内存,然后使用mmap()文件。
分配内存后,你可以
echo 0 > /proc/sys/vm/swappiness
要求内核更喜欢从缓存中回收内存而不是交换内存。
只需0.2美元
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.