推荐使用 JfrUnit:JUnit 扩展,用于断言 JDK Flight Recorder 事件
性能测试的革新者
在软件开发中,单元测试已经成为保证功能正确性的标准实践。然而,通过自动化测试来发现性能退化(如增加延迟、降低吞吐量)却是一项更具挑战的任务。传统的基于具体请求运行时的断言方法在虚拟化或容器化的 CI 环境中容易受到其他任务并发负载的影响。
JfrUnit 正是为此场景而设计,它是一个 JUnit 的扩展,允许您对应用程序发出的 JDK Flight Recorder(JFR)事件进行断言。这个创新工具提供了一种全新的视角,不仅关注如延迟和吞吐量这样的直接性能指标,而是通过 JFR 事件来间接评估可能影响这些指标的因素,例如内存分配、数据库 I/O 和执行的 SQL 语句数量。从一个基准线出发,如果这些断言在未来失败,就可能是代码变更引入了更高的垃圾收集压力、不必要的数据检索,或者常见的 SQL 问题(如 N+1 个 SELECT 语句)导致的性能退化。
JfrUnit 使您能够在标准 JUnit 测试中以可靠且环境独立的方式识别并分析这些问题,从而在它们成为生产环境中的性能问题之前及时发现。
学习更多资源
以下是一些详细介绍 JfrUnit 及其性能回归测试方法的资源:
- 走向持续性能回归测试
- 推出 JfrUnit 1.0.0.Alpha1
- 使用 JfrUnit 断言 JDK Flight Recorder 事件
- JfrUnit 连续性能回归测试
- 用 Flight Recorder、JMC Agent 和 JfrUnit 保持 SQL 的检查
使用
JfrUnit 需要运行时环境为 OpenJDK 16 或更高版本。支持 JDK 11 的工作已经在路线图上,但在此版本下,JfrUnit 不再依赖 JFR 事件流,而是从磁盘上的记录文件读取 JFR 事件。欢迎贡献这一更改的 Pull Request。
您可以从 Maven 中央仓库获取 JfrUnit;只需将以下依赖添加到您的项目 pom.xml 文件中:
...
<dependency>
<groupId>org.moditect.jfrunit</groupId>
<artifactId>jfrunit-core</artifactId>
<version>1.0.0.Alpha2</version>
<scope>test</scope>
</dependency>
...
或者,您可以从源代码构建 JfrUnit(参见下文),以便拉取最新的变更。
然后,您可以像这样实现期望特定 JFR 事件的测试:
import org.moditect.jfrunit.*;
import static org.moditect.jfrunit.JfrEventsAssert.*;
import static org.moditect.jfrunit.ExpectedEvent.*;
import org.moditect.jfrunit.events.JfrEventTypes;
@JfrEventTest
public class JfrTest {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(GarbageCollection.EVENT_NAME)
@EnableEvent(ThreadSleep.EVENT_NAME)
public void shouldHaveGcAndSleepEvents() throws Exception {
System.gc();
Thread.sleep(1000);
jfrEvents.awaitEvents();
assertThat(jfrEvents).contains(JfrEventTypes.GARBAGE_COLLECTION);
assertThat(jfrEvents).contains(
JfrEventTypes.THREAD_SLEEP.withTime(Duration.ofMillis(1000)));
}
}
对于使用 @QuarkusTest
注解的 Quarkus 应用程序,不需要(甚至不应)添加 @JfrEventTest
注解。相反,Quarkus 测试框架会自动处理管理 JFR 录制所需的回调。
@EnableEvent
注解用于启用应捕获的一个或多个 JFR 事件类型。星号字符 (*
) 可用作通配符匹配多个类型。
@Test
@EnableEvent("jdk.GC*")
@EnableEvent("jdk.G1*")
public void someTest() throws Exception { ... }
这将捕获 jdk.GCHeapSummary
、jdk.GCPhasePause
、jdk.G1GarbageCollection
等事件。所有内置 JFR 事件类型的完整列表可以在此处找到。
另外,您还可以使用 @EnableConfiguration
注解指定 JFR 配置文件的名称,例如 "default" 或 "profile":
@Test
@EnableConfiguration("default")
public void someTest() throws Exception { ... }
JFR 配置文件位于 $JAVA_HOME/bin/jfr 目录下。
使用 Spock 框架
您也可以使用 Spock 框架 编写 JfrUnit 测试:
import org.moditect.jfrunit.JfrEvents
import spock.lang.Specification
import java.time.Duration
class JfrSpec extends Specification {
JfrEvents jfrEvents = new JfrEvents()
@EnableEvent('jdk.GarbageCollection')
@EnableEvent('jdk.ThreadSleep')
def 'should Have GC And Sleep Events'() {
when:
System.gc()
sleep(1000)
then:
jfrEvents['jdk.GarbageCollection']
jfrEvents['jdk.ThreadSleep'].withTime(Duration.ofMillis(1000))
}
}
正如您所见,您可以使用自定义 DSL 来检查预期状态。
构建
该项目的构建要求 OpenJDK 16 或更高版本。使用 Apache Maven 进行构建。运行以下命令以构建项目:
mvn verify
运行以下命令将 JAR 安装到本地 Maven 仓库:
mvn install
许可证
此代码库遵循 Apache 许可证 2.0 版发布。
JfrUnit 提供了一个强大的工具,可以帮助开发者在早期阶段发现潜在的性能问题,并确保代码质量。结合其易用性和灵活性,无论是 Java 标准测试还是采用 Spock 框架的测试,都值得您的团队尝试。立即加入我们的行列,让性能回归测试变得更加简单和高效!
- 鸿蒙开发工具大赶集本仓将收集和展示鸿蒙开发工具,欢迎大家踊跃投稿。通过pr附上您的工具介绍和使用指南,并加上工具对应的链接,通过的工具将会成功上架到我们社区。07
- LangChatLangChat: Java LLMs/AI Project, Supports Multi AI Providers( Gitee AI/ 智谱清言 / 阿里通义 / 百度千帆 / DeepSeek / 抖音豆包 / 零一万物 / 讯飞星火 / OpenAI / Gemini / Ollama / Azure / Claude 等大模型), Java生态下AI大模型产品解决方案,快速构建企业级AI知识库、AI机器人应用Java03
- 每日精选项目🔥🔥 01.24日推荐项目:微软21节课程,入门生成式AI🔥🔥 每日推荐行业内最新、增长最快的项目,快速了解行业最新热门项目动态~~027
- source-vue🔥 一直想做一款追求极致用户体验的快速开发平台,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间对若依框架进行扩展写了一套快速开发系统。如此有了开源字节快速开发平台。该平台基于 Spring Boot + MyBatis + Vue & Element ,包含微信小程序 & Uniapp, Web 报表、可视化大屏、三方登录、支付、短信、邮件、OSS...Java02
- Cangjie-Examples本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。Cangjie047
- 毕方Talon工具本工具是一个端到端的工具,用于项目的生成IR并自动进行缺陷检测。Python039
- PDFMathTranslatePDF scientific paper translation with preserved formats - 基于 AI 完整保留排版的 PDF 文档全文双语翻译,支持 Google/DeepL/Ollama/OpenAI 等服务,提供 CLI/GUI/DockerPython06
- mybatis-plusmybatis 增强工具包,简化 CRUD 操作。 文档 http://baomidou.com 低代码组件库 http://aizuda.comJava03
- 国产编程语言蓝皮书《国产编程语言蓝皮书》-编委会工作区018
- advanced-javaAdvanced-Java是一个Java进阶教程,适合用于学习Java高级特性和编程技巧。特点:内容深入、实例丰富、适合进阶学习。JavaScript0109