为什么32位CPU / OS / Java上的Tomcat 7比64位慢得多?

时间:2017-10-11 17:49:42

标签: java linux performance tomcat

                        Raspberry Pi3   Raspberry Pi3   Odroid C2       Odroid XU4
                        1,20 GHz        1,20 GHz        1,5 GHz         2,0 GHz
                        Debian 32 Bit   SuSE 64 Bit     Ubuntu 64 Bit   Ubuntu 32 Bit
Start Apache Tomcat     04:30,00        00:29,06        00:27,45        04:08,39
1. page (1. request)    00:50,00        00:03,91        00:03,66        00:24,75
1. page (2. request)    00:03,30        00:00,79        00:00,77        00:02,39

我正在研究IoT类项目,并且需要测试使用Tomcat作为Web服务器在Java中实现的某些Web前端是否在我们可能的硬件上“足够快”。我们需要在Raspberry Pi3Odroid C2Odroid XU4之间进行选择。根据规格,Pi3和C2都有一个64位CPU,性能略有不同,XU4只有32位CPU,理论上也应该比其他两个更快。重要的是Pi3默认运行32 Bit OS,即使它有64位CPU,XU4也运行32位,但C2运行的是64位操作系统。 64位Java等。

在默认设置中比较所有这些设备,我们发现C2明显快于其他设备。使用我们的一些测试应用程序重启Tomcat需要4分钟以上~30秒。此外,像htop这样的工具显示使用了C2的大部分运行时所有核心,而Pi3和XU4大多只能将一个核心置于负载之下。在Tomcat加载后我们能够浏览我们的测试应用程序时,性能上的差异是相同的:只需浏览一些带有CSS / JS的页面,就需要约1.5秒而4到5.5秒。

虽然Pi3的默认操作系统仅为32位,但我们能够成功安装特殊的64位SuSE分发版。猜猜发生了什么?现在性能与我们在C2上已经看到的情况相近,对于许多测试几乎相同,即使Pi3的时钟频率仅为C2和1.5 GHz。特别有趣的是,现在Pi3的所有内核在大部分时间都处于负载状态,因此整体行为与C2现在非常相似。

因此,只需切换到64位操作系统,Java等,我们就看到了性能的显着提升。其他一切都是相同的,相同的测试应用程序,Tomcat等,没有超频,没有其他存储或其他。怎么可能?是什么导致这种戏剧性的改进?

使用64位操作系统,我们发现与32位相比,设备的所有内核都处于负载状态。但是为什么Linux内核调度程序会关心它是否在32位或64位上运行呢?

如果没有,差异来自Java,为什么/如何?在如此简单的测试中,32位和64位JVM不应该几乎完全相同吗?两者不应该特别在核心上放置几乎相同的负载而不是表现不同吗?操作系统的体系结构不应该对JVM内部使用的线程数有任何影响,这主要是在Tomcat和我们的测试应用程序的控制之下,因此没有改变。根据我所读到的关于32 vs. 64 Bit Java性能的内容,在我的用例中差异应该可以忽略不计。此外,better performance of a 64 Bit JVM的其他用户似乎没有像我所看到的4到5的因子,并且也没有解释各个核心的CPU负载差异。

我们的测试不受I / O限制,我们不分配太多内存或使用许多线程等,它几乎是严格的CPU,只编译Java类并发布HTML,CSS和JS。但是我们看到内核上的负载差别很大,具体取决于32/64位和非常不同的性能结果。

我的一位同事说,他在某处读到Java内部仅使用64位值,因此在32位CPU / OS上需要更多周期来处理相同的事情。我猜他的来源并不意味着真正的一切,而只是像对象一样只引用/指向内存。但我无法相信32位JVM在内部确实无缘无故地使用64位指针,特别是如果存在compressed oops之类的优化。但可能是一个解释,所以有任何想法吗?

如果感兴趣,32位操作系统上的软件包都以“armhf”作为体系结构,而64位操作系统上的“arm64”。我认为这可能会影响Java的构建方式,可能真的使用64位指针是出于某些奇怪的原因?

Java始终是OpenJDK 8,与OS相同的架构,与OS提供的包管理器一样。带有SuSE的Pi3有1.8_144,UB为32位和64位安装提供了1.8_131,所有都是服务器虚拟机。另外,Linux内核是不同的,例如Pi3与SuSE vs. C2和XU 4与UB:Pi3有一些当前的4.x,C2有些旧3.14和XU 4有些当前4.9。

那么,关于差异来自何处的任何想法?谢谢!

1 个答案:

答案 0 :(得分:3)

您已告诉过您从标准软件包中安装了OpenJDK 8。

从未有过针对ARM 32的OpenJDK 8的优化版本(至少在Debian和Ubuntu上)。默认包是从“Zero”端口构建的,它甚至没有JIT编译器。

root@localhost:~# java -server -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-8u131-b11-1~bpo8+1-b11)
OpenJDK Zero VM (build 25.131-b11, interpreted mode)
        ^^^^^^^                    ^^^^^^^^^^^^^^^^

尝试从Java SE downloads page手动安装Oracle JDK 它内部有一个优化的HotSpot JVM。它的确运作得更快。

root@localhost:~# /usr/java/jdk1.8.0_131/bin/java -server -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) Server VM (build 25.131-b11, mixed mode)
     ^^^^^^^^^^^^^^^^^^^^^                    ^^^^^^^^^^

相比之下,HotSpot JVM的Aarch64端口已经成为OpenJDK的一部分很长一段时间了。因此,在64位操作系统上,默认的OpenJDK软件包附带了包含优化JIT编译器的HotSpot JVM。