Java性能进程与线程

我正在用Java实现一个工作池。

这基本上是一整堆对象,它们将获取数据块,处理数据然后存储结果。 由于IO延迟,工作人员将远远多于处理器核心。

服务器专用于此任务,我想从硬件中获取最大性能(但不,我不想在C ++中实现它)。

最简单的实现是使用单个Java进程来创建和监视许多工作线程。 另一种方法是为每个worker运行一个Java进程。

假设为了争论一个四核Linux服务器,您会预期哪些解决方案更具性能?为什么?

您可以假设工人永远不需要彼此沟通。

一个进程,多个线程 – 出于几个原因。

在作业之间进行上下文切换时,某些处理器在线程之间切换比在进程之间切换更便宜。 在这种I / O限制案例中,这一点尤为重要,因为工作人员多于核心。 在阻止I / O之间做的工作越多,这就越不重要。 但是,良好的缓冲将为线程进程付出代价。

在同一JVM中的线程之间切换时,至少某些Linux实现(特别是x86)不需要刷新缓存。 看Tsuna的博客 。 线程之间的缓存污染将最小化,因为它们可以共享程序缓存,执行相同的任务,并共享相同的代码副本。 我们说的是每个开关大约100纳秒到几微秒的节省。 如果那是你的小土豆,请继续阅读……

根据设计,一个进程的I / O数据路径可能更短。

线程的启动和预热时间通常要短得多。 操作系统不必启动进程,Java不必启动另一个JVM,类加载只执行一次,JIT编译只执行一次,HotSpot优化只执行一次,并且更快。

通常,在讨论多处理(/每个进程一个线程)与同一进程中的multithreading时,虽然理论开销在第一种情况下比在后者中更大(因此多处理在理论上比multithreading慢),实际上,在大多数现代操作系统中,这不是一个大问题。 但是,在Java环境中讨论它时,启动新进程比启动新线程要昂贵得多。 启动一个新进程意味着启动一个新的JVM实例,这个实例非常昂贵,特别是在内存方面。 我建议您在同一个JVM中启动多个线程。

此外,如果您说线程间通信不是问题,您可以使用Java的Executor Service来获取大小为2x(可用CPU数量)的固定线程池。 可以通过Java的Runtime类在运行时自动检测可用CPU的数量。 通过这种方式,您可以快速进行简单的multithreading处理而无需任何锅炉板代码。

实际上,如果你使用多个jvm进程进行大规模删除比使用多个线程的jvm更快。 至少我们从来没有像多个jvms一样快速运行jvm。

我们做了一些计算,其中每个任务使用大约2-3GB ram并进行一些重数字运算。 如果我们生成30个jvm并运行30个任务,它们比在一个jvm中产生30个线程的性能提高约15-20%。 我们尝试调整gc和各种内存部分,但从未赶上第一个变体。

我们在16核服务器上的各种机器上执行了14个任务,在36核服务器上执行了34个任务。在java中的multithreading总是执行多个jvm进程。

它可能对简单的任务没有任何区别,但是在繁重的计算中,似乎jvm在线程上表现不好。