为什么-Xss没有增加创建的线程数?

时间:2012-11-28 00:51:21

标签: java multithreading memory jvm

我需要一些关于如何最好地调整内存设置以允许更多线程的输入。

我读了How many threads can a Java VM support?上的冒充并在那里跟着java示例(dieLikeaDog)它确实有效,在死前产生不到800个线程。

与上面的(dieLikeaDog示例)链接一样,代码生成所有线程,直到出现以下错误:java.lang.OutOfMemoryError:无法创建新的本机线程

在命令行上指定Xss(例如java -Xss104k dieLikeADog)不会改变创建的线程数。

我也尝试更改-Xms和-Xmx,但都没有改变它可以产生的线程数。

确实改变线程数的一件事是我的-u ulimit(对于最大用户进程)。将其设置得更大会增加线程数。

我的ulimits如下:

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 46588
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

我有点困惑,因为我在阅读其他示例时认为指定较小的-Xss应该会增加线程数。

是否有其他事情正在阻止Xss工作?

如果重要的话,我使用的是64位fedora 15系统(有6台演出):

  OS:
    Linux
    2.6.42.12-1.fc15.x86_64
    amd64

  JVM:
    Sun Microsystems Inc.
    Java(TM) SE Runtime Environment
    Java HotSpot(TM) 64-Bit Server VM
    1.6.0_27

2 个答案:

答案 0 :(得分:1)

-Xss参数控制为每个线程的堆栈分配的内存量。选择值是平衡堆栈深度与可用内存的情况。设置值-Xss104k表示将为每个启动的线程的堆栈消耗104KB的可用内存(使用-Xmx设置)如果从-Xmx1024k开始,那么在你达到10个线程之前内存将会耗尽,因为1M的内存包括堆和类(permgen)以及线程堆栈。

我的方法是首先检查要在线程中运行的代码。递归繁重的代码需要更多的堆栈。只迭代大量数据的代码可能只需要很少的堆栈。

平衡所涉及的力量的经验方法是减少-Xss,直到得到StackOverflowError。这意味着您的线程正在耗尽堆栈。添加一些填充到最后一个有效的值。如果不导致StackOverflowError的最后一个值是'-Xss1k , the try - Xss2k or - Xss3k . If the stack is wiping out at something like 10k I'd try just bumping to 15k`。

现在你有一个线程堆栈的大小。您的总内存(-Xmx)减去permgen,减去所需的堆数量,可以为您提供线程剩余的内存。如果你需要1000K的堆和50K的permgen,并且你认为堆栈大小为2K,那么要运行十个线程,你将-Xmx1070K视为最小内存。

那说,看看你想要完成什么。为什么需要更多线程?也许答案不是更多的线程,而是一种不同的算法,可以在使用更少的线程时更快地处理数据。

<强>更新

我已经删除了我发现的错误的部分原始答案。

堆栈空间不是从堆空间中获取的,它们是单独分配的。 线程堆栈和堆都计入进程的虚拟内存。减少堆允许更多线程,并且增加它允许更少。

在32位JVM上,我能够将堆栈大小减小到1K。 在64位JVM上,104K是最小值。

我在带有4G内存和2个内核的64位Windows 7机箱上进行了一些测试。

使用32位JVM -Xss8k-Xmx128m,程序为我提供了~5000个线程。这似乎是最好的情况。我没有找到可以增加超过该点的线程数的选项组合。如果我增加了堆大小,则最大线程会下降。线程堆栈大小似乎可能与系统页面大小有关,因为如果我选择的堆栈少于8k,则最大线程实际上会变得更糟。

~5000线程限制似乎也适用于Ubuntu Quantal上的32位JVM。

使用64位JVM,这是一个完全不同的故事。使用-Xss104k-Xmx128m,程序超过50000个线程。那时Windows 真的不开心。它停止响应几分钟,然后开始杀死其他进程。我猜想要释放更多的记忆。

<强>更新

对Ubuntu的更多测试:我发现我有一个虚拟内存的ulimit。在ulimit -v unlimited之后,该程序可以达到~36000个线程。

答案 1 :(得分:0)

原因可能在于您提供的ulimits:

max user processes              (-u) 1024

每个线程都将计入此值。因为您不仅运行JVM,而且已经从该值中扣除了很多线程。

尝试执行

ulimit -u 4000

并重新运行测试(在你执行命令的shell中!),你可以创建的线程数不应该增加。