【问题标题】:Set swappiness for allocated memory为分配的内存设置 swappiness
【发布时间】:2023-03-04 07:54:06
【问题描述】:

在 C 或 C++ 程序中分配内存时,有一种方法(即使是奇特的)来设置交换性,或者向操作系统提供有关它的提示?

请注意,我不想为整个过程设置交换性,而是在对象/变量级别。

【问题讨论】:

  • 你所说的 swappiness 是什么意思?
  • Swappiness 是一个 Linux 内核参数,用于控制换出运行时内存的相对权重,而不是从系统页面缓存中删除页面。 en.wikipedia.org/wiki/Swappiness
  • 有点像锤子,不提供任何调优,但 POSIX 提供了mlock()mlockall()。这不是一个真正的答案,但从这里开始:pubs.opengroup.org/onlinepubs/7908799/xsh/mlock.html
  • 首先,由于您不交换单个对象或变量,因此您可能的意思是“想在 page 级别执行此操作”。其次,swappiness 参数不是你想要的,它甚至不是 per-process
  • 所以也许可以站出来描述一下您要解决的更高层次的问题?

标签: c++ c malloc


【解决方案1】:

一般来说,如果没有自定义分配器,您将无法做如此细粒度的事情。像mlockposix_madvise 这样的东西在页面级别上工作,它们基本上是开/关开关。因此,对于普通堆,您将为您分配的对象以及碰巧共享相同页面的任何其他对象调整“swappiness”(无论您如何定义它),并且如果您随后分配了一个具有不同的新对象“swappiness”并最终出现在同一页面中,您将覆盖旧设置。

要完成这项工作,您基本上需要为“swappiness”维护一组具有不同堆全局设置的单独堆,并根据需要为每个堆分配对象。并且由于重载operator new 是基于每个类型的,如果您想更改相同类型的不同对象的行为,您将不得不手动从每个堆执行原始分配并执行放置new/delete动态更改所需的“swappiness”。

无论您做什么,分配的任何堆栈都不能使用这种方法,因为堆栈不能像这样拆分,因此调整一个堆栈对象的“交换性”也会调整它以适应大量的东西(变量和诸如返回地址存储和寄存器溢出之类的东西)。

注意:如果您将 Linux 内核 swappiness 称为 @nicolacdnil suggests in the comments,这是不可能的。这是适用于整个系统的内核级别设置,甚至在每个进程级别上都无法调整,更不用说每个对象级别了。

【讨论】:

  • “这是一个适用于整个系统的内核级别设置,它甚至无法在每个进程级别进行调整,更不用说每个对象级别了。”这是我所期待的。谢谢。
【解决方案2】:

你可以使用mlock:

struct MyStruct { // ... };

void * memory_pool = malloc(sizeof(MyStruct));
mlock(memory_pool, sizeof(MyStruct));

MyStruct * my_struct = new(memory_pool) MyStruct();

// (You must check all values returned by `malloc`, `mlock` and `new`!)

my_struct 将在物理内存中,并且在调用munlock() 或进程退出之前不会被交换到磁盘。

【讨论】:

  • 当然,如果你再mallocMyStructmlock 它,它们很可能会出现在同一页面中。如果你在free-ing 他们之前munlock 他们中的任何一个,你将munlock 他们两个。 mlock 是页面粒度,一个布尔标志;单个munlock 可以撤消任意数量的锁。
  • @ShadowRanger 你可能会得到足够大的memory_pool 来容纳所有对象,然后使用一个mlock
  • 另外,mlock/munlock 的 POSIX 标准允许实现要求为锁定传递的地址是页面对齐的,因此不能保证您的示例是可移植的。您需要明确强制页面与 void *pool_base_addr = (void*)((intptr_t)memory_pool & ~(sysconf(_SC_PAGESIZE) - 1)); mlock(pool_base_addr, memory_pool + sizeof(MyStruct) - pool_base_addr); 之类的东西对齐,丑陋但便携(可能需要一两个演员来消除签名警告)。
  • @ShadowRanger 感谢您提供有关对齐的说明,忘记了。
  • 非常同意。尽管您通常无法预先预测所需的对象总数(并且高估意味着无法使用的物理 RAM,这要归功于mlock)。在实践中,您也可以编写自己的分配器(可能借用dlmalloc 或类似的东西)来包装这种形式的通用分配,但这对于可能最好留给操作系统的东西来说将是巨大的努力。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
  • 2018-03-20
  • 2018-10-30
  • 2015-12-05
  • 2017-06-22
  • 1970-01-01
相关资源
最近更新 更多