资讯动态

reactor-core 基准测试实战:JMH 任务使用指南(benchmarks 模块)

发布时间:2026/10/13 8:39:56 来源:尧图企业网站定制
后端异步编程【免费下载链接】reactor-coreNon-Blocking Reactive Foundation for the JVM项目地址https://gitcode.com/gh_mirrors/re/reactor-core点击查看免费下载导读本文以 benchmarks/README.md 为核心系统讲解 reactor-core 仓库中benchmarks模块的 JMHJava Microbenchmark Harness基准测试任务用法包括如何精确指定被测类、如何附加 profiler 分析 GC 与线程行为、如何切换报告格式、如何注入 JVM 参数以及如何借助jmhBaseline与最新发布版本进行 A/B 对比。读完本文你将能够在本地复现 reactor-core 的性能回归验证流程并理解这些 Gradle 任务底层是如何拼装 JMH 命令行参数的。一、benchmarks 模块与 JMH 基础设施概览benchmarks是 reactor-core 仓库中的一个独立 Gradle 子项目在 settings.gradle 中通过include benchmarks, ...注册专门用于存放针对reactor-core及reactor-core-micrometer的 JMH 基准测试。它的 Gradle 配置位于 benchmarks/build.gradle其核心依赖与任务关系如下依赖org.openjdk.jmh:jmh-core版本 1.37见 gradle/libs.versions.toml并通过annotationProcessor libs.jmh.generatorAnnprocess使用 JMH 注解处理器自动生成*_jmh运行类使用compileOnly引入reactor-perfBaseline-core等基线依赖目的是防止在编写 benchmark 时意外使用新版本 API见 benchmarks/build.gradle 的注释 Use the baseline to avoid using new APIs in the benchmarks定义了三个关键任务jmh、jmhBaseline与jmhProfilers其中jmh和jmhBaseline都继承自自定义任务类 JmhExecTask位于 buildSrc 中jmhProfilers则直接以org.openjdk.jmh.Main -lprof方式列出所有可用 profiler见 benchmarks/build.gradle。由于任务定义在benchmarks子项目内从仓库根目录运行需写为./gradlew :benchmarks:jmh ...而原文档中的../gradlew jmh ...则是约定在benchmarks/目录下执行的形式二者等价。二、精确控制被测 Benchmarkinclude、fullInclude 与 excludeJMH 默认会运行所有Benchmark方法而 reactor-core 的基准测试往往数量较多、耗时较长。因此第一步通常是缩小范围。2.1 按子串匹配--include原文档给出的第一种方式是按子串过滤Gradle 会自动在传入值前后各加一个.*通配符../gradlew jmh --include(BenchmarkPrimary|OtherBench)上述命令实际匹配的是类名JMH 内部按 类名.方法名 形式的 benchmark 全名做正则匹配等效于正则.*(BenchmarkPrimary|OtherBench).*可以一次匹配多个含不同关键字的 benchmark。2.2 自己写完整正则--fullInclude如果你需要更精细的控制可以直接传入完整的 JMH 风格正则../gradlew jmh --fullInclude.*MyBenchmark.*2.3 反向排除--exclude虽然原文档未列出但从 JmhExecTask.java 的源码可以看到任务还提供了exclude选项它会被映射为 JMH 的-e参数../gradlew jmh --exclude.*SomeSlowBench.*三个选项在任务实现中的优先级关系见 JmhExecTask.java是若设置了include则使用.*include.*否则若设置了fullInclude则直接使用该正则exclude独立生效两者可组合使用。三、附加 Profiler定位 GC、线程与 JIT 瓶颈JMH 本身只负责测量吞吐量或耗时要回答“时间花在哪了”需要挂载 profiler。../gradlew jmh --profilersgc,stack--profilers接受逗号分隔的多个 profiler 名称底层实现会对每个名称依次追加一个-prof name参数见 JmhExecTask.java。原文档重点推荐了四个常用 profilerProfiler用途compJitCompilations查看 JIT 编译情况用于微调迭代次数stack统计哪些方法耗时最多热点方法分布gc打印垃圾回收统计信息分配率、GC 次数与耗时hs_thr线程使用情况HotSpot 线程状态统计要查看完整 profiler 清单运行专门的列出任务../gradlew jmhProfilers该任务即执行org.openjdk.jmh.Main -lprof见 benchmarks/build.gradle会打印诸如gc、stack、comp、hs_thr、async、perfasm、javaProfiler等全部可用选项供你按需选用。四、报告格式从 JSON 切换到 CSV/TEXTJMH 默认输出 JSON 格式报告DEFAULT_FORMAT json见 JmhExecTask.java原文档允许切换为以下五种之一./gradlew jmh --formatcsv--format的合法取值为CSV、JSON、NONE、SCSV、TEXTCSV/SCSV便于导入 Excel 或 pandas 做后处理JSON默认结构完整适合程序化解析TEXT人类可读的控制台式文本NONE不生成机器可读报告。在任务实现中该参数同时决定结果文件路径build/reports/任务名/result.format见 JmhExecTask.java。也就是说用--formatcsv跑jmh任务后报告位于benchmarks/build/reports/jmh/result.csv供持续集成或人工对比读取。五、注入 JVM 参数某些 benchmark 需要特定的系统属性或 JVM 开关可通过--jvmArgs传入注意参数按空格拆分多个参数用空格分隔见 JmhExecTask.java../gradlew jmh --jvmArgs-Dtest.clusterlocal仓库中的 benchmark 也大量依赖此类 JVM 开关。例如 AssemblyTraceBenchmark 通过Fork(jvmArgsAppend ...)在 fork 的 JVM 上分别设置-Dreactor.trace.operatorStacktracetrue/false来对比启用/关闭操作符堆栈跟踪时的开销并追加-XX:-OmitStackTraceInFastThrow防止 JIT 优化掉异常堆栈。这类测试场景配合--jvmArgs可以进一步叠加自定义属性。需要说明的是任务实现还会无条件追加两个堆内存参数见 JmhExecTask.java-Xmx3072m -Xms3072m即每个 fork 出的 JVM 固定使用 3GB 堆避免因默认堆过小导致 GC 干扰测量结果。六、验证模式只检查 benchmark 能否运行完整跑一轮基准测试往往需要数十分钟甚至更久。改动 benchmark 代码后想快速确认“能编译、能跑通、不出错”用验证模式../gradlew jmh --verifytrue从源码看verify模式会把 fork、预热迭代、测量迭代全部压到最小值见 JmhExecTask.java-f 1只 fork 一次-wi 1仅 1 轮预热迭代-i 1仅 1 轮测量迭代。同时任务始终追加-foe truefail-on-error任何 benchmark 抛错立即失败与-v NORMAL输出级别因此验证模式下任何异常都会直接导致构建失败便于在 CI 或本地快速回归。七、与最新发布版基线对比jmhBaseline性能优化的关键问题是“我的改动相比上一个版本是变快还是变慢”为此仓库提供了配套任务jmhBaseline它用最新发布版本而非当前工作区代码运行同一批 benchmark../gradlew jmh jmhBaseline --includeMyBenchmark在 benchmarks/build.gradle 中jmh与jmhBaseline分别使用两组独立配置jmh的 classpath 为sourceSets.main.runtimeClasspath configurations.currentcurrent指向当前模块project(:reactor-core)与project(:reactor-core-micrometer)见 benchmarks/build.gradlejmhBaseline使用configurations.baseline即通过libs.reactor.perfBaseline.core解析到的发布版坐标当前版本配置为baselinePerfCore 3.8.7见 gradle/libs.versions.toml并设置changing true、缓存时间为 0 秒确保总是拉取最新基线。两个任务产生的报告分别落在build/reports/jmh/result.json与build/reports/jmhBaseline/result.json对比两份 JSON 即可量化本次改动的性能影响。这也是 reactor-core 维护者在发布前验证性能回归的标准流程。八、仓库内典型 Benchmark 速览理解了任务用法之后快速浏览仓库中已有的 benchmark 可以帮助你写出风格一致、结果可信的新用例FluxPublishBenchmark使用Param({0, 10, 1000, 100000})在四种数据规模下测量Flux.range().publish().autoConnect(availableProcessors())的多线程发布吞吐Threads(Threads.MAX)让线程数与 CPU 核数对齐配合Fork(value 1)固定 fork 次数可对比不同rangeSize的扩展性。MonoAllBenchmark用Flux.range(0, rangeSize).all(i - i Integer.MAX_VALUE).block()测量all()谓词短路运算在不同数据规模下的平均耗时纳秒级输出。BoundedElasticBusyStructureBenchmark同一被测场景下对比当前Schedulers.newBoundedElastic(...)与仓库保留的旧实现OldBoundedElasticScheduler其任务队列基于PriorityBlockingQueue见 OldBoundedElasticScheduler.java用于验证调度器数据结构改造带来的收益。FluxBufferTimeoutBenchmark通过自定义JmhSubscriber模拟两种背压请求模式一次请求Long.MAX_VALUE的unlimited与逐条request(1)的oneByOne测量bufferTimeout在不同缓冲大小下的行为差异。CheckpointBenchmark对比checkpoint(desc, true)完整堆栈跟踪与轻量checkpoint(identifier)两种调试模式对吞吐量Throughput与采样耗时SampleTime的影响直接指导生产环境调试开关的选型。AssemblyTraceBenchmark以递归方式构造不同深度Param({10, 40, 80})的 operator 链在开启/关闭reactor.trace.operatorStacktrace两种模式下测量装配期堆栈跟踪的开销。这些用例普遍遵循同一套 JMH 规范类级标注BenchmarkMode、Warmup、Measurement、Fork、OutputTimeUnit与State(Scope.Benchmark)方法级使用Blackhole消费结果防止死代码消除。新写 benchmark 时照搬这套模板即可。九、执行与报告速查需求命令在benchmarks/下执行说明按子串运行../gradlew jmh --includeBenchmark自动加.*通配按正则运行../gradlew jmh --fullInclude.*MyBenchmark.*完整 JMH 正则附加 profiler../gradlew jmh --profilersgc,stack逗号分隔多个列出全部 profiler../gradlew jmhProfilers等价jmh -lprof切换报告格式./gradlew jmh --formatcsvCSV/JSON/NONE/SCSV/TEXT注入 JVM 参数../gradlew jmh --jvmArgs-Dkeyvalue空格分隔多个参数快速验证../gradlew jmh --verifytrue1 fork、1 预热、1 测量对比基线../gradlew jmh jmhBaseline --includeMyBenchmark基线为最新发布版几点补充提醒结果文件位置jmh与jmhBaseline的报告分别写入build/reports/jmh/result.format与build/reports/jmhBaseline/result.format见 JmhExecTask.java对比时注意区分目录堆内存固定 3GB任务会自动追加-Xmx3072m -Xms3072m若需调整只能覆盖 fork 参数而非直接覆盖该内存设置fail-on-error 恒定开启-foe true保证任何 benchmark 异常都会使构建失败适合接入 CI验证模式结果无参考意义--verifytrue只用于“能否运行”的检查其数值因迭代过少不具备统计价值正式数据应以默认完整模式产出为准。通过组合上述选项你可以在不改动任何仓库代码的前提下完成从“精确跑某个 benchmark”到“当前分支 vs 最新发布版”的完整性能验证闭环这正是 reactor-core 对每个 PR 进行性能守护的实践基础。赞分享后端异步编程【免费下载链接】reactor-coreNon-Blocking Reactive Foundation for the JVM项目地址https://gitcode.com/gh_mirrors/re/reactor-core点击查看免费下载相关推荐Reactor Core 性能基准测试JMH 实战指南Reactor Core 性能基准测试JMH 实战指南 Reactor Core 作为 JVM 平台上领先的非阻塞响应式编程框架其性能表现直接影响着高并发应后端异步编程Apache Kafka JMH 基准测试模块jmh-benchmarks实战指南运行、调参与编写微基准Apache Kafka JMH 基准测试模块jmh benchmarks实战指南运行、调参与编写微基准 本文以 Apache Kafka 仓库中的 jm消息队列流处理数据集成存储Reactor Core性能终极指南JMH基准测试完整实战Reactor Core性能终极指南JMH基准测试完整实战 在当今高并发应用开发中性能优化已成为不可或缺的关键环节。Reactor Core作为JVM平台上后端异步编程上一篇vue-flow 图形截图实战基于 html-to-image 实现流程图导出与下载下一篇用Python雪球接口pysnowball搭建个人投资数据监控一份含踩坑记录的新手完整实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑