是否值得付費(fèi)?Oracle,Open JDK等四大JVM性能全面對(duì)比
市面上可供選擇的JVM發(fā)行版還是有不少的。選擇合適的JVM需要考慮不同的因素。性能是其中一個(gè)重要的因素??孔V的性能研究是很困難的。在本文中,我創(chuàng)建了一個(gè)測試,在不同的JVM上執(zhí)行對(duì)比測試。測試程序包括Spring Boot REST應(yīng)用,使用Prometheus監(jiān)控JVM并使用Grafana可視化。下圖是示意圖。除了soapui外,所有東西都在docker容器中運(yùn)行。
隔離干擾因素
如何確定沒有別的因素干擾你的設(shè)施。我們可以通過嘗試隔離分配給流程的資源來實(shí)現(xiàn)。 例如,分配專用CPU和固定數(shù)量的內(nèi)存。 我還進(jìn)行了幾項(xiàng)測試,這些測試將資源限制放在負(fù)載均衡器,監(jiān)控軟件和可視化軟件上(為這些資源分配不同的CPU和內(nèi)存)。 為進(jìn)程分配特定資源(使用docker-compose v2 cpuset和內(nèi)存參數(shù))似乎不會(huì)對(duì)單個(gè)進(jìn)程負(fù)載和響應(yīng)時(shí)間的度量產(chǎn)生很大影響。 我還比較了啟動(dòng),負(fù)載和無負(fù)載情況。 在這些不同情況下,測試結(jié)果沒有很大變化。
為進(jìn)程分配特定CPU和內(nèi)存
使用docker-compose無法為進(jìn)程配置特定CPU。 docker-compose v3不支持為進(jìn)程分配特定的CPU,也不支持分配資源約束。 您可以想象在潛在的多主機(jī)環(huán)境中分配特定CPU并非易事。 因此,我將docker-compose文件遷移回v2,該版本允許分配特定的CPU。 可以用于監(jiān)控軟件,這些CPU和JVM使用的CPU隔離開。 我使用了taskset命令。
同環(huán)境測試
您如何確保所有測試都在完全相同的情況下進(jìn)行? 當(dāng)我針對(duì)JVM運(yùn)行測試而明天再次運(yùn)行相同的測試場景時(shí),我的結(jié)果會(huì)有所不同。 這可能有各種原因,例如不同的CPU會(huì)占用工作負(fù)載,而且這些CPU也忙于處理其他事情,或者我在主機(jī)或客戶操作系統(tǒng)中運(yùn)行不同的后臺(tái)進(jìn)程。 即使***測試單個(gè)JVM并在測試之后測試另一個(gè)JVM,結(jié)果也無法比較。 例如,我正在使用Prometheus收集數(shù)據(jù)。 在第二次運(yùn)行期間,Prometheus數(shù)據(jù)庫可能會(huì)存儲(chǔ)更多數(shù)據(jù)。 這可能會(huì)導(dǎo)致添加新數(shù)據(jù)的速度變慢,這可能會(huì)影響第二個(gè)JVM性能指標(biāo)。 這個(gè)例子雖然可能相當(dāng)牽強(qiáng),但您可以采取措施排除其他因素。 這是我選擇同時(shí)執(zhí)行所有測試的原因。
setup
我的環(huán)境包括一個(gè)docker-compose文件,它允許我輕松啟動(dòng)4個(gè)在不同JVM上運(yùn)行Spring Boot應(yīng)用程序。 在4個(gè)JDK的之前,我加了一個(gè)haproxy實(shí)例來進(jìn)行負(fù)載均衡。 這是為了確保不同的測試之間沒有時(shí)間相關(guān)的差異,保證所有JVM都同時(shí)處于相同的負(fù)載下。
為了監(jiān)控結(jié)果,我使用了Micrometer保證Prometheus能夠讀取JVM性能指標(biāo)。 我使用Grafana對(duì)數(shù)據(jù)可視化:https://grafana.com/dashboards/4701
由于GraalVM目前僅作為JDK 8版本提供,因此其他JVM也使用JDK 8。 當(dāng)容器運(yùn)行時(shí),可以通過訪問執(zhí)行器url來檢查JVM版本:localhost:8080/actuator/env
或者使用如下命令:
docker exec -it store/oracle/serverjre:8 java -version
使用的JVM版本如下:
- GraalVM CE rc9 (8u192)
- OpenJDK 8u191
- Zulu 8u192
- Oracle JDK 8u181
開始測試
可以在這里下載代碼,然后運(yùn)行命令:
sh ./buildjdkcontainers.sh
docker-compose -f docker-compose-jdks.yml up
你可以可以訪問:
- 8080端口的haproxy
- 9090端口的Prometheus
- 3000端口的Grafana
需要配置Grafana訪問Prometheus的數(shù)據(jù)
接下來配置Grafana中的dashboard:
接下來,您可以對(duì)http://localhost:8080/hello(HTTP GET)執(zhí)行負(fù)載測試,并在Grafana儀表板中查看結(jié)果。
操作系統(tǒng)差異
不同Docker鏡像之間使用的OS不同。 操作系統(tǒng)可通過以下方式確定:
- docker exec -it store/oracle/serverjre:8 cat /etc/*-release
- azul/zulu-openjdk:8 used Ubuntu 18.04
- oracle/graalvm-ce:1.0.0-rc9 used Oracle Linux Server 7.5
- openjdk:8 used Debian GNU/Linux 9
- store/oracle/serverjre:8 used Oracle Linux Server 7.5
我認(rèn)為這不會(huì)對(duì)JVM運(yùn)行產(chǎn)生太大的影響。OracleJDK和Graalvm使用相同的操作系統(tǒng)。
測試結(jié)果
使用JVM dashboard,可以輕松區(qū)分特定的差異區(qū)域,以便進(jìn)一步研究它們。
cpu使用
GraalVM在測試期間總體CPU使用率***。 Oracle JDK的CPU使用率***。
響應(yīng)時(shí)間
整體GraalVM的響應(yīng)時(shí)間最短,OpenJDK***,緊隨Oracle JDK和Zulu。 平均而言,OpenJDK與GraalVM之間的差異約為30%。
垃圾回收
GraalVM加載了比其他JDK更多的類。 OpenJDK加載最少的類。 GraalVM和OpenJDK之間的差異大約是25%。 尚未確定這是否是GraalVM的固定開銷,或者與所使用的類的數(shù)量成比例。
這些額外的類可能會(huì)導(dǎo)致垃圾收集期間的延遲(盡管這種相關(guān)性可能不一定是因果關(guān)系)。 GraalVM的的GC暫停時(shí)間確實(shí)最長。
下面是GC暫停時(shí)間總和的圖表。 由于GraalVM中的分配失敗導(dǎo)致了最長的GC暫停時(shí)間(頂部的一行)。
內(nèi)存使用
JVM內(nèi)存使用情況很有意思。 如上圖所示,OpenJDK JVM使用的內(nèi)存堆垛。 GraalVM和Zulu的垃圾收集行為似乎相似,但GraalVM具有更高的內(nèi)存使用率。 Oracle JDK垃圾收集并不頻繁。 在查看平均值時(shí),OpenJDK JVM使用***內(nèi)存,而Zulu使用最少內(nèi)存。 在較長時(shí)間內(nèi)衡量時(shí),Oracle JDK和OpenJDK的行為看起來不穩(wěn)定,而Zulu和GraalVM看起來更穩(wěn)定。
總結(jié)
在本次測試中,我使用SOAP UI對(duì)運(yùn)行在4個(gè)不同JVM上的Spring Boot Rest程序進(jìn)行了壓力測試。我使用Prometheus輪詢JVM實(shí)例(每5s輪訓(xùn)一次,用Micrometer生成數(shù)據(jù)),并使用Grafana和Prometheus來顯示數(shù)據(jù)。結(jié)果表明GraalVM不適合作為OpenJDK的替代品,因?yàn)樗谋憩F(xiàn)更差,使用了更多資源,加載更多類而且垃圾收集時(shí)間更長。
GraalVM加載的類更多
GraalVM 上的應(yīng)用程序響應(yīng)時(shí)間最慢
GraalVM的CPU使用率***(響應(yīng)時(shí)間最慢)
GraalVM的GC時(shí)間最長
Zulu OpenJDK使用的內(nèi)存最少。與Oracle JDK和OpenJDK相比,Zulu OpenJDK和GraalVM的內(nèi)存使用更穩(wěn)定。
當(dāng)然,由于GraalVM相對(duì)較新,Micrometer提供的指標(biāo)可能無法正確顯示實(shí)際吞吐量和資源使用情況。也可能是我的設(shè)置導(dǎo)致這種差異。我通過查看不同情況下的結(jié)果來排除第二個(gè)問題。
如果您想使用GraalVM的多語言功能,那么其他JVM無此功能。GraalVM也提供了本地編譯選項(xiàng)(我在同一個(gè)JAR上執(zhí)行了測試)。此功能可能會(huì)大大提高性能。
原文地址:https://technology.amis.nl/2018/11/23/comparing-jvm-performance-zulu-openjdk-openjdk-oracle-jdk-graalvm-ce/#prettyPhoto