feat(bench): JMH microbenchmarks module + manual CI job
CEO plan v1 polish — закрывает gap "JMH performance benchmarks в CI для baseline + Redis-enabled scenarios". New module: - ordinis-bench/ — JMH 1.37 microbenchmarks. Gated behind `bench` Maven profile в parent pom — НЕ строится при обычном `mvn package` (default CI остаётся быстрым). - maven-shade-plugin под `bench` profile собирает uber-jar `target/benchmarks.jar` (86 MB, ~12 sec build). - LineageBenchmark covers hot paths из dict-relationships-v2: * parseRef_simple / withSchemaButNoOnClose / withOnClose * onCloseAction_block / cascade / null * schemaTraversal_findRefs (40 props, 5 refs — realistic shape) Baseline numbers (M3 MBP, JDK 25, single thread): - onCloseAction_*: 0.6–12 ns/op - parseRef_*: 20–93 ns/op - schemaTraversal: 417 ns/op (~83 ns per ref на 40 props) Cumulative budget for findSchemaDependents на 40 dicts × 40 props × 5 refs: ~17 µs. p99 endpoint SLO = 200 ms — запас 4 порядка. README documents budget + 2x regression alarm. CI integration: - New job maven-bench (stage: test). Manual trigger only: * RUN_BENCH=true variable, OR * web pipeline source с manual click. - Default CI (push/merge) НЕ запускает bench — slow + noisy в history. - Output artifacts: bench-results.json + bench-results.txt (5 day expire). - Quick smoke config: 1 fork, 2 warmups, 3 measurements × 2s = ~5 min total. Side effect: ReferenceValidator.parseRef static methods переведены из package-private в public. Они и так часть public ParsedRef contract — visible to bench module без изменения design intent. Verify: - mvn -P bench -pl ordinis-bench -am package: BUILD SUCCESS (12s). - java -jar benchmarks.jar -f 1 -wi 1 -i 2 Lineage: all 7 benchmarks exec'ятся, valid ns/op numbers. - mvn -pl ordinis-rest-api -am test: 106/106 PASS unchanged. - glab ci lint: clean. README в ordinis-bench/README.md документирует: - baseline numbers + 2x regression budget - local run options (smoke / full / GC profile / JSON output) - when CI bench runs (manual web trigger) - difference vs k6/wrk (HTTP load tests are different layer, both needed) - how to add new benchmark
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>cloud.nstart.terravault.ordinis</groupId>
|
||||
<artifactId>ordinis-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ordinis-bench</artifactId>
|
||||
<name>Ordinis :: Benchmarks</name>
|
||||
<description>JMH microbenchmarks for hot paths. Не deployable — runs ad-hoc
|
||||
via `mvn -P bench package` + `java -jar target/benchmarks.jar`. Catches
|
||||
algorithmic complexity regressions (например parseRef становится O(n²),
|
||||
schema traversal превышает 1ms на 100 dicts).</description>
|
||||
|
||||
<properties>
|
||||
<jmh.version>1.37</jmh.version>
|
||||
<skip.bench>true</skip.bench>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Production deps мы измеряем. -->
|
||||
<dependency>
|
||||
<groupId>cloud.nstart.terravault.ordinis</groupId>
|
||||
<artifactId>ordinis-rest-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cloud.nstart.terravault.ordinis</groupId>
|
||||
<artifactId>ordinis-domain</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- JMH annotation processor pulled через jmh-generator-annprocess (provided). -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Surefire skip: бенчи в src/main, тестов нет. -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<!--
|
||||
Profile `bench`: собирает uber-jar `target/benchmarks.jar` через
|
||||
maven-shade. Активируется через `mvn -P bench package`. По default
|
||||
выключен — обычный `mvn package` не строит JMH JAR (медленно, не нужно).
|
||||
|
||||
После build:
|
||||
java -jar target/benchmarks.jar -h # all options
|
||||
java -jar target/benchmarks.jar Lineage # filter benchmarks
|
||||
java -jar target/benchmarks.jar -prof gc # GC profiler
|
||||
-->
|
||||
<profile>
|
||||
<id>bench</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<!-- unique id чтобы не конфликтовать с parent's default. -->
|
||||
<id>jmh-uber-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>benchmarks</finalName>
|
||||
<transformers>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<manifestEntries>
|
||||
<Main-Class>org.openjdk.jmh.Main</Main-Class>
|
||||
</manifestEntries>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
Reference in New Issue
Block a user