有没有办法查看每个线程的进程的虚拟内存使用情况?

Posted

技术标签:

【中文标题】有没有办法查看每个线程的进程的虚拟内存使用情况?【英文标题】:Is there any way to see virtual memory usgae of a process per thread? 【发布时间】:2014-07-30 11:31:20 【问题描述】:

我使用的是 RHEL 6.3(64 位)。 我对我的多线程 c/c++ 程序进行了一些更改(使用 std:map 来满足特定要求),现在我的项目的初始虚拟内存使用量非常高(大约 900m)。我所做的所有更改都在一个 MACRO 下进行保护。

但是在禁用 MACRO 之后,我也看不到我的进程的虚拟内存使用量有任何减少。

所以我有几个问题要问。

    有什么方法可以找出哪个线程消耗了最大的虚拟内存,以便我可以隔离问题?

    为什么禁用宏后我的进程的虚拟内存使用量没有下降?

    32 位 (RHEL-6.3) 上的相同项目占用的虚拟内存非常少(大约 150m)。 几乎比 64 位操作系统少 6 倍。为什么?

    我使用 top 命令查看虚拟内存使用情况。

【问题讨论】:

为什么这是个问题? 0.9Gbytes 没那么大!内存很便宜。赢得几百兆字节值得您花几天的时间吗? 您是否使用了版本控制系统(git 等)?如果是这样,而不是仅仅更改宏实际上同步回旧版本并尝试它。如果你看到了你所期望的(低内存使用),那么仔细看看所有的变化。不是,开始使用一个。 【参考方案1】:

您可能应该使用valgrind 来寻找memory leaks。当然用调试信息和警告编译你的所有程序(例如g++ -Wall -g)。在 x86-64 上使用最近的 GCC 编译器(例如 gcc-4.9),您还可以使用地址清理程序(-fsanitize=address

在运行(用于测试)您的程序时,您可以使用pmap(1) 来查询其地址空间。另见proc(5)。也可以试试htop。在 64 位系统上对原始程序(未经您的任何修改)进行基准测试。

我希望你在你的代码和你的修改中使用version control system,比如git。

根据定义,address space 对您的process 中的所有线程都是通用的。认为某个特定的线程正在消耗内存是错误的——它是进程本身(即正在运行的程序中的任何线程)。

也许你想为x32 ABI编译。

顺便说一句,每个线程都需要一些内存(用于堆栈、TLS 等)——这当然对其他线程是可见的,例如如果您在其中传递一些指针-并且在 64 位上可能比在 32 位上更多。你有多少线程? (您可能应该避免使用十几个线程)。

【讨论】:

这只是我进程的一个初始虚拟内存。一旦启动。它已经用 valgrind 过滤了。所以没有泄漏的可能性,为什么这个问题只出现在 64 位上。在 32 位上没问题。 当我使用 pmap 查看地址空间时。我看到有很多 [anon] 部分消耗了大部分内存。但我无法弄清楚它们到底是什么? 您没有显示pmap 的输出,但它们可能被malloc 的实现使用或用于线程堆栈或TLS。 共有14个线程。我不能减少线程数,因为每个线程都是为了特定目的。使用这些类似的线程,它之前工作得很好。在我添加这些 std:maps 之前。我观察到的另一件事是这个问题只在 RHEL 6.3 系统中出现。在 centos 上,虚拟内存使用限制为 250m。 您使用的是什么版本的 GCC 以及 C++ 标准库?考虑升级编译器 - 你可以从源代码 tarball 编译 GCC 4.9.1【参考方案2】:

64 位代码指针是 8 字节,而不是 32 位代码的 4 字节。因此,如果您的代码使用大量指针,很容易将堆大小加倍。但这并不能解释 6 倍的大小。

听起来您想了解您的内存使用情况。谷歌搜索“内存分析”来寻找工具。

我通常在我的代码中对自己进行内存分析

extern void * operator new( size_t, const char *, int );

#if 1
#define MY_NEW() new
#else
#define MY_NEW() new( __FILE__, __LINE__ )
#endif

然后在您的代码中将所有“new”的使用更改为 MY_NEW(),并在您想要启用内存分析时更改 #if。运算符 new() 调用 malloc() 并将所有 3 个参数打印到文件中。然后,您可以编写一个脚本来根据需要对数据进行切片和切块。将一个 FILE 和 __LINE_ 组合的所有分配相加通常是一个不错的起点。此方法不包括库(如 STL)中的内存分配。

【讨论】:

【参考方案3】:

使用valgrind --tool=massif (http://valgrind.org/docs/manual/ms-manual.html)分析程序的内存消耗并检查修改前后的内存消耗非常有用。

2) 首先,既然您说“我使用 top 命令查看虚拟内存使用情况”,那么测量进程中的所有内存 (http://valgrind.org/docs/manual/ms-manual.html#ms-manual.not-measured) valgrind --tool=massif --pages-as-heap=yes your-program 并检查生成的报告中的峰值是非常有用的内存消耗和最大分配的堆栈跟踪。

2) 其次,如果在步骤 1 中您了解问题出在堆分配中,请使用 valgrind --tool=massif your_program 检查您的应用程序,并比较修改前后进程的内存消耗。

【讨论】:

【参考方案4】:

您可以为您的进程尝试 ps 命令 grep 并列出线程 ps -eLF ,我不记得确切地按内存使用情况排序。

try top -- command 'H' 显示线程的选项

【讨论】:

以上是关于有没有办法查看每个线程的进程的虚拟内存使用情况?的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程

如何查看虚拟内存使用情况

centos系统查看资源使用情况的工具

怎么查看进程在内存中的地址?

linux 怎样查看内存被哪个进程占用

linux怎么查看占用内存或cpu最多的进程