Skip to content

JEP 143: Improve Contended Locking | 改进争用锁定

摘要

改进争用的 Java 对象监视器的性能。

目标

通过以下基准测试和测试,改进争用的 Java 对象监视器的整体性能:

  • CallTimerGrid (though more of a stress test than a benchmark)
  • Dacapo-bach (was dacapo2009)
  • _ avrora
  • _ batik
  • _ fop
  • _ h2
  • _ luindex
  • _ lusearch
  • _ pmd
  • _ sunflow
  • _ tomcat
  • _ tradebeans
  • _ tradesoap
  • _ xalan
  • DerbyContentionModelCounted
  • HighContentionSimulator
  • LockLoops-JSR166-Doug-Sept2009 (was LockLoops)
  • PointBase
  • SPECjbb2013-critical (was specjbb2005)
  • SPECjbb2013-max
  • specjvm2008
  • volano29 (was volano2509)

非目标

该项目的目标不是解决内部 VM 监视器或互斥锁的性能改进;Java 监视器和内部 VM 监视器/互斥锁由不同的代码实现。尽管该项目中的一些概念可能适用于内部 VM 监视器/互斥锁,但代码并不直接适用。

该项目的目标不是改进每个基准测试或测试中争用的 Java 监视器的性能;在某些情况下,特定基准测试或测试可能会出现性能下降。为了在另一个基准测试或测试中获得性能改进,可能会认为这种性能下降是可以接受的。

成功指标

如果根据上述基准测试测量到可证明的性能提升,并且没有相应的显著性能回退,那么该项目将被视为成功。

非争用锁的性能不得出现重大回退。

动机

改进争用锁将显著有益于实际应用程序,除了 Volano 和 DaCapo 等行业基准测试。

描述

该项目将探索与争用的 Java 监视器相关的以下领域的性能改进:

  • 字段重新排序和缓存行对齐
  • 加速 PlatformEvent::unpark()
  • 快速的 Java 监视器进入操作
  • 快速的 Java 监视器退出操作
  • 快速的 Java 监视器 notify/notifyAll 操作

原始工作的范围还包括“更快的哈希码”;由于 Java 对象哈希码支持与争用的 Java 监视器没有直接关系,因此该工作不包含在此项目中。

该项目还将针对在工作过程中发现的各种错误生成修复程序;这些错误修复将独立于性能改进工作进行管理,以便更早地集成修复程序。

该项目由以下“总体”错误覆盖,以简化管理:

JDK-6607129 减少争用锁自旋循环中的 L2$ 一致性失效流量,特别是对于 ctn-family 上的 derby

然而,随着子任务或错误修复的完成,工作将使用单独的错误 ID 进行集成。这样可以通过一个错误 ID(JDK-6607129)引用整个项目,同时允许增量改进更快地提供,而不必等待整个项目完成。

测试

功能测试

似乎没有专门针对 Java 监视器的功能测试集,也没有必要。Java 监视器被如此广泛地用于甚至最简单的 Java 程序,以至于几乎任何 Java 监视器的功能故障都应该是显而易见的。

压力测试

需要一组针对 Java 监视器的良好的压力测试。这些可以是针对特定 Java 监视器场景的有针对性的压力测试,或者是已知对 Java 监视器使用较多的测试,以特定的压力诱导选项运行。

注意:使用 “-XX:-UseBiasedLocking -XX:+UseHeavyMonitors” 来绕过偏向锁定和基于栈的锁定;强制使用 ObjectMonitor 对象。

字段重新排序和缓存行对齐子任务压力测试

压力测试应该专注于生成大量活动的 ObjectMonitor 对象。压力测试的目标是 ObjectMonitor 的峰值使用情况、ObjectMonitor 块分配算法和 ObjectMonitor 空闲列表管理代码。以下是目标:

  1. 对于小型到中型配置,具有相同或更好的 ObjectMonitor 峰值使用情况,
  2. 没有内存泄漏,和
  3. 没有数据结构管理故障。

加速 PlatformEvent::unpark() 子任务压力测试

压力测试应该专注于高并发等待者和/或并发进入 - 退出线程的大量数量。进入 - 等待 - 退出和进入 - 退出线程的混合应该是可配置的。压力测试的目标是后继机制。

目标:没有因为丢失的 unpark 操作而导致挂起。

快速的 Java 监视器进入操作子任务压力测试

压力测试应该专注于具有可扩展数量的并行线程的进入 - 退出操作的正确性。压力测试的目标是 Java 监视器的所有权。

目标:没有所有权冲突,即多个线程认为自己拥有 Java 监视器。

快速的 Java 监视器退出操作子任务压力测试

应该由 “加速 PlatformEvent::unpark()” 和 “快速的 Java 监视器进入操作” 子任务的压力测试覆盖。

快速的 Java 监视器 Notify/NotifyAll 操作子任务压力测试

压力测试应该专注于具有可扩展数量的并行线程的进入 - 等待 - 退出操作的正确性。压力测试的目标是 Java 监视器在 wait() 完成并重新进入 Java 监视器后的所有权。

目标:没有所有权冲突,即多个线程认为自己拥有 Java 监视器。