【问题标题】:Thread performance issues for Java on Raspberry PiRaspberry Pi 上 Java 的线程性能问题
【发布时间】:2017-06-16 19:40:48
【问题描述】:

这个应用程序的目标是通过 TCP 处理 800 个并发客户端,每个客户端每秒发送一个 3.5kb 的 xml。这些请求中的每一个都需要被解析(参见代码片段)。这发生在不同的线程上。

该项目的限制是它必须在小型 Raspberry Pi3(1.2 ghz 四核,1gb 内存)上运行。当我将负载增加到超过 150 个并发客户端(80% cpu 使用率)时,我遇到了利用率问题。

当我在我的开发机器上运行这个程序时,它似乎运行得很好。 (0-1% 的使用率,低于 150)。我知道我的开发机器比 RPI 更强大,因此运行得更好。不过好像差别太大了。

在我当前的设置中,我使用 Java nio 来处理/读取所有传入的连接。然后我使用多个线程来读取数据。

这是当前在处理线程上运行的简单代码。还尝试一次读取一个简单的 byte[] 数组 1 个字节。甚至读取 StaX 流。 我尝试的每一种读取方式,“读取类型”的操作都会给出最差的性能。

BufferedInputStream input = new BufferedInputStream(new ByteArrayInputStream(buffer.array(), 0, bytecount));
int current;
/* In this snippet input.read() is the cause of performance issues 
Reading directly from byte[] gives similar poor performance.
*/
while ((current = input.read()) != -1) {
    continue;
}

根据我的分析器,Input.read() 调用在 Pi 上使用了大量的处理能力,占总 CPU 时间的 97%。另外 3% 是处理连接的主线程。

在我的开发机器上,这几乎是颠倒的,主线程占了大部分 cpu 使用率,93%。 7% 用于处理线程。

什么会导致如此大的差异?为什么 pi 上的这个 read() 调用与我的其他机器相比如此昂贵,它可能与内存有关吗?

注意事项:

  • Pi 运行 raspbian linux - openjdk 1.8.0_40-internal
  • 开发机器运行 win 10 - Java(TM) SE 运行时环境(内部版本 1.8.0_121-b13)
  • 尝试在两台机器上使用 -Xms -Xmx 标志运行,结果相同。

【问题讨论】:

  • 树莓派绝对是最差的 IO。您的 PC 有一个巨大的旋转磁盘,甚至可能是一个 SSD - 这比糟糕的 SD 卡快 几个数量级。这甚至还没有从 CPU 架构、内核数量、超线程等开始。
  • 应用程序不对磁盘执行任何(显式)IO,pi 可以很好地处理套接字 IO(无需处理),在主线程中读取套接字并将其存储在字节缓冲区中。如果我正确的话,处理线程应该从 RAM 中读取。
  • 此外,RPI3 的硬件是 ARMv8(带有 Cortext-A53),但 raspian 映像是旧版 ARM-32 armhf(甚至不是 Aarch32)。 Raspian 没有充分利用该设备的潜力。您可以考虑使用由 openSUSE、CentOS 或其他发行版之一提供的 Aarch64 映像。
  • 如果我没看错的话,这有点奇怪,而且开销很大。我想知道当您已经将所有内容都放入 ByteArrayInputStream 内的内存中时,BufferedInputStream 的目的是什么......然后再次一次取出 1 个字节。
  • @Georggroenendaal - 我最近对 ​​Coreext-A53 和 Cortex-A57 之间的差异有所了解。两者都是ARMv8,A57是更高端的型号。但是我的BLAKE2b implementation for Crypto++ ran slower on the A57。它甚至比 C++ 实现还要慢。事实证明 NEON/ASIMD 转换成本更高:它们有 7 个周期的延迟,并且只能在其中一个管道上运行。使用整数操作的非 NEON 实现更快。优化指南为我们提供了详细信息并进行了解释。

标签: java linux multithreading raspberry-pi3


【解决方案1】:

原来问题在于 Raspberry Pi 3 上的 JVM 和 32 位操作系统的组合。当使用 OpenJDK 运行 32 位 raspbian 时,我的应用程序性能非常差(尤其是在“读取”调用上)。切换到 Oracle JVM 给了我“更好”的预期性能。

但是,当切换到 64 位操作系统(在我的例子中是 OpensSuse)时,OpenJDK 和 Oracle JVM 的性能都很好。

(感谢 cmets 中的@jww,建议切换到 64 位操作系统)

【讨论】:

    猜你喜欢
    • 2018-01-08
    • 1970-01-01
    • 1970-01-01
    • 2019-09-09
    • 2012-09-14
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多