gpt4 book ai didi

java - SocketInputStream.socketRead0()中CPU占用率高的原因

转载 作者:IT王子 更新时间:2023-10-29 00:24:17 41 4
gpt4 key购买 nike

在分析本土网络应用程序时,我遇到了非常奇怪的(至少对我而言)观察结果。

几乎所有时间都花在 SocketInputStream 类的 socketRead0() 方法上。这并不奇怪,因为我的应用程序会根据每个请求与远程服务建立网络。奇怪的是,此方法不仅挂钟时间使用率很高,CPU 时钟时间 也非常高。我不明白为什么 CPU 时间很高,因为如果我的应用程序等待远程服务回复(实际上并没有那么快),应用程序本身就无事可做。所以 CPU 时间应该很低。

更多观察:

  • 采样模式下的 VisualVM 显示方法 SocketInputStream.socketRead0() 消耗了高达 95% 的时间(挂钟时间 CPU 时间);
  • mpstat(我们使用 Linux 作为操作系统)显示大约 90% 的用户时间和 1-3% 的系统时间(其余为空闲时间);
  • 部署在专用服务器上的应用;
  • 远程服务也是 HTTP 网络应用程序。平均响应时间约为 100 毫秒。平均响应大小约为 2Kb。
  • 我的应用程序使用 spring RestTemplate 与远程服务交互,而不是直接使用 SocketInputStream

目前我只有一个想法——也许这是在 JVM 中调用本地方法的开销(SocketInputStream.socketRead0() 是本地的)?

你怎么看?还有其他原因吗?

最佳答案

我也遇到了同样的问题。我的应用程序具有非常高的 qps,每个请求都会让我发送多个 thrift 调用,这些调用使用此 native api:socketRead0

所以我决定做一个实验。我在返回前用 api sleep 30s 创建了一个模拟服务器,客户端调用了这个 api。我的目的是测试网络 io 发生时的线程状态。根据我的线程转储,线程状态为 RUNNABLE

这解释了两件事:

  1. 高qps阻塞io的应用会面临高cpu负载值

  2. 您的 java 线程仍在 jvm 中运行,因为线程状态为 RUNNABLE,这将有助于提高用户空间 cpu 利用率

这两者都会让你的 cpu 忙碌。

我在实验过程中注意到,系统空间 cpu 利用率很低。我认为这与jvm 和os 之间的线程调度策略差异有关。我们知道热点线程模型是 1:1,这意味着一个 jvm 线程对一个 os 线程。当发生阻塞 io 时,例如 socketRead0 内核线程将设置为状态 S 并且不会阻塞 cpu,但用户空间线程正在阻塞(等待)。发生这种情况时,我认为我们需要重新考虑应用程序中的基本 I/O 模型。

关于java - SocketInputStream.socketRead0()中CPU占用率高的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12489215/

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com