Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SocketInputStream.socketRead0()中CPU使用率高的原因_Java_Linux_Performance_Jvm_Cpu Usage - Fatal编程技术网

Java SocketInputStream.socketRead0()中CPU使用率高的原因

Java SocketInputStream.socketRead0()中CPU使用率高的原因,java,linux,performance,jvm,cpu-usage,Java,Linux,Performance,Jvm,Cpu Usage,在分析自己开发的web应用程序时,我遇到了以下非常奇怪(至少对我来说)的观察结果 几乎所有的时间都花在socketRead0()类的SocketInputStream方法上。这并不奇怪,因为我的应用程序在每次请求时都会与远程服务进行联网。奇怪的是,这种方法不仅墙上的时钟使用率很高,CPU时钟时间也很高。我不明白为什么CPU时间很长,因为如果我的应用程序等待远程服务的响应(事实上不是那么快),那么应用程序本身就没有什么可做的了。所以CPU时间应该很低 还有一些观察: 采样模式下的VisualVM

在分析自己开发的web应用程序时,我遇到了以下非常奇怪(至少对我来说)的观察结果

几乎所有的时间都花在
socketRead0()
类的
SocketInputStream方法上。这并不奇怪,因为我的应用程序在每次请求时都会与远程服务进行联网。奇怪的是,这种方法不仅墙上的时钟使用率很高,CPU时钟时间也很高。我不明白为什么CPU时间很长,因为如果我的应用程序等待远程服务的响应(事实上不是那么快),那么应用程序本身就没有什么可做的了。所以CPU时间应该很低

还有一些观察:

  • 采样模式下的VisualVM显示方法
    SocketInputStream.socketRead0()
    占用了95%的时间(墙上的时钟时间CPU时间)
  • mpstat
    (我们使用Linux作为操作系统)显示约90%的用户时间和约1-3%的系统时间(其余为空闲时间)
  • 部署在专用服务器上的应用程序
  • 远程服务也是HTTP web应用程序。平均响应时间约为100ms。平均响应大小约为2Kb
  • 我的应用程序使用spring
    RestTemplate
    与远程服务交互,而不是直接使用
    SocketInputStream
现在我只有一个想法——也许这是在JVM中调用本机方法的开销(
SocketInputStream.socketRead0()
是本机的)


你觉得怎么样?还有其他原因吗?

VisualVM将负载显示为相对值,而不是绝对值,因此它只是意味着您的应用程序没有更多的CPU消耗点

我相信您应该将VisualVM配置为不深入,而是将此方法调用作为代码(或spring)中方法的一部分


我已经经历过这样的行为,但它看起来不需要任何优化。Web应用程序只需从套接字(即HTTP请求、数据库、内部网络服务等)读取数据,没有任何帮助。

我面临同样的问题。我的应用程序具有非常高的qps,每个请求都会让我发送多个thrift调用,这些调用使用本机api:
socketRead0

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

这说明了两件事:

  • 具有高qps阻塞io的应用程序将面临高cpu负载值

  • java线程仍在jvm中运行,因为线程状态为
    RUNNABLE
    ,这将提高用户空间cpu利用率

  • 这两个都会让你的cpu很忙


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

    这似乎有点奇怪,但并非不可能。你能提供更多的背景吗?“自主开发的web应用程序”是否直接使用套接字?您正在读取单个字节吗?在“观察”下有更多的上下文,您是否知道堆栈的更上层是什么,或者读取的大小是什么?我可以想象,如果你试图从一个无缓冲的套接字进行JSON解析,你会得到你的数字。@themel我们正在使用Spring的RestTemplate,所以我想我们在这方面应该是安全的。但我会检查的。平均响应大小约为几千字节。socketRead将用于请求解析,而不是响应(除非您正在使用其他人的服务)。在@DenisBazhenov试图说的话中解释了这种现象,在这种情况下,100%CPU是程序本身的总和,而不是整个CPU的总和。因此,如果您的程序占用了5%的CPU,并且99%的时间花费在socketRead中,这意味着您的程序将99%的时间花费在socketRead函数中,而这个程序只占用了5%的CPU,这可能不是来自套接字。所以最好不要叫Sleep(),否则这可能会占到100%。