java - 在 Java 下创建进程变慢?

标签 java linux performance

我有一个单一的大堆(最大 240GB,虽然在这个执行阶段的大部分时间在 20-40GB 范围内)JVM [1] 在具有 24 个内核的服务器上运行在 Linux [2] 下。我们有成千上万的对象必须由外部可执行文件处理,然后将这些可执行文件创建的数据加载回 JVM。每个可执行文件都会产生大约 0.5 兆字节的数据(在磁盘上),当进程完成后直接读入这些数据时,当然会更大。

我们的第一个实现是让每个可执行文件只处理一个对象。这涉及生成两倍于我们拥有的对象的可执行文件(因为我们调用了调用可执行文件的 shell 脚本)。我们的 CPU 利用率一开始会很高,但不一定是 100%,然后会慢慢恶化。当我们开始测量以查看发生了什么时,我们注意到进程创建时间 [3] 不断变慢。虽然从亚秒级开始,但最终会增加到一分钟或更长时间。可执行文件完成的实际处理通常需要不到 10 秒。

接下来我们更改了可执行文件以获取要处理的对象列表,以尝试减少创建的进程数。批量大小为数百(约为我们当前样本大小的 1%)时,流程创建时间从大约 2 秒开始,然后增长到大约 5-6 秒。

基本上,为什么在执行过程中创建这些进程需要这么长时间?

[1]甲骨文JDK 1.6.0_22
[2] Red Hat Enterprise Linux Advanced Platform 5.3, Linux kernel 2.6.18-194.26.1.el5 #1 SMP
[3] 创建 ProcessBuilder 对象,重定向错误流,并启动它。

最佳答案

我的猜测是,如果 Java 使用 fork/exec 系统调用来生成子进程,您可能会遇到 fork/exec 问题。

通常 fork/exec 相当高效,因为 fork() 做的很少——所有页面都是写时复制。对于非常大的进程(即那些映射了千兆字节的页面的进程),这不再如此真实,因为页表本身需要相对较长的时间来创建 - 当然,销毁,因为您立即调用 exec。

由于您正在使用大量堆,这可能会影响您。您映射的页面越多,它可能会变得越糟糕,这可能是导致逐渐变慢的原因。

请考虑:

  • 使用 posix_spawn,如果它不是由 libc 中的 fork/exec 实现的话
  • 使用负责创建/收获其他子进程的单个子进程;产生一次并使用一些 IPC(管道等)告诉它该做什么。

注意:这都是猜测;您可能应该做一些实验,看看情况是否如此。

关于java - 在 Java 下创建进程变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4571928/

相关文章:

linux - Docker 中的 Docker 无法挂载卷

c - Valgrind 关于 asprintf : address is 0 bytes inside a block of size <size> alloc'd

php - 当安全性不受威胁时,php 中可用的最高性能散列算法是什么?

java - 快速乘法和减法取模素数

java - 如何在 Activity 菜单项中画一条线

linux - 使用正则表达式别名时如何设置devnull后缀用户

java - 谷歌验证码 : how to get only letters as a challenge

mysql - 为什么 MySQL 在 JOIN 查询中选择了错误的索引?

java - Sonarqube 测试用例规则不考虑 @Test 注释

java - 为什么 java 5+ 中的 volatile 不能确保来自另一个线程的可见性?