2

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

我阅读了关于Java VM 可以支持多少线程?并遵循那里的java示例(dieLikeaDog),它确实有效,在死前产生了不到800个线程。

如上面的(dieLikeaDog 示例)链接中,代码使所有可以使用的线程,直到出现以下错误结果:java.lang.OutOfMemoryError:无法创建新的本机线程

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

我还尝试更改 -Xms 和 -Xmx 并没有更改它可以产生的线程数。

改变线程数的一件事是 my -u ulimit (用于最大用户进程)。使这个更大确实增加了线程的数量。

我的ulimit如下:

$ 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 gigs 的 ram):

  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
4

2 回答 2

3

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

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

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

现在您有了线程堆栈的大小。你的总内存 ( -Xmx) 减去 permgen,减去所需的堆数量,就可以得到线程剩余的空间。如果您需要 1000K 的堆和 50K 的 permgen,并且您计算出 2K 的堆栈大小,那么运行十个线程,您正在查看-Xmx1070K您的最小内存。

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

更新

我已经删除了我发现不正确的部分原始答案。

栈空间不是取自堆空间,它们是分开分配的。线程堆栈和堆都计入进程的虚拟内存。减少堆允许更多线程,增加它允许更少。

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

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

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

Ubuntu Quantal 上的 32 位 JVM 似乎也存在约 5000 个线程限制。

使用 64 位 JVM,情况就完全不同了。和程序超过 50000 个线程-Xss104k-Xmx128m那时,Windows真的很不高兴。它停止响应几分钟,然后开始杀死其他进程。我猜是为了释放更多内存。

更新:

在 Ubuntu 上进行更多测试:我发现我为虚拟内存设置了 ulimit。在ulimit -v unlimited程序结束〜36000个线程之后。

于 2012-11-28T05:34:03.220 回答
0

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

max user processes              (-u) 1024

每个线程都将计入该值。由于您不仅在运行 JVM,因此已经从该值中扣除了相当多的线程。

尝试执行

ulimit -u 4000

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

于 2013-12-02T08:04:31.893 回答