Java定期在futex上停顿,IO输出非常低。

18

目前我的应用程序定期在IO阻塞,并且输出非常低。我使用一些命令来追踪这个过程。

通过使用jstack,我发现该应用程序在FileOutputStream.writeBytes处挂起。

通过使用strace -f -c -p pid收集系统调用信息,我发现,在正常情况下,它具有Futex和Write系统调用。但是当它出现异常时,只有Futex系统调用。该应用程序不断调用Futex,但所有调用都失败并抛出ETIMEDOUT,就像这样:

<futex resumed>  =-1 ETIMEDOUT (Connecton timed out)
futex(Ox7f823, FUTEX_WAKE_PRIVATE,1)=0
futex(Ox7f824, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME) =-1<unfinished>
<futex resumed>  =-1 ETIMEDOUT (Connecton timed out)
futex(Ox7f823, FUTEX_WAKE_PRIVATE,1)=0
futex(Ox7f824, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME) =-1<unfinished>

这个问题周期性地发生,持续数分钟或数小时,然后恢复正常。

特别是在IO被阻塞时,echo 3 > /proc/sys/vm/drop_caches总会使其暂时恢复正常。我搜索了一下,发现一些类似的问题,如下所示:

  1. 闰秒。不行,我们系统的ntpd已经停止了。
  2. 透明大页面bug。https://bugzilla.redhat.com/show_bug.cgi?id=879801 这个问题与我的非常相似,但我的khugepaged进程正常,并且负载始终接近于零。尤其是drop_caches对我的应用程序也有效。而且我的系统也是多核和大内存。但对我来说它不起作用。所以有没有人遇到过相同的问题或熟悉这个问题?

关于我的系统的一些信息。

操作系统:Redhat 6.1,内核版本2.6.31

JDK:1.7.0_05

CPU:X5650,24个核心

内存:24GB和48GB


我担心JDK:1.7.0_05太旧了。你应该尝试最新的Java7版本。这是最简单的第一步。 - sibnick
@bforevdr 看起来像是内核问题,你尝试过重置系统日期并再次尝试吗?可以使用类似这样的命令 date -s "\date`"`。 - kucing_terbang
1
我曾尝试使用jdk 1.8,但似乎无法正常工作,我将进行详细测试。同时,我发现当被阻塞时,gc线程不断调用futex(),但失败了。但是从jstat -gcutil中可以看到,YGCT和FGCT都是正常的,只需要几秒钟。 - bforevdr
请您检查分页I/O流量(交换)和块设备的利用率。使用iostat -x -m -d 1进行检查,也可以尝试使用vmstat和top命令。可能是操作系统仅运行在RAM上,并开始将交换到相同的物理驱动器。 - Radu
可能与Linux futex_wait() bug...有关,这是由于Commit b0c29f79ecea引起的。红帽平台和内核版本看起来差不多正确。 - jww
2个回答

3

1
除了时钟跳动和上述(相当老的)THP内核bug之外,导致Java在IO上意外阻塞的另一个常见原因是读取{{link1:非常缓慢和阻塞的/dev/random}},一些库比更常用且性能更好的/dev/urandom更喜欢使用它。
判断是否为罪魁祸首的简单方法:
sudo mv /dev/random /dev/random.real
sudo ln -s /dev/urandom /dev/random

然后重新启动应用程序,查看是否停止IO阻塞。完成测试后,您可能想要恢复/dev/random:

sudo mv /dev/random.real /dev/random

...并向应用程序供应商提出bug报告,要求在适当的情况下使用/dev/urandom。


非常感谢!这对我帮助很大!!! - Super Coco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接