在维护具有大量线程的Java应用程序时,我需要了解什么?

Eri*_*son 8 java optimization performance multithreading

背景资料

我有一个分布式处理应用程序来进行数据分析.它旨在并行处理实时更新的多组数据.作为设计的一部分,分析已经分解为分析节点.每个节点获取源数据并对其进行处理以创建其他数据,然后可以由其他节点使用.要对一个数据集进行当前的全套分析,需要大约200个节点.

在当前设计中,每个节点都使用自己的线程运行.现在,大多数时候这些线程都处于睡眠状态.每当数据更新时,他们就像瀑布一样唤醒,然后他们又回到睡眠状态.该应用程序目前正在生产中运行40组数据,每组需要200个节点,使用8000个线程.当没有数据进入时,服务器上没有负载.当数据以最繁忙的时间进入时,服务器的CPU占用率约为25%.这都在项目的设计和生产参数范围内.

现在进行下一步,我们将40组数据扩展到200.每组需要200个节点,这意味着总共40000个节点,即40000个线程.这超出了我们服务器的最大PID,所以我要求我们的服务器管理员增加上限.他们做到了,应用程序正常运行,但是他们给了我一些关于线程数量的推迟.我并不否认线程的数量是不寻常的,但我们的设计阶段是预期和保证的.

我正在计划对设计进行一些小的调整,以将线程与节点分开.这将允许我们配置一个线程来运行多个节点,并减少我们的线程数.对于不经常更新的数据集,让一个线程在每个节点中执行数据更新的性能影响非常小.对于每秒更新数百次的数据集,我们可以将每个节点配置为在其自己的线程上运行.事实上,我不怀疑这种设计会发生什么变化 - 这只是时间问题.与此同时,我希望尽可能多地了解使用此设计的后果.

在一台机器上运行超过40,000个线程的成本是多少?通过让JVM/Linux操作系统管理这么多线程,我失去了多少性能?请记住,当没有工作时,它们都已正确配置为睡眠状态.所以,我只是谈论额外的开销和线程数量导致的问题.

请注意 - 我知道我可以减少线程数,我知道改变这个设计是个好主意.我会尽快做到,但必须与其他工作和设计考虑因素保持平衡.我问这个问题是为了收集信息以做出正确的决定.您对这种性质的想法和评论非常感谢.

Ste*_*n C 9

在一台机器上运行超过40,000个线程的成本是多少?通过让JVM/Linux操作系统管理这么多线程,我失去了多少性能?请记住,当没有工作时,它们都已正确配置为睡眠状态.所以,我只是谈论额外的开销和线程数量导致的问题.

在JVM空间中,每个线程都需要一个线程堆栈(默认为256kb)以及Thread对象和连接的对象.可以使用-Xss选项更改默认线程堆栈,但我相信64kb是下限.(40,000 x 256kb是10Gb ...)

在Linux上,每个线程也占用一个OS线程描述符,当线程没有执行时,它将帮助线程的注册上下文...和其他东西.这些描述符是预先分配的,我相信它们不会被分页.这是您的管理员需要增加的资源.

无论线程是清醒还是休眠,都会使用这些资源.

另一个问题是你需要在使用wait/notifyAll进行同步时要小心.如果有很多线程在同一个对象上等待,那么当每个线程被唤醒时,notifyAll将引起一连串的活动.(但是你可以通过没有很多线程在同一个对象上等待来避免这种情况.)

有关使用大量线程的后果的详细信息,请参阅Oracle Java Threading页面.


我的感觉是40,000个线程过多.理想的线程数与您拥有的物理处理器/核心数成正比.虽然通过拥有大量线程不一定会看到性能下降,但是你会占用大量资源,这可能会产生间接的性能问题; 例如GC时间越长,潜在的VM抖动.

应用程序的更好的体系结构是实现线程池和工作队列,以便将工作分配给更少数量的活动线程.