市面上还有很多JVM版本可供选择。选择正确的JVM需要考虑不同的因素。性能是重要因素之一。可靠的性能研究很困难。在本文中,我创建了一个在不同JVM上执行比较测试的测试。测试程序由一个SpringBootREST应用组成,使用Prometheus监控JVM,使用Grafana进行可视化。下图是示意图。除soapui外,一切都在docker容器中运行。如何隔离干扰因素确保没有其他因素干扰您的设施。我们可以通过尝试隔离分配给进程的资源来做到这一点。例如,分配专用CPU和固定数量的内存。我还运行了几个测试,对负载平衡器、监控软件和可视化软件施加资源限制(为这些资源分配不同的CPU和内存)。为进程分配特定资源(使用docker-composev2cpuset和内存参数)似乎对单个进程负载和响应时间测量没有太大影响。我还比较了启动、负载和空载条件。在这些不同的情况下,测试结果相差不大。为进程分配特定的CPU和内存使用docker-compose无法为进程配置特定的CPU。docker-composev3不支持为进程分配特定的CPU,也不支持分配资源约束。可以想象,在潜在的多主机环境中分配特定CPU并非易事。所以我将docker-compose文件迁移回v2,它允许特定的CPU分配。可用于监控软件,这些CPU与JVM使用的CPU是隔离的。我使用了任务集命令。您如何确保所有测试都在完全相同的条件下运行?当我针对JVM运行测试并在明天再次运行相同的测试场景时,我的结果会有所不同。这可能有多种原因,比如不同的CPU占用了工作负载,而这些CPU也忙于其他事情,或者我在主机或来宾操作系统中运行了不同的后台进程。即使你***测试单个JVM,测试完再测试另一个JVM,结果也没有可比性。例如,我正在使用Prometheus来收集数据。在第二次运行期间,Prometheus数据库可能会存储更多数据。这会导致添加新数据的速度变慢,从而影响第二个JVM性能指标。虽然这个例子可能相当牵强,但您可以采取一些步骤来排除其他因素。这就是我选择同时执行所有测试的原因。设置我的环境包括一个docker-compose文件,它允许我轻松启动4个运行在不同JVM上的SpringBoot应用程序。在4个JDK之前,我加了一个haproxy实例来做负载均衡。这是为了确保不同测试之间没有与时间相关的差异,并且所有JVM同时处于相同负载下。为了监控结果,我使用了Micrometer来确保Prometheus能够读取JVM性能指标。我使用Grafana进行数据可视化:https://grafana.com/dashboards/4701由于GraalVM目前只有JDK8版本,其他JVM也使用JDK8。当容器运行时,您可以通过以下方式查看JVM版本访问actuatorurl:localhost:8080/actuator/env或者使用如下命令:dockerexec-itstore/oracle/serverjre:8java-version使用的JVM版本如下:GraalVMCErc9(8u192)OpenJDK8u191Zulu8u192OracleJDK8u181开始测试你可以在这里下载代码,然后运行命令:sh./buildjdkcontainers.shdocker-compose-fdocker-compose-jdks.ymlup你可以访问:haproxyonport8080Prometheusonport9090Grafanaon3000端口需要配置Grafana才能访问Prometheus数据。接下来在Grafana中配置dashboard:接下来可以对http://localhost:8080/hello(HTTPGET)进行负载测试,并在Grafanainstrument上显示在dashboard上查看结果。操作系统差异不同的Docker镜像使用不同的操作系统。可以通过以下方式确定操作系统:dockerexec-itstore/oracle/serverjre:8cat/etc/*-releaseazul/zulu-openjdk:8usedUbuntu18.04oracle/graalvm-ce:1.0.0-rc9usedOracleLinuxServer7.5openjdk:8usedDebianGNU/Linux9store/oracle/serverjre:8usedOracleLinuxServer7.5我认为这对JVM运行不会有太大影响。OracleJDK和Graalvm使用相同的操作系统。测试结果使用JVM仪表板,可以轻松识别特定的差异区域,以便您可以进一步调查它们。cpu使用GraalVM进行测试期间的总体CPU使用率***。OracleJDK的CPU使用率***。响应时间GraalVM的整体响应时间最短,OpenJDK最好,其次是OracleJDK和Zulu。平均而言,OpenJDK和GraalVM之间的差异约为30%。垃圾收集GraalVM比其他JDK加载更多的类。OpenJDK加载最少的类。GraalVM和OpenJDK之间的差异约为25%。尚未确定这是GraalVM的固定开销,还是与使用的类数成正比。这些额外的类可能会导致垃圾收集期间的延迟(尽管这种相关性不一定是因果关系)。GraalVM确实有最长的GC暂停时间。下面是GC暂停时间总和的图表。最长的GC暂停(顶行)是由于GraalVM中的分配失败。内存使用JVM内存使用很有趣。如上图所示,OpenJDKJVM使用的内存栈。GraalVM和Zulu的垃圾回收行为似乎相似,但GraalVM的内存占用更高。OracleJDK垃圾回收很少见。查看平均值时,OpenJDKJVM使用的内存最多,而Zulu使用最少。当在较长时间段内进行测量时,OracleJDK和OpenJDK的行为似乎不稳定,而Zulu和GraalVM似乎更稳定。总结在本次测试中,我使用SOAPUI对运行在4个不同JVM上的SpringBootRest程序进行了压力测试。我使用Prometheus轮询JVM实例(每5s轮询一次,用Micrometer生成数据),并使用Grafana和Prometheus显示数据。事实证明,GraalVM不适合作为OpenJDK的替代品,因为它性能更差、使??用更多资源、加载更多类并且垃圾收集时间更长。GraalVM加载更多类GraalVM上的应用程序具有最慢的响应时间GraalVMCPU使用率***(最慢的响应时间)GraalVM具有最长的GC时间ZuluOpenJDK使用最少的内存。ZuluOpenJDK和GraalVM的内存使用比OracleJDK和OpenJDK更稳定。当然,由于GraalVM相对较新,Micrometer提供的指标可能无法正确显示实际吞吐量和资源使用情况。也可能是我的设置导致了这种差异。我通过查看不同情况下的结果排除了第二个问题。如果你想使用GraalVM的多语言能力,其他JVM没有这个能力。GraalVM还提供了一个本地编译选项(我在同一个JAR上执行了测试)。此功能可能会大大提高性能。原文地址:https://technology.amis.nl/2018/11/23/comparing-jvm-performance-zulu-openjdk-openjdk-oracle-jdk-graalvm-ce/#prettyPhoto
