尽管这看起来可能是其他问题的重复,但让我解释一下为什么不是这样。
我希望在达到特定内存限制时,使应用程序的特定部分正常降级。我本可以根据剩余的可用物理内存来使用标准,但这并不安全,因为操作系统可以在达到标准之前开始调出我的应用程序使用的内存,这会认为还剩下一些物理内存,并保持出于同样的原因,我无法使用该进程当前使用的物理内存量,因为一旦OS开始换出我,我将继续分配为OS页面内存,因此该数量不再增长。
因此,我根据应用程序分配的内存量(即非常接近虚拟内存大小)选择了一个标准。
这个问题(如何从进程内部确定CPU和内存消耗?)提供了查询当前进程使用的虚拟内存量的好方法,我正是我所需要的。
在Windows上,我正在使用GetProcessMemoryInfo()
和PrivateUsage
字段,效果很好。
在Linux上,我尝试了几种无效的方法(下面列出)。虚拟内存使用对我不起作用的原因是由于在Linux上的NVidia硬件上创建OpenCL上下文时发生了某些事情。驱动程序保留虚拟内存空间的区域,足以容纳所有RAM,所有交换和所有视频内存。我的猜测是对统一地址空间和所有内容都这样做。但这也意味着该进程报告使用了大量内存。例如,在我的系统上,top将在VIRT列中报告23.3 Gb(12 Gb的RAM,6 Gb的交换,2 Gb的视频内存,这为NVidia驱动程序保留了20 Gb)。
在OSX上,通过使用task_info()
和virtual_size
字段,我得到的数字也比预期的大(对于在Windows上甚至不接近1 Gb的应用程序,该数字为几Gb),但不如Linux大。
所以这是一个大问题:如何获得应用程序分配的内存量?我知道这是一个模糊的问题(“分配的内存”是什么意思?),但是我很灵活:
真正重要的是,该数目随着动态分配(新分配,malloc分配)而增长,并在释放内存时减小(我知道这可能与实现有关)。
这是我尝试和/或考虑过的几种解决方案,但对我而言不起作用。
从/ proc / self / status中读取
这是如何从进程内部确定cpu和内存消耗的方法。但是,如上所述,这将返回虚拟内存量,这对我不起作用。
从/ proc / self / statm中读取
非常轻微最坏:根据http://kernelnewbies.kernelnewbies.narkive.com/iG9xCmwB/proc-pid-statm-doesnt-match-with-status,这是指Linux内核代码,这两个值之间的唯一区别是第二个不减去reserved_vm
虚拟内存量。我本来reserved_vm
希望包含OpenCL驱动程序保留的内存,但事实并非如此。
用途mallinfo()
与uordblks
领域
这似乎并不包括所有分配(我猜是new
s缺失了),因为虚拟内存空间增长了+ 2Gb(在完成了一些繁重的工作之后仍然保留了内存),我只看到了mallinfo()
。返回的数字大约增加0.1Gb 。
从/ proc / self / smaps读取[heap]节的大小
对于将虚拟内存空间增加+ 2Gb的工作,此值开始于336,760 Kb左右,最高达到1,019,496 Kb,然后再也没有下降,因此我不确定我是否真的不能依靠这个数字...
监视我的应用程序中的所有内存分配
是的,在理想的世界中,我可以控制分配内存的每个人。但是,这是一个遗留应用程序,使用了大量不同的分配器,一些malloc
,某些new
,某些特定于操作系统的例程等。有些插件可以执行任何所需的工作,可以使用不同的编译器进行编译,因此,尽管这对于真正控制内存非常有用,但这在我的上下文中不起作用。
在OpenCL上下文初始化之前和之后读取虚拟内存大小
尽管这可能是解决问题的一种“ hacky”方法(而且我可能不得不退后),但我真的希望有一种更可靠的查询内存的方法,因为OpenCL上下文可以在我无法控制的地方初始化,并且其他类似但非OpenCL的特定问题可能会蔓延,而我对此一无所知。
所以这就是我所拥有的。我还没有尝试过另一件事,因为它只能在OSX上运行,但是要使用“为什么mstats和malloc_zone_statistics释放后不显示已恢复的内存”中描述的方法。,即使用malloc_get_all_zones()
和malloc_zone_statistics()
,但我认为这可能是与相同的问题mallinfo()
,即未将所有分配都考虑在内。
因此,有人可以建议一种查询Linux中给定进程(以及OSX的内存使用情况,即使这是一种不同的方法)的方式的查询方法(这个术语含糊不清,请参见上文以获取准确性)?
这是我最终使用的内容。我扫描/ proc / self / maps并求和满足我的条件的所有地址范围的大小,即:
这是我的解决方案的代码:
size_t getValue()
{
FILE* file = fopen("/proc/self/maps", "r");
if (!file)
{
assert(0);
return 0;
}
size_t value = 0;
char line[1024];
while (fgets(line, 1024, file) != NULL)
{
ptrdiff_t start_address, end_address;
char perms[4];
ptrdiff_t offset;
int dev_major, dev_minor;
unsigned long int inode;
const int nb_scanned = sscanf(
line, "%16tx-%16tx %c%c%c%c %16tx %02x:%02x %lu",
&start_address, &end_address,
&perms[0], &perms[1], &perms[2], &perms[3],
&offset, &dev_major, &dev_minor, &inode
);
if (10 != nb_scanned)
{
assert(0);
continue;
}
if ((inode == 0) &&
(perms[0] != '-' || perms[1] != '-' || perms[2] != '-') &&
(perms[3] == 'p'))
{
assert(dev_major == 0);
assert(dev_minor == 0);
value += (end_address - start_address);
}
}
fclose(file);
return value;
}
由于这是遍历/ proc / self / maps中的所有行,因此以这种方式查询内存比使用如何从进程内部确定CPU和内存消耗中的“当前进程当前使用的虚拟内存”慢得多。。
但是,它提供的答案更接近我的需求。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句