歡迎光臨
每天分享高質量文章

是否值得付費?Oracle,Open JDK等四大JVM效能全面對比

導讀:隨著Java 11 的釋出,Oracle JDK成為收費軟體,很多公司轉向尋找Oracle JDK的替代品。有很多人都會懷疑,Oracle JDK和其他JDK之間有沒有很大的效能差異,本文作者透過多方面測試,給出這個問題的答案,適合Java程式員研讀。

 

市面上可供選擇的JVM發行版還是有不少的。選擇合適的JVM需要考慮不同的因素。效能是其中一個重要的因素。靠譜的效能研究是很困難的。在本文中,我建立了一個測試,在不同的JVM上執行對比測試。測試程式包括Spring Boot REST應用,使用Prometheus監控JVM並使用Grafana視覺化。下圖是示意圖。除了soapui外,所有東西都在docker容器中執行。

 

隔離幹擾因素

如何確定沒有別的因素幹擾你的設施。我們可以透過嘗試隔離分配給流程的資源來實現。 例如,分配專用CPU和固定數量的記憶體。 我還進行了幾項測試,這些測試將資源限制放在負載均衡器,監控軟體和視覺化軟體上(為這些資源分配不同的CPU和記憶體)。 為行程分配特定資源(使用docker-compose v2 cpuset和記憶體引數)似乎不會對單個行程負載和響應時間的度量產生很大影響。 我還比較了啟動,負載和無負載情況。 在這些不同情況下,測試結果沒有很大變化。

為行程分配特定CPU和記憶體

使用docker-compose無法為行程配置特定CPU。 docker-compose v3不支援為行程分配特定的CPU,也不支援分配資源約束。 您可以想象在潛在的多主機環境中分配特定CPU並非易事。 因此,我將docker-compose檔案遷移回v2,該版本允許分配特定的CPU。 可以用於監控軟體,這些CPU和JVM使用的CPU隔離開。 我使用了taskset命令。

同環境測試

您如何確保所有測試都在完全相同的情況下進行? 當我針對JVM執行測試而明天再次執行相同的測試場景時,我的結果會有所不同。 這可能有各種原因,例如不同的CPU會佔用工作負載,而且這些CPU也忙於處理其他事情,或者我在主機或客戶作業系統中執行不同的後臺行程。 即使首次測試單個JVM併在測試之後測試另一個JVM,結果也無法比較。 例如,我正在使用Prometheus收集資料。 在第二次執行期間,Prometheus資料庫可能會儲存更多資料。 這可能會導致新增新資料的速度變慢,這可能會影響第二個JVM效能指標。 這個例子雖然可能相當牽強,但您可以採取措施排除其他因素。 這是我選擇同時執行所有測試的原因。

setup

我的環境包括一個docker-compose檔案,它允許我輕鬆啟動4個在不同JVM上執行Spring Boot應用程式。 在4個JDK的之前,我加了一個haproxy實體來進行負載均衡。 這是為了確保不同的測試之間沒有時間相關的差異,保證所有JVM都同時處於相同的負載下。

為了監控結果,我使用了Micrometer保證Prometheus能夠讀取JVM效能指標。 我使用Grafana對資料視覺化:https://grafana.com/dashboards/4701

由於GraalVM目前僅作為JDK 8版本提供,因此其他JVM也使用JDK 8。 當容器執行時,可以透過訪問執行器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


開始測試

可以在這裡下載程式碼,然後執行命令:

sh ./buildjdkcontainers.sh

docker-compose -f docker-compose-jdks.yml up

你可以可以訪問:

  • 8080埠的haproxy
  • 9090埠的Prometheus
  • 3000埠的Grafana

需要配置Grafana訪問Prometheus的資料

接下來配置Grafana中的dashboard:


接下來,您可以對http://localhost:8080/hello(HTTP GET)執行負載測試,併在Grafana儀錶板中檢視結果。

作業系統差異

不同Docker映象之間使用的OS不同。 作業系統可透過以下方式確定:

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

我認為這不會對JVM執行產生太大的影響。OracleJDK和Graalvm使用相同的作業系統。

測試結果

使用JVM dashboard,可以輕鬆區分特定的差異區域,以便進一步研究它們。

 

cpu使用

 

GraalVM在測試期間總體CPU使用率最高。 Oracle JDK的CPU使用率最低。

 

響應時間

 

整體GraalVM的響應時間最短,OpenJDK最好,緊隨Oracle JDK和Zulu。 平均而言,OpenJDK與GraalVM之間的差異約為30%。

垃圾回收

 

GraalVM載入了比其他JDK更多的類。 OpenJDK載入最少的類。 GraalVM和OpenJDK之間的差異大約是25%。 尚未確定這是否是GraalVM的固定開銷,或者與所使用的類的數量成比例。

 

這些額外的類可能會導致垃圾收集期間的延遲(儘管這種相關性可能不一定是因果關係)。 GraalVM的的GC暫停時間確實最長。

下麵是GC暫停時間總和的圖表。 由於GraalVM中的分配失敗導致了最長的GC暫停時間(頂部的一行)。

 

記憶體使用

 

 

JVM記憶體使用情況很有意思。 如上圖所示,OpenJDK JVM使用的記憶體堆垛。 GraalVM和Zulu的垃圾收集行為似乎相似,但GraalVM具有更高的記憶體使用率。 Oracle JDK垃圾收集並不頻繁。 在檢視平均值時,OpenJDK JVM使用最大記憶體,而Zulu使用最少記憶體。 在較長時間內衡量時,Oracle JDK和OpenJDK的行為看起來不穩定,而Zulu和GraalVM看起來更穩定。

 

總結

 

在本次測試中,我使用SOAP UI對執行在4個不同JVM上的Spring Boot Rest程式進行了壓力測試。我使用Prometheus輪詢JVM實體(每5s輪訓一次,用Micrometer生成資料),並使用Grafana和Prometheus來顯示資料。結果表明GraalVM不適合作為OpenJDK的替代品,因為它的表現更差,使用了更多資源,載入更多類而且垃圾收集時間更長。

  • GraalVM載入的類更多
  • GraalVM 上的應用程式響應時間最慢
  • GraalVM的CPU使用率最高(響應時間最慢)
  • GraalVM的GC時間最長
  • Zulu OpenJDK使用的記憶體最少。與Oracle JDK和OpenJDK相比,Zulu OpenJDK和GraalVM的記憶體使用更穩定。

當然,由於GraalVM相對較新,Micrometer提供的指標可能無法正確顯示實際吞吐量和資源使用情況。也可能是我的設定導致這種差異。我透過檢視不同情況下的結果來排除第二個問題。

如果您想使用GraalVM的多語言功能,那麼其他JVM無此功能。GraalVM也提供了本地編譯選項(我在同一個JAR上執行了測試)。此功能可能會大大提高效能。

原文地址:
https://technology.amis.nl/2018/11/23/comparing-jvm-performance-zulu-openjdk-openjdk-oracle-jdk-graalvm-ce/#prettyPhoto

本文作者Maarten Smeets,由方圓翻譯。轉載本文請註明出處,歡迎更多小夥伴加入翻譯及投稿文章的行列,詳情請戳公眾號選單「聯絡我們」。GIAC全球網際網路架構大會深圳站將於2019年6月舉行,屆時將有Java專題深入探討相關話題,敬請期待。

贊(0)

分享創造快樂