【问题标题】:How to keep CPU usage level low in Socket long connection如何在 Socket 长连接中保持低 CPU 使用率
【发布时间】:2016-12-30 02:21:43
【问题描述】:

对不起,我的台球英语。 我有一个 javaFx 应用程序,它需要连接到许多在 android 手机中启动的 Socket 服务器(超过 40 个)。 当连接到服务器时,我创建一个线程来保持长连接,服务器每 600 毫秒将 SCREENSHOT(二进制)发送到我的应用程序。 javaFx 应用程序不能是服务器。 以下是部分代码:

while (ScreenMonitorService.isConnectionAll()){
Future<Image> f = ThreadPoolUtil.getThreadPool().submit(new Callable<Image>() {
  @Override
  public Image call() throws Exception {
       return readImage(inputStream, outputStream);
    }
  });
Image fxImage = f.get();
Platform.runLater(()->{
    device.getImageView().setImage(fxImage);
});


//what readImage do
private synchronized Image readImage(InputStream inputStream, OutputStream outputStream) throws IOException {
try {
        Thread.sleep(700);<==== This is the now solution for high cpu performtion , but it doesn't work
    } catch (InterruptedException e) {
        logger.error("=====> error", e);
    }
    int fileLen = readInt(inputStream);
    int readLength = fileLen;
    int tempLength = 0;
    int n;
    byte[] bt = new byte[readLength];
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    while ((n = inputStream.read(bt,0,readLength)) > 0) {
        tempLength += n;
        readLength = tempLength + n > fileLen ? fileLen - tempLength : readLength;
        bout.write(bt,0,n);
    }
    ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
    BufferedImage image = ImageIO.read(bin);
    Image fxImage = SwingFXUtils.toFXImage(image,null);
    writeInt(outputStream,1);
    return fxImage;
 }

我知道这是 CPU 性能不佳的原因。 我曾使用 nio|notify/wait|blockqueue 尝试解决问题,但失败了。 可能有人可以给我一些解决这个问题的建议,谢谢。

【问题讨论】:

    标签: java android sockets


    【解决方案1】:

    其实....你不是在忙着等待,sleep 不是你问题的原因。

    你真正应该做的是profile代码,看看它在哪里花费了大部分时间。我怀疑实际上是在这两个调用中:

        BufferedImage image = ImageIO.read(bin);
        Image fxImage = SwingFXUtils.toFXImage(image, null);
    

    换句话说,我怀疑大部分 CPU 都在转换图像。如果是这种情况,那么您需要找到一种减少图像处理的方法。

    这也可能是与 GC 相关的问题,但分析也可以提供证据。


    我注意到您在处理之前将整个文件缓冲在内存中。这可能会使事情变慢。您可以通过将InputStream 包装在BufferedInputStream 中并将BIS 传递给ImageIO.read 来避免这种情况。但我不认为字节的双重处理是主要问题。

    【讨论】:

    • 转换成本约200毫秒。
    • 对不起,转换成本是20ms
    • 那么,如果您已经分析了代码......大部分时间实际上在哪里?
    • ReadInt() 花费最多的时间,(大约 200 毫秒),即读取四次以获得数据的长度。服务器每 600 毫秒发送一次数据。所以,我认为可能读取速度太快会消耗 cpu性能如此
    • Erm ... 200ms 不是 CPU 使用率。这实际上是空闲时间,因为您正在等待服务器。您需要测量 CPU 时间,而不是经过的时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多