【问题标题】:Why does park/unpark have 60% CPU usage?为什么 park/unpark 有 60% 的 CPU 使用率?
【发布时间】:2012-10-09 23:44:50
【问题描述】:

最近我们开始使用 YJP 11.0.9 对我们的应用程序(基于 XMPP 的聊天服务器)进行压力测试。在我们的测试中,我们注意到以下奇怪的行为。

  1. 采样显示 sun.misc.Unsafe.unpark(Object) 占用了 60% 的 CPU。
  2. 对于同一个应用程序跟踪显示 LockSupport.park(Object) 占用了 52% 的 CPU。

我做了多次测试来确认结果,每次都得到类似的结果。

我无法理解为什么 unpark 需要 60% 的时间,以及为什么跟踪显示完全相反的结果。

谁能帮我理解这些结果。我在这里遗漏了什么吗?

环境:

java -版本
java版本“1.6.0_31”
Java(TM) SE 运行时环境 (build 1.6.0_31-b04)
Java HotSpot(TM) 64 位服务器 VM(内部版本 20.6-b01,混合模式)

【问题讨论】:

  • 如果调用unpark 几乎是线程唯一做的事情,那么它可能需要这么多。 “跟踪显示完全相反的结果”是什么意思?跟踪是否可能测量在方法中花费的时间? park 是一种阻塞方法,难怪在其中花费时间。
  • @MarkoTopolnik 线程还可以做其他事情。基本上它的生产者/消费者问题。生产生产任务并将其提交到队列中并通知等待的消费者。消费者对任务采取行动,如果没有可用的任务,则自行停放。
  • 调用unpark的线程不是被解除停放的线程。反过来,该线程可能实际上只做很少的工作,除了取消驻留适当的消费者线程。至于park 的 CPU 时间,a) 由于阻塞而难以测量,并且 b) 无关紧要,因为它只是在停放状态下实际花费的时间的一小部分。
  • @MarkoTopolnik 在 Sampling 测试中 60% 的 CPU 用于执行 unpark consumer。在跟踪测试中,52% 的 CPU 用于从消费者线程进行停放。
  • @MarkoTopolnik 正如我所说,生产者会进行诸如 xml 解析之类的 CPU 活动,这应该比 unpark 高得多。

标签: java profiling yourkit


【解决方案1】:

我了解到,如果您多次调用 LockSupport.parkNanos() 方法并且您的 sleep 参数为纳秒级,那么您也可以在 LockSupport.parkNanos() 上获得高 CPU 使用率:

while(true){
  // code logic
  LockSupport.parkNanos(100);
}

只需更改为微秒即可帮助我解决问题。我也在我的本地机器上尝试了它,并且能够重现高 CPU 使用率,并且在运行几微秒后看到它显着改善。

【讨论】:

    【解决方案2】:

    Unsafe.unpark 的高 CPU 时间是过度上下文切换的标志。这里有一篇文章来了解上下文切换的代价:

    How long does it take to make a context switch?

    在 Linux 上找出 CS 计数的最简单方法是运行 vmstat <seconds>

    一旦确认了高 CS(例如,每核/每秒更多 10K 开关),您就可以使用有问题的线程(您可以在 YJP 中按 CPU 时间对线程进行排序)并运行 strace -p <pid> -c 以找出切换的原因,例如线程正在从小块读取套接字并关闭,在这种情况下增加套接字缓冲区可能会有所帮助。

    【讨论】:

      【解决方案3】:

      对于某些低级别的阻塞命令,如读/写/停放/锁定,“CPU”时间被高估了,因为它假定它在实际操作阻塞时正在消耗 CPU。 unpark/park 都很高的事实确实表明您有问题,但我怀疑您应该将这两个百分比中的较低者作为估计值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-02
        • 2020-01-27
        • 1970-01-01
        • 1970-01-01
        • 2020-06-02
        • 2021-09-05
        相关资源
        最近更新 更多