java - 如何通过负载测试优化 JVM & GC

标签 java optimization garbage-collection jvm load-testing

编辑 :在这个问题已经收到的几个非常慷慨和有帮助的回答中,我很明显在今天早上早些时候问这个问题时没有把这个问题的重要部分说清楚。到目前为止,我收到的答案更多是关于优化应用程序和消除代码级别的瓶颈。我知道这比尝试从 JVM 中获得额外的 3% 或 5% 重要得多!

这个问题假设我们已经做了几乎所有可以在代码级别优化我们的应用程序架构的工作。现在我们想要更多,接下来要看的是JVM级别和垃圾收集;我相应地更改了问题标题。再次感谢!

我们有一个“管道”风格的后端架构,其中消息从一个组件传递到下一个组件,每个组件在每一步执行不同的过程。

组件位于部署在 Tomcat 服务器上的 WAR 文件中。我们总共有大约 20 个组件在管道中,位于 5 个不同的 Tomcat 服务器上(我没有为每个服务器选择架构或 WAR 的分布)。我们使用 Apache Camel 创建组件之间的所有路径,有效地形成管道的“结缔组织”。

我被要求优化每个运行 JVM 的服务器的 GC 和一般性能(总共 5 个)。我已经花了几天时间阅读 GC 和性能调优,并且对每个不同的 JVM 选项的作用、堆的组织方式以及大多数选项如何影响 JVM 的整体性能有很好的了解.

我的想法是优化每个 JVM 的最佳方法不是将其作为独立的进行优化。我“感觉”(这是我所能证明的!)尝试在本地优化每个 JVM 而不考虑它如何与其他服务器(上游和下游)上的其他 JVM 交互不会产生全局优化的解决方案.

对我来说,从整体上优化整个管道是有意义的。所以我的第一个问题是: SO 是否同意,如果不同意,为什么?

为此,我正在考虑创建一个 LoadTester这将生成输入并将其提供给管道中的第一个端点。此 LoadTester可能还有一个单独的“监控线程”来检查最后一个端点的吞吐量。然后,我可以进行各种处理,检查消息的平均端到端旅行时间、故障前的最大吞吐量等。
LoadTester会一遍又一遍地生成相同模式的输入消息。本实验中的变量是传递给每个 Tomcat 服务器启动选项的 JVM 选项。我有一个大约 20 个不同选项的列表,我想通过 JVM,并认为我可以不断调整它们的值,直到找到接近最佳的性能。

这可能不是做到这一点的绝对最佳方式,但这是我可以用我为这个项目(大约一周)获得的时间进行设计的最佳方式。

第二个问题: SO对这个设置有什么看法?那么如何以不同的方式创建“优化解决方案”?

最后但并非最不重要的一点是,我很好奇我可以使用什么样的指标作为衡量和比较的基础。我真的只能想到:

  • 找到为消息产生最快平均端到端旅行时间的 JVM 选项配置
  • 找到在不使任何服务器崩溃的情况下产生最大容量吞吐量的 JVM 选项配置

  • 还有其他人吗?这两个不好的原因是什么?

    在查看剧本后,我可以看到如何将其解释为一个整体问题,但实际上我要问的是 SO 将如何优化沿管道运行的 JVM,并且可以随意切割我的解决方案,无论你喜欢什么它。

    提前致谢!

    最佳答案

    让我更上一层楼,说我多年前在一个大型 C 应用程序中做过类似的事情。
    它由许多跨互连硬件交换消息的进程组成。
    我想出了一个两步走的方法。

    第 1 步。在每个过程中,我使用了 this technique摆脱任何浪费的 Activity 。
    这需要几天的采样、修改代码和重复。
    这个想法是有一个链条,首先要做的是消除链接中的低效率。

    第 2 步。这部分费力但有效:生成消息流量的时间戳日志。
    将它们合并到一个共同的时间线中。
    仔细查看特定的消息序列。
    你要找的是

  • 该消息是必要的,还是由于超时或其他可避免的原因导致的重传?
  • 消息是何时发送、接收和执行的?如果在收到和采取行动之间存在显着延迟,那么延迟的原因是什么?例如,是否只是“排队”在另一个进行 I/O 的进程后面?是否可以通过不同的流程优先级进行修复?

  • 这个 Activity 花了我大约一天的时间来生成日志、组合它们、找到加速机会并修改代码。
    按照这个速度,大约 10 个工作日后,我发现/修复了许多问题,并大大提高了速度。

    这两个步骤的共同点是我没有测量或试图获得“统计数据”。
    如果某件事花费了太多时间,那么这个事实就会暴露给一个勤奋的程序员,仔细观察正在发生的事情。

    关于java - 如何通过负载测试优化 JVM & GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8745695/

    相关文章:

    c# - 在非托管异步操作期间保持对象事件

    java - 在eclipse中的tomcat上部署maven构建项目

    java - 如何用 Java 进行 FTP

    java - 无法解析 AJAX 中 servlet 返回的 JSON 对象

    java - Cypher 使用不在实体中的参数创建查询

    c++ - 我该怎么做——像一个人一样快速地修改 2 的幂++ 2 的幂?

    c# - 如何向 C# XmlDocument 添加新的根元素?

    c# - 我如何优化这个像素不透明度计算?

    java - 调整 GC (CMS) 的参数

    python - 饥饿的 Python worker 的内存泄漏