繁体   English   中英

Thread.sleep 和 BufferedReader.readLine 在我的 java tcp 服务器中使用最多的 CPU 周期。 为什么?

[英]Thread.sleep and BufferedReader.readLine use the most cpu cycles in my java tcp server. Why?

晚上好,

我正在开发一个 java tcp 服务器用于客户端之间的通信。

此时我正在对开发的服务器进行负载测试。

今天早上,我得到了一个分析器(yourkit)并开始在我的服务器中寻找问题点。

我现在有 480 个客户端每 500 毫秒向服务器发送消息。 服务器将收到的每条消息转发给 6 个客户端。

当处于恒定负载时,服务器现在使用了我大约 8% 的 cpu。

我的问题是关于使用最多 cpu 周期的 java 函数。

使用最多 cpu 周期的 java function 奇怪的是“Thread.sleep”,其次是“BufferedReader.readLine”。

这两个函数似乎在等待某些东西时阻塞了当前线程(sleep 等待几毫秒,readline 等待数据)。

有人能解释一下为什么这两个函数会占用那么多 CPU 周期吗? 我还想知道是否有使用更少 cpu 周期的替代方法。

亲切的问候,T. Akhayo

sleep() 和 readLine() 可以使用大量 cpu,因为它们都会导致可以上下文切换的系统调用。 由于这个原因,这些方法的时间也可能不准确(可能是高估)

减少上下文切换/sleep() 开销的一种方法是减少线程并避免需要使用睡眠(例如使用 ScheduledExecutorServices),使用 NIO 可以减少 readLine() 开销,但可能会增加一些复杂性。

睡眠不应该是一个问题,除非你有一堆线程在短时间内睡眠(当你有 480 个线程运行一个循环时,100-150ms 是“短”的,只是睡眠并做一些微不足道的事情)。

当 readLine 调用实际上没有读取某些内容时,它应该几乎没有使用,除非您第一次调用它。 但就像你说的那样,它会阻塞,除非你有小的 windows 在它阻塞的地方,否则它不应该使用大量的 CPU。 除非您正在读取大量数据或最初调用该方法,否则 CPU 使用率并不高。

所以,你的循环太紧了,你太快地接收到太多的消息,这最终会导致“吨”的上下文切换和处理。 如果您对 NIO 不够满意而无法自己使用它,我建议您使用 NIO 框架(如 Netty)。

此外对于每秒发送 2 条消息的 480 个客户端来说,8% 的 CPU 并不算多。

这是一个程序,其中sleep使用了应用程序几乎 100% 的 cpu 周期:

for (i = 0; i < bigNumber; i++){
  sleep(someTime);
}

为什么? 因为它根本不使用很多实际的 cpu 周期,而且在它使用的那些周期中,几乎所有这些周期都花在了进入和离开sleep上。

这是否意味着这是一个真正的问题? 当然不是。

这就是只查看 CPU 时间的分析器的问题。

您需要一个按挂钟时间而不是 CPU 时间进行采样的采样器。 它应该对堆栈进行采样,而不仅仅是程序计数器。 它应该通过代码行(而不是函数)向您显示包含该行的堆栈样本的分数。

对挂钟时间采样的常见反对意见是,由于与其他进程共享机器,测量结果将不准确。 但这没关系,因为找到时间消耗并不需要测量精度。 它需要精确的定位 您正在寻找的是精确的代码位置和调用站点,它们在堆栈上占实际时间的一小部分,由与程序的 state 不相关的堆栈采样确定。 与其他进程的竞争不会将调用站点在堆栈上的时间比例改变到足以导致遗漏问题的程度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM