Executors.newFixedThreadPool(numThreads)
每次运行程序时,我都会调整numthreads
,以查看它的效果。
然后,我将NumThread
作业(java.util.concurrent.Callable
的实例)提交到池。每一个都增加一个AtomicInteger
,做一些工作(创建一个随机整数数组并对其进行洗牌),然后Hibernate一段时间。其思想是模拟一个web服务调用。最后,作业将自己重新提交到池中,这样我总是有numthreads
作业在工作。
我正在测量吞吐量,例如每分钟处理的作业数。
现在的问题是:我得到了一个java.lang.OutOfMemoryError:无法创建新的本机线程
,作业超过了31,000个。我尝试过设置-xmx6000m
,但这没有帮助。我尝试使用-xss
,但这也没有帮助。
我读到过ulimit
可能很有用,但是使用ulimit-u64000
增加值并没有改变任何东西。
有关信息:
[root@apollo ant]# 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) 127557
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
那么问题1:我必须做什么才能创建一个更大的线程池?
问题2:我应该在什么阶段看到上下文切换真的会降低吞吐量,并导致进程陷入停顿?
以下是一些结果,我修改了它,做了一点更多的处理(正如建议的那样),并开始记录平均响应时间(正如建议的那样)。
// ( (n_cores x t_request) / (t_request - t_wait) ) + 1
// 300 ms wait, 10ms work, roughly 310ms per job => ideal response time, 310ms
// ideal num threads = 1860 / 10 + 1 = 187 threads
//
// results:
//
// 100 => 19,000 thruput, 312ms response, cpu < 50%
// 150 => 28,500 thruput, 314ms response, cpu 50%
// 180 => 34,000 thruput, 318ms response, cpu 60%
// 190 => 35,800 thruput, 317ms response, cpu 65%
// 200 => 37,800 thruput, 319ms response, cpu 70%
// 230 => 42,900 thruput, 321ms response, cpu 80%
// 270 => 50,000 thruput, 324ms response, cpu 80%
// 350 => 64,000 thruput, 329ms response, cpu 90%
// 400 => 72,000 thruput, 335ms response, cpu >90%
// 500 => 87,500 thruput, 343ms response, cpu >95%
// 700 => 100,000 thruput, 430ms response, cpu >99%
// 1000 => 100,000 thruput, 600ms response, cpu >99%
// 2000 => 105,000 thruput, 1100ms response, cpu >99%
// 5000 => 131,000 thruput, 1600ms response, cpu >99%
// 10000 => 131,000 thruput, 2700ms response, cpu >99%, 16GB Virtual size
// 20000 => 140,000 thruput, 4000ms response, cpu >99%, 27GB Virtual size
// 30000 => 133,000 thruput, 2800ms response, cpu >99%, 37GB Virtual size
// 40000 => - thruput, -ms response, cpu >99%, >39GB Virtual size => java.lang.OutOfMemoryError: unable to create new native thread
我把它们解释为:
1)尽管应用程序在96.7%的时间内处于Hibernate状态,但仍然需要进行大量的线程切换。2)上下文切换是可测量的,并显示在响应时间中。
这里有趣的是,当调优应用程序时,您可能会选择可接受的响应时间,比如400ms,并增加线程数,直到您获得该响应时间为止,在本例中,该响应时间将使应用程序每分钟处理大约9万5千个请求。
经常有人说,理想的线程数是在核心数附近。在有等待时间(阻塞线程,例如等待数据库或web服务响应)的应用程序中,计算需要考虑这一点(参见上面的公式)。但即使是理论上的理想也不是实际的理想,当你观察结果或调整到特定的响应时间时。
我得到一个java.lang.OutOfMemoryError:无法使用超过31,000个作业创建新的本机线程。我试过设置-xmx6000m,这没有帮助。我试着玩-xss,但这也没有帮助。
-xmx设置不会有帮助,因为线程堆栈不是从堆中分配的。
正在发生的情况是,JVM正在向OS请求内存段(在堆之外!)以保存堆栈,而操作系统拒绝该请求。最可能的原因是ulimit或OS内存资源问题:
>
“数据序列大小”ulimit是无限的,所以这不应该是问题所在。
这样就会留下内存资源。30,000个线程,每次1MB,相当于30GB,这比您拥有的物理内存多得多。我的猜测是30GB的虚拟内存有足够的交换空间,但您把边界推得有点过了。
-xss设置应该有所帮助,但您需要使请求的堆栈大小小于1M
的默认大小。此外还有一个严格的最小尺寸。
问题#1:我必须做什么才能创建一个更大的线程池?
将默认堆栈大小减小到当前值以下,或增加可用虚拟内存量。(不推荐使用后者,因为看起来您已经严重过度分配了。)
问题2:我应该在什么阶段看到上下文切换真的会降低吞吐量,并导致进程陷入停顿?
Oracle站点关于线程堆栈空间的主题是这样说的:
在Java SE 6中,Sparc上的默认值在32位VM中为512K,在64位VM中为1024K。在x86 Solaris/Linux上,32位VM中为320K,64位VM中为1024K。
在Windows上,默认的线程堆栈大小是从二进制(java.exe)中读取的。在Java SE 6中,该值在32位VM中为320K,在64位VM中为1024K。
可以通过使用-xss选项运行来减小堆栈大小。例如:
java -server -Xss64k
请注意,在Windows的某些版本上,OS可能使用非常粗略的粒度将线程堆栈大小取整。如果请求的大小比默认大小小1K或更多,则堆栈大小四舍五入为默认大小;否则,堆栈大小将四舍五入为1 MB的倍数。
64K是每个线程允许的最少堆栈空间量。
问题内容: 在Java中拥有多个线程池的优缺点是什么?我已经看过代码,其中有多个线程池用于不同的“类型”任务,而且我不确定它是更好的设计还是只是开发人员感到懒惰。一个示例是将ScheduledThreadPoolExecutor用于定期执行的任务或具有超时的任务,而将另一ThreadPoolExecutor用于其他任务。 问题答案: 具有单独的专用线程池的目的是,使活动不会因线程不足而被饥饿,因为
问题内容: Go 支持以数千个逗号输出数字吗? 输出,我可以指定输出什么格式呢? 这些文档似乎没有提到逗号,而且我也无法立即在源代码中看到任何内容。 问题答案: fmt打印动词均不支持数千个分隔符。
我使用Netty 4创建了一个相当直接的服务器。我已经能够将它扩展到处理数千个连接,而且它从未超过40个线程。 为了测试它,我还创建了一个创建数千个连接的测试客户端。不幸的是,这会创建和连接一样多的线程。我希望尽量减少客户端的线程。我已经看了很多帖子。许多示例显示了单个连接设置。这个和这个说在客户端之间共享NioEventLoopGroup,我这样做了。我得到的nioEventLoopGroup数
我正在使用matplotlib的hist()函数或bar()制作直方图,我想使用 我尝试过使用rwidth()并改变其值,也尝试过使用figsize()并简单地扩展绘图的大小,但最终的结果总是每个垂直条彼此相邻,中间没有空格。
问题内容: 我们正在构建一个eLearningMultipleChoice工具,成千上万的用户将完成我们的测试。我们已经有成千上万的其他研讨会的订阅者,因此很可能成千上万的人也将完成MC测试。 现在,我们需要跟踪每个用户回答的每个问题,花了他多长时间,是否正确(经过多次尝试之后),如果不是,他给出了哪个错误答案等等。确实有很多数据。 现在,我们将有成千上万的问题和成千上万的用户。由于每个问题至少要
问题内容: 当我们在程序中启动线程时,是否有任何方法可以为每个线程分配内存限制? 我的意思是我们为新流程分配了以下内容: 我们可以用Java线程做任何类似的事情吗? 基本上,我的每个线程都将执行某项任务,我希望对每个线程的内存使用量设置一些最大限制。 问题答案: 我们可以用Java线程做任何类似的事情吗? 不能。进程中的线程通常用于访问进程(在本例中为JVM)中的共享主内存。 基本上,我的每个线程