4

我有几个在 RHEL 6.3 上运行的进程,但由于某种原因,它们超出了线程堆栈大小。

例如,Java 进程在启动时在运行时被赋予 -Xss256k 的堆栈大小,而 C++ 进程在实际代码中使用 pthread_attr_setstacksize() 被赋予 1MB 的线程堆栈大小。

然而,出于某种原因,这些过程并没有遵守这些限制,我不确定为什么。

例如,当我运行

pmap -x <pid> 

对于 C++ 和 Java 进程,我可以看到每个线程都有数百个“匿名”线程(我已经确认是这些进程中的每一个创建的内部工作线程),但是每个分配的值是 64MB,而不是设置的限制以上:

00007fa4fc000000 168 40 40 rw--- [ anon ] 
00007fa4fc02a000 65368 0 0 ----- [ anon ] 
00007fa500000000 168 40 40 rw--- [ anon ] 
00007fa50002a000 65368 0 0 ----- [ anon ] 
00007fa504000000 168 40 40 rw--- [ anon ] 
00007fa50402a000 65368 0 0 ----- [ anon ] 
00007fa508000000 168 40 40 rw--- [ anon ] 
00007fa50802a000 65368 0 0 ----- [ anon ] 
00007fa50c000000 168 40 40 rw--- [ anon ] 
00007fa50c02a000 65368 0 0 ----- [ anon ] 
00007fa510000000 168 40 40 rw--- [ anon ] 
00007fa51002a000 65368 0 0 ----- [ anon ] 
00007fa514000000 168 40 40 rw--- [ anon ] 
00007fa51402a000 65368 0 0 ----- [ anon ] 
00007fa518000000 168 40 40 rw--- [ anon ] 
...

但是,当我使用所有 64MB 的“匿名”线程在上述进程中运行以下命令时

cat /proc/<pid>/limits | grep stack 

Max stack size 1048576 1048576 bytes 

它显示的最大线程堆栈大小为 1MB,所以我对这里发生的事情有点困惑。此外,调用这些程序的脚本也设置了“ulimit -s 1024”。

应该注意的是,这似乎只发生在使用非常高端的机器(例如 48GB RAM,24 个 CPU 内核)时。该问题不会出现在功能较弱的机器上(例如 4GB RAM、2 个 CPU 内核)。

任何帮助理解这里发生的事情将不胜感激。

4

4 回答 4

6

事实证明,RHEL6 2.11 改变了线程模型,使得每个线程尽可能分配到自己的线程池,因此在更大的系统上,您可能会看到它占用了 64MB。在 64 位上,允许的最大线程池数更大。

解决此问题的方法是添加

export LD_PRELOAD=/path/to/libtcmalloc.so 

在启动进程的脚本中(而不是使用 glibc2.11)

有关这方面的更多信息可从以下网址获得:

Linux glibc >= 2.10 (RHEL 6) malloc 可能会显示过多的虚拟内存使用情况 https://www.ibm.com/developerworks/mydeveloperworks/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

glibc bug malloc 为多线程应用程序使用过多内存 http://sourceware.org/bugzilla/show_bug.cgi?id=11261

Apache hadoop 通过设置 MALLOC_ARENA_MAX https://issues.apache.org/jira/browse/HADOOP-7154解决了这个问题

于 2012-11-05T13:39:36.910 回答
0

使用setrlimit(2)/proc/1234/limits设置报告的堆栈大小(可能由PAM子系统在登录时设置)。

我不知道为什么实际的堆栈段似乎每个都是 64Mb。也许您的大型服务器使用大页面(但您的桌面没有)。

您可能会在调用程序的脚本中调用setrlimit(可能使用内置的ulimitbash 或内置的limitzsh)。

于 2012-11-01T16:17:41.383 回答
0

您可以使用ulimit -s <size_in_KB>设置进程的最大堆栈大小。您也可以看到当前限制使用ulimit -s

于 2012-11-01T16:25:28.810 回答
0

@rory根据您的回答,64mb块地址应该是堆地址,但是现在地址就像00007fa50c02a000一样,是堆栈地址,对吗?

于 2014-02-27T04:26:09.640 回答