JEP 143:改进竞争锁定
概括
提高竞争 Java 对象监视器的性能。
目标
通过以下基准测试和测试来衡量,提高竞争 Java 对象监视器的整体性能:
- CallTimerGrid(尽管更多的是压力测试而不是基准测试)
- 达卡波巴赫 (dacapo2009)
- _阿夫罗拉
- _ 蜡染
- _ 福普
- _ h2
- _ luindex
- _ 路搜索
- _ 下午
- _ 向日葵
- _ 雄猫
- _ 贸易豆
- _ 贸易肥皂
- _ 夏兰
- 德比竞争模型已统计
- 高竞争模拟器
- LockLoops-JSR166-Doug-2009 年 9 月(原为 LockLoops)
- 点基
- SPECjbb2013-关键(原为specjbb2005)
- 规格jbb2013-max
- 规格jvm2008
- volano29(原为 volano2509)
非目标
该项目的目标不是解决内部虚拟机监视器或互斥体的任何性能改进问题; Java监视器和内部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 空闲列表管理代码。以下是目标:
- 要为中小型配置提供相同或更好的峰值 ObjectMonitor 使用率,
- 没有内存泄漏,并且
- 没有数据结构管理失败。
加速PlatformEvent::unpark()
子任务压力测试
压力测试应关注大量并发等待者和/或并发进入-退出线程。输入-等待-退出和输入-退出线程的组合应该是可配置的。压力测试的目标是后继机制。
目标:不会因取消驻留操作丢失而导致挂起。
快速Java监控进入操作子任务压力测试
压力测试应重点关注具有可扩展数量的并行线程的进入-退出操作的正确性。压力测试的目标是Java监视器所有权。
目标:当多个线程认为自己拥有 Java 监视器时,不会发生所有权冲突。
快速Java监控退出操作子任务压力测试
压力测试应涵盖“加速PlatformEvent::unpark()
”和“快速 Java 监控输入操作”子任务。
快速Java监控Notify/NotifyAll操作子任务压力测试
压力测试应重点关注具有可扩展数量的并行线程的输入-等待-退出操作的正确性。压力测试的目标是wait()
完成并重新进入 Java 监视器后的 Java 监视器所有权。
目标:当多个线程认为自己拥有 Java 监视器时,不会发生所有权冲突。