在不使用交换的情况下分配最大缓冲区

时间:2010-07-14 10:54:37

标签: c++ c linux virtual-memory

在Linux下的C / C ++中,我需要分配一个大的(几千兆字节)内存块,以便存储连接到以太网端口的传感器的实时数据和大约110MB / s的流数据。我想分配尽可能多的内存,以最大化我可以存储的数据序列的长度。但是,我还需要确保不会进行磁盘交换,因为产生的延迟和磁盘访问带宽有限会导致传感器(非常有限)的缓冲区溢出。

确定要分配多少内存的最佳方法是什么?我仅限于分配比报告的可用内存稍小的块,还是可以更直接地与linux虚拟内存管理器连接?

5 个答案:

答案 0 :(得分:9)

好吧,在linux下你可以使用mlock()/ mlockall()来保持物理内存中的地址范围并防止它被换出。使用mlock的过程需要一些特权来执行此操作,“man mlock”具有详细信息。我不确定最大的mlock'able块(它可能与看似“免费”的块有所不同),所以可能二进制搜索可能有所帮助(锁定范围,如果失败则减小区域的大小等等。)

另一方面,对于固态硬盘来说,110MB / s并不是真正的问题。一个60GB的SSD,写入速度为280MB / s,在拐角处的成本约为200美元。只需将传感器数据复制到一个小的写入缓冲区中,然后将其传输到SSD。

答案 1 :(得分:3)

如果计算机系统专用于从传感器接收数据,则可以简单地禁用交换。然后尽可能地分配大缓冲区,在系统中留下足够的内存仅用于基本工具。

答案 2 :(得分:0)

如果malloc所需的内存量并以该速度写入,则由于所有页面错误(即将每页虚拟内存映射到物理内存,您仍然会受到性能影响)也可能包括交换其他进程的内存)。

为了避免这种情况,您可以在开始从传感器读取之前将整个分配的缓冲区memset设置为0,以便将所有需要的虚拟内存映射到物理内存。

如果您只使用可用的物理内存,则根本不应该进行交换。使用更多将导致其他进程的内存交换到磁盘 - 如果这些进程空闲,它不应该造成任何问题。如果它们处于活动状态(即偶尔使用它们的内存),则会发生一些交换 - 可能比硬盘驱动器带宽低得多。您使用的内存越多,更多活动进程的内存将被换出,并且会发生更多的HD活动 - 此时您可以使用的最大内存量具有良好的性能,这几乎是试错的结果。

通过使用超过可用的物理内存,你肯定会导致内存写入速率的交换,并且没有办法避免这种情况。

答案 3 :(得分:0)

  

确定要分配多少内存的最佳方法是什么?

由于虚拟内存的使用方式,不可交换的内核内存,几乎不可能确定应用程序可以访问多少已安装的内存。

我能想到的最好的方法是允许用户配置用于缓冲的内存量。

  

我仅限于分配比报告的可用内存稍小的块,

报告的可用内存并非真正的“免费物理内存”。不幸的是

  

或者我可以更直接地与linux虚拟内存管理器连接吗?

可以通过使用自定义设备驱动程序,直接在内核空间中分配内存并通过mmap()提供对它的访问来完成。一般不推荐,但适用于您的特殊情况。

  

但是,我还需要确保没有磁盘交换

随着Linux内核开发的步伐,知识变得非常快,所以我在这里说的就是盐。您可以尝试使用以下内容:

  1. SysV共享内存。它通常不会被交换。请参阅man shmget

  2. tmpfs - 内存中的文件系统。至少在早期的2.6内核中,内存被固定到RAM,因此无法交换。要将其用作内存,请在tmpfs上创建一个文件,将write()内容创建到文件中(以强制实际分配内存),然后在文件中创建mmap()。

答案 4 :(得分:0)

分配内存后,你可以

echo 0 > /proc/sys/vm/swappiness

要求内核更喜欢从缓存中回收内存而不是交换。

只需我0.2美元