Linux内存映射文件保留了大量物理内存

Dav*_*ave 5 linux macos mmap

我有一个问题,在多个线程中描述了内存映射和Linux下不断增长的内存消耗.

当我在Linux或MacOS X下打开1GB文件并使用时将其映射到内存中

me.data_begin = mmap(NULL, capacity(me), prot, MAP_SHARED, me.file.handle, 0);
Run Code Online (Sandbox Code Playgroud)

并且顺序读取映射的内存,我的程序使用了越来越多的物理内存,尽管我使用了posix_madvise(甚至在读取过程中多次调用它):

posix_madvise(me.data_begin, capacity(me), MMAP_SEQUENTIAL);
Run Code Online (Sandbox Code Playgroud)

没有成功.:-(

我试过了:

  • 不同的标志MMAP_RANDOM,MMAP_DONTNEED,MMAP_NORMAL没有成功
  • posix_fadvise(me.file.handle,0,capacity(me),POSIX_FADV_DONTNEED)调用mmap之前和之后 - >没有成功

适用于Mac OS X!当我结合起来

posix_madvise(.. MMAP_SEQUENTIAL)
Run Code Online (Sandbox Code Playgroud)

msync(me.data_begin, capacity(me), MS_INVALIDATE).
Run Code Online (Sandbox Code Playgroud)

常驻内存低于16M(我在16mio步后定期调用msync).

但在Linux没有任何作用.有没有人对我在Linux下的问题有想法或成功的故事?

干杯,大卫

Jul*_*ano 8

Linux内存管理与其他系统不同.关键原则是没有使用的内存是浪费的内存.在许多方面,Linux试图最大化内存使用,从而(大部分时间)获得更好的性能.

它不是"在Linux中没有用 ",而是它的行为与你期望的有点不同.

当从mmapped文件中提取内存页面时,操作系统必须决定它将释放(或换出)哪些物理内存页面才能使用.它将查找更易于更换的页面(不需要立即写入磁盘),并且不太可能再次使用.

madvice()POSIX调用用于告诉系统应用程序将如何使用页面.但正如名称所说,这是一个建议,以便操作系统更好地进行分页和交换决策.它既不是政策,也不是订单.

为了演示madvice()对Linux的影响,我修改了我给学生的一个练习.请在此处查看完整的源代码.我的系统是64位的,有2 GB的RAM,现在大约有50%在使用.使用该程序mmap 2 GB文件,按顺序读取并丢弃所有内容.它报告每读取200 MB的RSS使用情况.没有madvice()的结果:

<juliano@home> ~% ./madvtest file.dat n
     0 :     3 MB
   200 :   202 MB
   400 :   402 MB
   600 :   602 MB
   800 :   802 MB
  1000 :  1002 MB
  1200 :  1066 MB
  1400 :  1068 MB
  1600 :  1078 MB
  1800 :  1113 MB
  2000 :  1113 MB
Run Code Online (Sandbox Code Playgroud)

Linux不断推出内存,直到读取大约1 GB.之后,它开始对进程本身施压(因为其他50%的内存由其他进程激活)并稳定到文件结束.

现在,使用madvice():

<juliano@home> ~% ./madvtest file.dat y
     0 :     3 MB
   200 :   202 MB
   400 :   402 MB
   600 :   494 MB
   800 :   501 MB
  1000 :   518 MB
  1200 :   530 MB
  1400 :   530 MB
  1600 :   530 MB
  1800 :   595 MB
  2000 :   788 MB
Run Code Online (Sandbox Code Playgroud)

请注意,Linux决定只将页面分配给进程,直到它达到大约500 MB,比没有madvice()快得多.这是因为在此之后,当前在内存中的页面似乎比通过此过程标记为顺序访问的页面更有价值.VMM中有一个阈值,用于定义何时开始从进程中删除旧页面.

您可能会问为什么Linux将页面分配到大约500 MB并且没有更快地停止,因为它们被标记为顺序访问.无论如何系统都有足够的可用内存页面,或者其他驻留页面太旧而无法保留.在将旧页面保留在内存中似乎不再有用,并为现在运行的程序提供更多页面之间,Linux选择了第二个选项.

即使它们被标记为顺序访问,它只是一个建议.应用程序可能仍希望返回到这些页面并再次阅读它们.或者系统中的另一个应用程序.madvice()调用只说应用程序本身正在做什么,Linux考虑了更大的图景.