1



我正在开发一个创建大量线程并严重依赖字符串操作的应用程序。
该应用程序一次可以运行 24 小时,并且需要始终保持响应速度。
我试图将对象的创建保持在最低限度。该应用程序目前运行良好,无需任何配置。

但是我想知道使用特定的 JVM 配置是否有任何优势(或劣势)?

请多多包涵,我对 JVM/GC 配置的主题还很陌生:

  • 我想知道在使用多线程时是否绝对应该使用任何 JVM 选项?
  • 我应该配置堆吗?
  • 我还应该配置 GC 吗?
  • 我应该尽量减少垃圾收集吗?

    我开始阅读:http
    ://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html 关于该主题的任何提示将不胜感激。

    提前致谢,

  • 4

    5 回答 5

    4

    一般来说,关于调整 JVM 的最佳初始建议是不要。除非您在使用默认设置时遇到与 JVM 相关的特定问题,否则不要理会它们。

    如果您确实需要摆弄设置,我建议您设置一个有代表性的测试用例并使用高级分析器,例如JProfiler

    此外,您应该真正阅读有关 HotSpot VM 的技术文档,特别是内存管理白皮书,您可以在此处找到所有这些文档。

    于 2012-09-25T10:49:56.407 回答
    3

    如果它工作正常,那么你不应该做任何事情。

    如果您的应用程序受 CPU 限制,则不应创建大量线程。原因是大量时间浪费在上下文切换上。字符串操作,如果它在内存中,那么应该只有那些需要的线程

    NCPU = UCPU* (1+W/C)
    
    Where  NCPU--> Number of CPU
    UCPU--> Target CPU Utilization
    W-->Wait time
    C--> Compute time
    

    因此,对于 CPU 绑定操作,它应该是最大(CPU 数量 +1)线程。

    Java Concurrency in Practice 中也为并发应用程序定义了很多测试用例。你可能想检查那些。

    于 2012-09-25T10:50:26.360 回答
    2

    我想知道在使用多线程时是否绝对应该使用任何 JVM 选项?

    默认情况下,所有最佳选项都将打开。如果您查看HotSpot VM 选项,您会看到很多选项,-XX:+这意味着它们默认处于打开状态。

    我应该配置堆吗?

    可能。但如果可以的话,我会保留默认设置。

    我还应该配置 GC 吗?

    可能。但如果可以的话,我会保留默认设置。

    我应该尽量减少垃圾收集吗?

    减少产生的垃圾量需要付出努力。它在一定程度上提供了一些好处。你必须决定什么是最好的利用你的时间,以及花多少时间来减少产生的垃圾量。

    我总是从内存分析器开始,找出你在哪里创建了最多的垃圾。从列表的顶部开始,而不是尝试调整所有内容,因为这样可以确保您以最少的努力获得最大的收益。


    顺便说一句:我提倡低垃圾和堆外程序,这样做是有意义的。我已经编写了可以运行一天的交易系统,甚至可以在没有次要 GC 的情况下运行,以及可以在堆外内存中加载/使用 500+ GB 数据的程序。但是,您必须能够证明或量化它将对最终用户或您的业务产生多大的影响,以确定它是否真的值得。

    于 2012-09-25T11:02:10.783 回答
    2

    我想知道在使用多线程时是否绝对应该使用任何 JVM 选项?

    不。

    我应该配置堆吗?

    不,除了将堆大小设置为合理的值(使用 -Xmx 和 -Xms)

    我还应该配置 GC 吗?

    不,除非您特别需要“低暂停”。如果您当前正在满足“响应性”目标,则默认吞吐量编译器是最佳选择。如果您没有达到这些目标,那么您应该考虑 CMS 或 G1 ......但要注意它们会减少暂停,但也会降低吞吐量。

    我应该尽量减少垃圾收集吗?

    不,这不是一个明智的目标。您的目标是最大化吞吐量,而最小化 GC 不一定能实现这一目标。在很多情况下,产生垃圾比让应用程序做额外的工作来避免产生垃圾更有效。(正如 Peter Lawrey 指出的那样,您还需要额外的开发人员来编写和维护模式复杂代码。)


    我建议您使用分析器来查看您的应用程序相对于执行其他生产性工作是否花费了大量时间(CPU 时间或经过的时间)。如果没有,或者应用程序已经运行得足够快,那么不要摆弄 JVM 选项。

    如果您担心您的应用程序将来无法应对增加的负载,那么调整 GC 不会扩展。更好的选择是研究扩展您的硬件和/或弄清楚如何在多台机器上完成工作。此外,调整 GC 以提高当前负载的性能实际上可能会导致负载增加时性能更差。(考虑当 CMS 无法跟上并被迫进行完整的全球范围收集以恢复时出现的问题。)


    最后,拥有大量线程通常是个坏主意。最好使用少量工作线程(大致等于处理器/内核的数量)并通过并发队列等为它们提供工作。

    于 2012-09-25T11:00:51.280 回答
    1

    过去,我遇到过类似的服务器应用程序:大量的字符串操作、字符串创建,并且需要始终非常响应。该应用程序在默认配置下运行良好,直到遇到高压力情况。您需要启用 -XX:+UseConcMarkSweepGC 以获得低暂停,并微调其他参数以确保应用程序以您想要的方式运行。这是简短的清单:

    -XX:+CMSParallelRemarkEnabled
    -XX:+CMSScavengeBeforeRemark
    -XX:+UseCMSInitiatingOccupancyOnly
    -XX:CMSInitiatingOccupancyFraction=nn
    -XX:CMSWaitDuration=300000
    -XX:GCTimeRatio=nn
    -XX:+DisableExplicitGC

    于 2012-10-17T16:21:24.310 回答