我有一个容器,它仅限于 1 个 CPU,在这种情况下,java 11+ 的默认情况(可能也更旧(,在这种情况下,它对用户 SerialGC 来说。 我应该强制使用线程GC(如G1GC(还是将其保留在SerialGC?
哪一个在单个 CPU 上性能更好? 我一直认为在这种情况下SerialGC更好,但我经常看到在某些情况下强制使用G1GC。
编辑:我要求一般情况,因为我们有很多不同的应用程序使用相同的配置运行,很难测试每种情况。
根据文档。
串行收集器使用单个线程执行所有垃圾 收集工作,这使得它相对有效,因为有 线程之间没有通信开销。
它最适合单处理器机器,因为它不能 多处理器硬件的优势,尽管它可能在 多处理器适用于具有小型数据集的应用程序(最多 大约 100 MB(。
我假设文档中的处理器=核心(以及您的问题(。虽然文档说串行收集器对于多核计算机来说不是一个好的选择,但它并没有说其他收集器对单核计算机不利。
不过,其他收集器确实倾向于使用多个线程,并且您无法获得单核环境中的收集器的全部好处。
那么为什么你看到G1GC被使用呢?也许除了它是最新的之外没有其他原因。但是,如果有原因,很可能是 G1 提供的较短的 GC 暂停:
如果响应时间比整体吞吐量和垃圾更重要 收集暂停必须短于大约一秒, 然后选择一个大部分并发的收集器,其中 -XX:+UseG1GC 或 -XX:+UseConcMarkSweepGC.
最好的情况是,在这些情况下,他们使用不同的收集器测量性能,并选择提供最佳结果的收集器。
还要考虑评论中提到的字符串重复数据删除霍尔格。这是一个特定的内存优化,可能是使用 G1GC 背后的原因。毕竟,如果您只有一个内核,您可能也没有很多内存可供使用。
你想优化什么?您是否希望始终能够非常快速地回答或具有更好的整体性能?在第一种情况下,您应该以较短的 GC 暂停为目标,在第二种情况下,应针对所有 GC 暂停的较低总和。
您还需要考虑其他因素(即重新启动应用程序的频率(,因此IMO的最佳方法是数据驱动的方法。使用 GC 简易版或 GC 查看器分析每个应用程序的性能并采取相应措施。
请记住,GC 调优并不总是必需的,因此如果您不知道要实现的目标,则可能会过早优化。
通常:
- 将串行 GC用于暂停时间要求不低且在资源较少的环境中运行的应用程序
- 如果您有更多资源或需要快速回答,请使用G1 垃圾收集器(请记住在更改前后测量性能(
作为更一般的评论,不要假设因为你只有一个内核/CPU,所以使任务多线程化不会有任何好处。 根据所涉及的任务(在本例中为 GC(,可能会出现一个线程被阻塞(例如等待 IO 完成(的情况,这允许执行任务另一部分的其他线程使用处理器并完成有用的工作。 尽管一次只能运行一个线程,但整体性能得到了提高。
此线程中未提及的一件重要事情是,G1GC 可以将内存(取消提交(返回给操作系统,因此如果其他应用程序在服务器上运行,他们可以使用它。
从单个 vCPU 服务器切换到 2 个 vCPU 服务器时,我注意到了这一点,因为 java 默认对单个 CPU 使用 SerialGC,对多 CPU 使用 G1GC(至少对于 JDK 11 是这样(