大型应用程序的 JVM 性能调优

2024-01-20

默认 JVM 参数对于运行大型应用程序来说并不是最佳的。在实际应用程序上进行过调整的人们的任何见解都会有所帮助。我们在 32 位 Windows 机器上运行应用程序,其中使用客户端 JVM默认情况下 http://java.sun.com/docs/hotspot/gc5.0/ergo5.html#0.0.%20Garbage%20collector,%20heap,%20and%20runtime%20compiler%7Coutline。我们添加了 -server 并将 NewRatio 更改为 1:3(更大的年轻一代)。

您尝试过并发现有用的任何其他参数/​​调整吗?

[更新] 我所说的特定类型的应用程序是很少关闭的服务器应用程序,至少需要-Xmx1024m。还假设已经对应用程序进行了分析。我正在寻找以下方面的一般准则JVM性能 only.


Foreword

背景

去过 Java 商店。花了整整几个月的时间专门在分布式系统上运行性能测试,主要应用程序是用 Java 编写的。其中一些暗示产品由 Sun 自己(当时的 Oracle)开发和销售。

我将回顾我学到的经验教训、一些关于 JVM 的历史、一些关于内部结构的讨论、解释的几个参数以及最后的一些调整。尽量保持要点,以便您可以将其应用到实践中。

Java 世界中的事物正在快速变化,因此自去年我完成所有这些工作以来,其中的一部分可能已经过时了。 (Java 10 已经出来了吗?)

良好实践

你应该做什么:基准,基准,基准!

当您确实需要了解性能时,您需要针对您的工作负载执行真正的基准测试。没有其他选择。

Also, 你应该监控 JVM。启用监控。好的应用程序通常会提供监控网页和/或 API。除此之外还有常见的 Java 工具(JVisualVM、JMX、hprof 和一些 JVM 标志)。

请注意,通过调整 JVM 通常无法获得性能提升。它更多的是一个“崩溃还是不崩溃,找到过渡点”。这是关于知道当你给予时that您的应用程序的资源量,您可以始终期望that作为回报的表演量。知识就是力量。

性能主要取决于您的应用程序。如果你想要更快,你就必须编写更好的代码。

大多数时候你会做什么:接受可靠的敏感默认设置

我们没有时间优化和调整每个应用程序。大多数时候,我们只会接受合理的默认设置。

配置新应用程序时要做的第一件事是阅读文档。大多数重要的应用程序都附带性能调整指南,包括有关 JVM 设置的建议。

然后您可以配置应用程序:JAVA_OPTS: -server -Xms???g -Xmx???g

  • -server:启用全面优化(该标志在当今大多数 JVM 上是自动的)
  • -Xms -Xmx:设置最小和最大堆(两者始终具有相同的值,这是唯一要做的优化)。

干得好,您已经了解了有关 JVM 的所有优化参数,恭喜!这很简单:D

你永远不应该做的事:

请不要复制您在互联网上找到的随机字符串,尤其是当它们采用多行时,如下所示:

-server  -Xms1g -Xmx1g  -XX:PermSize=1g -XX:MaxPermSize=256m  -Xmn256m -Xss64k  -XX:SurvivorRatio=30  -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled  -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=10  -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark  -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Dsun.net.inetaddr.ttl=5  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=`date`.hprof   -Dcom.sun.management.jmxremote.port=5616 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -server -Xms2g -Xmx2g -XX:MaxPermSize=256m -XX:NewRatio=1 -XX:+UseConcMarkSweepGC

例如,在谷歌首页上发现的这个东西简直太糟糕了。多次指定的参数具有冲突的值。有些只是强制使用 JVM 默认值(最终是 2 个 JVM 版本之前的默认值)。有一些已经过时并且被简单地忽略了。最后,至少有一个参数是如此无效,以至于它的存在就会在启动时持续导致 JVM 崩溃。

实际调音

如何选择内存大小:

阅读您的应用程序中的指南,它应该给出一些指示。监控生产并随后进行调整。如果需要准确性,请执行一些基准测试。

重要的提示:java进程将花费最大堆加 10%。 X% 的开销是堆管理的开销,不包含在堆本身中。

所有内存通常由进程在启动时预先分配。您可能会看到该进程一直使用最大堆。这根本不是真的。您需要使用 Java 监控工具来查看真正正在使用的内容。

寻找合适的尺寸:

  • 如果它因 OutOfMemoryException 崩溃,则内存不足
  • 如果没有因 OutOfMemoryException 崩溃,则内存太多
  • 如果内存太多,但硬件已获得它和/或已经付费,那么它就是perfect数,工作完成!

JVM6 是青铜级,JVM7 是黄金级,JVM8 是白金级......

JVM 一直在不断改进。垃圾收集是一件非常复杂的事情,有很多非常聪明的人在研究它。它在过去十年中取得了巨大的进步,并将继续如此。

仅供参考。它们是 Oracle Java 7-8 (HotSpot) 和 OpenJDK 7-8 中至少 4 个可用的垃圾收集器。 (其他 JVM 可能完全不同,例如 Android、IBM、嵌入式):

  • SerialGC
  • 并行GC
  • 并发标记清除GC
  • G1GC
  • (加上变体和设置)

[从 Java 7 及更高版本开始。 Oracle 和 OpenJDK 代码部分共享。两个平台上的 GC 应该(大部分)相同。]

JVM >= 7 有许多优化并选择合适的默认值。它因平台而略有变化。它平衡了多种事物。例如,决定是否启用多核优化,无论 CPU 是否有多个核心。你应该让它去做。请勿更改或强制 GC 设置。

让计算机为你做决定是可以的(这就是计算机的用途)。最好让 JVM 设置始终保持 95% 的最佳状态,而不是在所有机器上强制执行“始终积极收集 8 个核心以缩短暂停时间”(其中一半最终为 t2.small)。

例外:当应用程序附带性能指南和特定调整时。保留提供的设置不变是完全可以的。

Tip:迁移到较新的 JVM 以从最新改进中受益有时可以无需付出太多努力即可提供良好的提升。

特殊情况:-XX:+UseCompressedOops

JVM 有一个特殊的设置,强制在内部使用 32 位索引(读作:类似指针)。这允许寻址 4 294 967 295 个对象 * 8 字节地址 => 32 GB 内存。 (不要与 REAL 指针的 4GB 地址空间混淆)。

它减少了总体内存消耗,并对所有缓存级别产生潜在的积极影响。

现实生活中的例子:ElasticSearch 文档指出,就内存中保存的实际数据而言,正在运行的 32GB 32 位节点可能相当于 40GB 64 位节点。

关于历史的注释:已知该标志在 java-7 之前的时代(甚至可能是 java-6 之前)不稳定。它在较新的 JVM 中已经完美运行了一段时间。

Java HotSpot™ 虚拟机性能增强 https://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html

[...] 在 Java SE 7 中,当未指定 -Xmx 且 -Xmx 值小于 32 GB 时,64 位 JVM 进程默认使用压缩 oop。对于 6u23 版本之前的 JDK 6,请在 java 命令中使用 -XX:+UseCompressedOops 标志来启用该功能。

See:JVM 再次比手动调优领先数年。不过,了解它还是很有趣的 =)

特殊情况:-XX:+UseNUMA

非均匀内存访问(NUMA)是一种用于多处理的计算机内存设计,内存访问时间取决于相对于处理器的内存位置。来源:维基百科 https://en.wikipedia.org/wiki/Non-uniform_memory_access

现代系统具有极其复杂的内存架构,具有跨核心和 CPU 的多层内存和缓存(私有和共享)。

很明显,访问当前处理器中二级缓存中的数据比必须从另一个插槽一直访问记忆棒要快得多。

我相信所有的多socket今天销售的系统在设计上是 NUMA,而所有消费者系统都不是。使用命令检查您的服务器是否支持NUMAnumactl --show在Linux上。

NUMA 感知标志告诉 JVM 优化底层硬件拓扑的内存分配。

性能提升可能是巨大的(即两位数:+XX%)。事实上,如果有人从“NOT-NUMA 10CPU 100GB”切换到“NUMA 40CPU 400GB”,如果他不了解该标志,他可能会经历性能的[戏剧性]损失。

Note:有讨论检测 NUMA 并在 JVM 中自动设置标志http://openjdk.java.net/jeps/163 http://openjdk.java.net/jeps/163

Bonus:所有打算在大型硬件(即 NUMA)上运行的应用程序都需要针对它进行优化。它并不特定于 Java 应用程序。

走向未来:-XX:+UseG1GC

垃圾收集的最新改进是G1 收集器(阅读:垃圾优先) http://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html.

它适用于高核心、高内存系统。绝对至少 4 核 + 6 GB 内存。它针对的是使用 10 倍及以上的数据库和内存密集型应用程序。

简而言之,在这些规模下,传统 GC 面临着太多数据无法立即处理,并且暂停变得失控。 G1 将堆分成许多小部分,这些小部分可以在应用程序运行时独立并行管理。

第一个版本于 2013 年推出。现在已经足够成熟,可以用于生产,但不会很快成为默认版本。对于大型应用程序来说,这值得一试。

不要碰:世代大小(NewGen、PermGen...)

GC 将内存分成多个部分。 (不赘述,可以google一下“Java GC Generations”。)

上次我花了一周时间在每秒点击 10000 次的应用程序上尝试 20 种不同的代标记组合。我得到了从 -1% 到 +1% 的巨大提升。

Java GC 生成是一个值得阅读或撰写相关论文的有趣主题。它们不是需要调整的东西,除非您是那 1% 的人中的一员,他们可以在真正需要优化的 1% 人中投入大量时间来获得微不足道的收益。

结论

希望这可以帮到你。享受 JVM 带来的乐趣。

Java是世界上最好的语言和最好的平台!去传播爱吧:D

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大型应用程序的 JVM 性能调优 的相关文章

  • 如何在一行中将字符串数组转换为双精度数组

    我有一个字符串数组 String guaranteedOutput Arrays copyOf values values length String class 所有字符串值都是数字 数据应转换为Double QuestionJava 中
  • AES 加密 Java/plsql

    我需要在Java和plsql DBMS CRYPTO for Oracle 10g 上实现相同的加密 解密应用程序 两种实现都工作正常 但这里的问题是我对相同纯文本的加密得到了不同的输出 下面是用于加密 解密过程的代码 Java 和 PLS
  • 在Windows上安装Java 11 OpenJDK(系统路径问题)

    Java 11 最近发布了 众所周知 这个版本没有安装文件 当然 要在没有安装程序的情况下安装 Java 我将系统设置 PATH 和 JAVA HOME 设置为解压缩 Java 11 的文件夹的地址 根据对类似问题的已接受回复建议 唯一的事
  • manifest.mf 文件的附加内容的约定?

    Java JAR 中的 MANIFEST MF 文件是否有任何超出 MANIFEST MF 约定的约定 JAR规范 http download oracle com javase 1 4 2 docs guide jar jar html
  • 如何查找 Android 设备中的所有文件并将它们放入列表中?

    我正在寻求帮助来列出 Android 外部存储设备中的所有文件 我想查找所有文件夹 包括主文件夹的子文件夹 有办法吗 我已经做了一个基本的工作 但我仍然没有得到想要的结果 这不起作用 这是我的代码 File files array file
  • CXF Swagger2功能添加安全定义

    我想使用 org apache cxf jaxrs swagger Swagger2Feature 将安全定义添加到我的其余服务中 但是我看不到任何相关方法或任何有关如何执行此操作的资源 下面是我想使用 swagger2feature 生成
  • 使用 ANTLR 为 java 源代码生成抽象语法树

    如何使用 ANTLR 从 java src 代码生成 AST 有什么帮助吗 好的 步骤如下 前往ANTLR站点 http www antlr org 并下载最新版本 下载Java g和JavaTreeParser g文件来自here htt
  • Java中接口作为方法参数

    前几天去面试 被问到了这样的问题 问 反转链表 给出以下代码 public class ReverseList interface NodeList int getItem NodeList nextNode void reverse No
  • 从 android 简单上传到 S3

    我在网上搜索了从 android 上传简单文件到 s3 的方法 但找不到任何有效的方法 我认为这是因为缺乏具体步骤 1 https mobile awsblog com post Tx1V588RKX5XPQB TransferManage
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • 检查 protobuf 消息 - 如何按名称获取字段值?

    我似乎无法找到一种方法来验证 protobuf 消息中字段的值 而无需显式调用其 getter 我看到周围的例子使用Descriptors FieldDescriptor实例到达消息映射内部 但它们要么基于迭代器 要么由字段号驱动 一旦我有
  • 尝试使用 Ruby Java Bridge (RJB) gem 时出现错误“无法创建 Java VM”

    我正在尝试实现 Ruby Java Bridge RJB gem 来与 JVM 通信 以便我可以运行 Open NLP gem 我在 Windows 8 上安装并运行了 Java 所有迹象 至少我所知道的 都表明 Java 已安装并可运行
  • 将多模块 Maven 项目导入 Eclipse 时出现问题 (STS 2.5.2)

    我刚刚花了最后一个小时查看 Stackoverflow com 上的线程 尝试将 Maven 项目导入到 Spring ToolSuite 2 5 2 中 Maven 项目有多个模块 当我使用 STS 中的 Import 向导导入项目时 所
  • 使用 Flyway 和 Hibernate 的 hbm2ddl 在应用程序的生命周期中管理数据库模式

    我正在开发 Spring Hibernate MySql 应用程序 该应用程序尚未投入生产 我目前使用 Hibernatehbm2ddl该功能对于管理域上的更改非常方便 我也打算用Flyway用于数据库迁移 在未来的某个时候 该应用程序将首
  • Tomcat 6找不到mysql驱动

    这里有一个类似的问题 但关于类路径 ClassNotFoundException com mysql jdbc Driver https stackoverflow com questions 1585811 classnotfoundex
  • 运行 Jar 文件时出现问题

    我已将 java 项目编译成 Jar 文件 但运行它时遇到问题 当我跑步时 java jar myJar jar 我收到以下错误 Could not find the main class myClass 类文件不在 jar 的根目录中 因
  • Keycloak - 自定义 SPI 未出现在列表中

    我为我的 keycloak 服务器制作了一个自定义 SPI 现在我必须在管理控制台上配置它 我将 SPI 添加为模块 并手动安装 因此我将其放在 module package name main 中 并包含 module xml 我还将其放
  • 正则表达式库基准

    我最近一直想知道正则表达式实现的性能 并且很难想出很多有用的信息 它很容易对浏览器 javascript 正则表达式性能进行基准测试 网上有很多工具 Chrome 和 Opera 中的 javascript 正则表达式实现几乎摧毁了所有其他
  • 将 JTextArea 内容写入文件

    我在 Java Swing 中有一个 JTextArea 和一个 提交 按钮 需要将textarea的内容写入一个带有换行符的文件中 我得到的输出是这样的 它被写为文件中的一个字符串 try BufferedWriter fileOut n
  • JAVA - 如何从扫描仪读取文件中检测到“\n”字符

    第一次海报 我在读取文本文件的扫描仪中读取返回字符时遇到问题 正在读取的文本文件如下所示 test txt start 2 0 30 30 1 1 90 30 0 test txt end 第一行 2 表示两个点 第二行 位置索引 0 xp

随机推荐

  • 检查 CancellationTokenSource.Cancel() 是否已使用 Moq 调用

    我有一个条件语句 应如下所示 if view VerifyData true else view PermanentCancellation Cancel 其中 PermanentCancellation 的类型为 Cancellation
  • 如何获取 Windows 用户帐户的用户权限和特权

    我需要能够检查所有these http technet microsoft com en us library dd349804 v WS 10 aspx用户权利和特权 我尝试使用令牌来访问这些 但这仅完成了权限列表 我查过这个图书馆 ht
  • 每个 Android 设备的唯一 ID

    我实际上正在开发一个 Android 应用程序 希望为每个 Android 设备捕获唯一的 Id 但不确定哪个 Id 是可靠的 电话号码Imei imsi 从android 10开始 即使提供了权限 第三方应用程序也将无法检索此id 安全
  • 链式作业如何进行?

    引用某事 gt gt gt x y somefunction 是相同的 gt gt gt y somefunction gt gt gt x y 问题 是 x y somefunction 与 x somefunction y somefu
  • “3.4E +/- 38(7 位数字)”到底是什么意思? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我试图了解数据类型的范围 对于非浮点
  • ELOOP:遇到太多符号链接

    当尝试点击命令时 npm install g angular email protected cdn cgi l email protection Note 我有 Node Js LTS 10 xx 版本 Net Framework 4 7
  • StreamSocket、DataWriter.StoreAsync()、DataReader.LoadAsync() -- 异步问题

    我正在创建一个 Win 8 商店应用程序 在其中使用 StreamSocket 连接到用 Java 编写的服务器 当我在调试中运行应用程序时 在 StreamSocket ConnectAsync DataWriter StoreAsync
  • Swift:以模态方式呈现并解除导航控制器

    我有一个非常常见的 iOS 应用场景 The MainVC该应用程序的一个UITabBar控制器 我在 AppDelegate swift 文件中将此 VC 设置为 rootViewController func application a
  • “不匹配”的正则表达式语法?

    我有一个大量使用正则表达式的 python 模板引擎 它使用像这样的串联 re compile regexp1 regexp2 regexp3 我可以修改各个子字符串 regexp1 regexp2 等 是否有任何不匹配的小而轻的表达式 我
  • Keras Tuner:根据层数选择单元数

    我正在使用 Keras Tuner 来调整神经网络的超参数 我想搜索隐藏层的最佳数量以及每层中的最佳单元数 为了避免模型过度参数化 我想施加以下条件 如果模型有两层 则选择最佳的单元数 每层最多 64 个 如果模型有一层 则选择最佳的单元数
  • iOS swift3 图表xaxis重复值问题

    我在使用 iOS 图表库为 xAxis 创建字符串值时遇到问题 x 值总是有重复值 请参见下图 您可以看到值总是JAN JAN JAN JAN FEB FEB FEB 我如何设置图表的 x 值 如下所示JAN FEB MAR import
  • PHP - 如何将数组发送到另一个页面?

    我正在尝试将数组发送到另一个页面 我之前尝试过的是 page1
  • 如何通过调用命名空间中没有该方法的函数来找到未附加包中的非导入方法?

    R 命名空间充当其关联包中所有函数的直接环境 换句话说 当函数bar 从包装中foo调用另一个函数 R 求值器首先在中搜索另一个函数
  • JQuery Select2 - 如何选择所有选项

    我正在使用 jQuery select2 多选下拉列表 我需要从代码中选择下拉列表中的所有选项 基本上有一个全选复选框 必须在其上实现此功能 我想从此复选框中选择 取消选择选项 使用选择 2DEMO http jsfiddle net jE
  • 强制 MATLAB 重新加载 mex 函数中链接的库

    我有一个墨西哥功能 比如说myfunction mexmaci64 这是 OS X 上的正确结局 现在 myfunction 链接到一个库mylibrary dylib mex 文件和库都位于同一文件夹中 现在 每当我改变一些东西mylib
  • Delphi:启动应用程序的快捷方式在哪里? [复制]

    这个问题在这里已经有答案了 我知道可以使用 Application Exename 找到当前可执行文件所在的目录 但是当应用程序使用另一个目录中的快捷方式启动时呢 我可以找到快捷方式所在的那个目录的地址吗 因为我想在那里创建一些文件 使用X
  • CORS 和 Web 扩展

    我设置了一个服务器http 本地主机 8080 http localhost 8080 where http example com http example com可以执行 POST 请求 use strict const express
  • 将 Microsoft Azure Function App 2.0 预览版绑定到 0.0.0.0

    我有一个用 C 编写的 Microsoft Azure Function App 2 0 预览版 它绑定到http 本地主机 7071 http localhost 7071 如何将其绑定到 0 0 0 0 而不是 localhost 以便
  • 耶拿:如何推断数据/性能问题

    我想使用 Jena 的推理功能 但在使用 InfModel 时遇到一些性能问题 这是我的本体的简化概述 特性 hasX Ranges intersection X inverse properties isXOf hasSpecialX R
  • 大型应用程序的 JVM 性能调优

    默认 JVM 参数对于运行大型应用程序来说并不是最佳的 在实际应用程序上进行过调整的人们的任何见解都会有所帮助 我们在 32 位 Windows 机器上运行应用程序 其中使用客户端 JVM默认情况下 http java sun com do