6

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

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

me.data_begin = mmap(NULL, capacity(me), prot, MAP_SHARED, me.file.handle, 0);

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

posix_madvise(me.data_begin, capacity(me), MMAP_SEQUENTIAL);

没有成功。:-(

我试过了:

  • 不同的标志 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)

msync(me.data_begin, capacity(me), MS_INVALIDATE).

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

但在Linux 下没有任何效果。有人对我在 Linux 下的问题有想法或成功案例吗?

干杯,大卫

4

1 回答 1

11

Linux 内存管理不同于其他系统。关键原则是,未使用的内存是浪费的内存。在许多方面,Linux 都试图最大限度地利用内存,从而(大多数情况下)获得更好的性能。

并不是说在 Linux 中“什么都行不通” ,而是它的行为与您的预期有些不同。

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

madvice() POSIX 调用用于告诉系统您的应用程序将如何使用页面。但顾名思义,这是一个建议,以便操作系统更好地进行分页和交换决策。这既不是政策也不是命令。

为了演示 madvice() 在 Linux 上的效果,我修改了我给学生的一个练习。在此处查看完整的源代码。我的系统是 64 位的,有 2 GB 的 RAM,现在大约 50% 正在使用中。使用该程序来映射一个 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

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

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

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

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

于 2010-09-24T20:04:02.303 回答