Skip to content

Commit e7f5ffc

Browse files
committed
docs: close parity-safe perf thread (one win); refresh status
Perf thread stopped after the single high-value observer-registry win (5baabea, LiborMarketModelTest 537s->5.94s, ~90x). The next candidate Date.clone was profiled and deliberately declined: shallow Object.clone with no algorithmic pathology; the realistic lazy-observable change is high-risk on a load-bearing mutable+Observable+shallow-cloned+concurrent class for a diffuse payoff; remaining suite headroom is off-limits MC/FD numerics. Document the closure rationale in perf-observer-optimization.md and refresh the README current-tip pointer. Signed-off-by: Jose Moya <jlmoya@gmail.com>
1 parent f218e8f commit e7f5ffc

2 files changed

Lines changed: 10 additions & 3 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ This is not a maintenance branch. It is a **systematic, full-fidelity port** wit
9494
| Console-noise cleanup | (5 commits: `de95bb17`, `3282157f`, `1a97b04f`, `642fdeca`, `14086930`) | Eliminated all stderr-flood + compile-warning noise during test runs. `LibraryException` constructors no longer call `QL.error(this)` (was unconditionally dumping ERROR + stack trace for every constructed instance — including ones caught for fast-path/slow-path control flow like `LfmCovarianceProxy.integratedCovariance` → numerical fallback, `IterativeBootstrap` retries, observer-failure chains). `DefaultObservable.notifyObservers` observer-failure log now routes via SLF4J WARN (configurable) instead of `QL.error` → stderr. 78 `@SuppressWarnings({"deprecation","unchecked"})` annotations on legitimate-internal-use sites (Array/Matrix subclasses accessing `Cells.$` raw backing, generic-erasure casts after `Class.newInstance()`, raw-type bridge code). | 3610/0/0/21 | 2026-05-23 |
9595
| **JQuantLib FINAL** | **`jquantlib-final`** (`14086930`) | **Final state pointer.** Suite 3610/0/0/21 BUILD SUCCESS (~19-20 min wall). `mvn clean verify deploy` from repo root succeeds: 0 compile warnings, 0 stderr ERROR-flood lines, jquantlib-1.0.0.jar (9.9 MB) deploys cleanly to local Nexus. **All worktrees + transient branches cleaned up local+remote** (only `main` + pre-existing `temp-p1b-test` remain). | **3610/0/0/21** | **2026-05-23** |
9696

97-
**Current tip on `main`:** `5baabea2` — parity-safe observer-registry performance optimization, on top of the full-surface functional-coverage milestone `0646ee75` (tag `jquantlib-cpp-surface-functional-coverage`). **Suite:** 3678 tests / 0 failures / 0 errors, BUILD SUCCESS (**~12 min** wall on JDK 25 LTS — down from ~19-20 min after the observer optimization; see [`docs/migration/perf-observer-optimization.md`](docs/migration/perf-observer-optimization.md)). **Scanner WIP-stub count:** `0` genuinely-pending (3 documented carve-outs). **Compile warnings:** `0` across all 5 reactor modules. **Stderr ERROR flood:** `0` (LibraryException + DefaultObservable both fixed). **JDK:** 25 LTS. **`mvn clean verify deploy`:** end-to-end success; deploys jquantlib-1.0.0.jar to local Nexus (port 7910). **Repo hygiene:** only `main` + pre-existing `temp-p1b-test` branches (all P1/P2/P3/P3F worktrees + transient branches removed local+remote).
97+
**Current tip on `main`:** `f218e8f9`. The parity-safe performance thread is **closed** after one clean win — the observer-registry optimization `5baabea2` (on top of the full-surface functional-coverage milestone `0646ee75`, tag `jquantlib-cpp-surface-functional-coverage`); the next candidate (`Date.clone`) was profiled and deliberately declined (no algorithmic pathology; remaining headroom is in off-limits MC/FD numerics — see [`docs/migration/perf-observer-optimization.md`](docs/migration/perf-observer-optimization.md)). **Suite:** 3678 tests / 0 failures / 0 errors, BUILD SUCCESS (**~12 min** wall on JDK 25 LTS — down from ~19-20 min after the observer optimization). **Scanner WIP-stub count:** `0` genuinely-pending (3 documented carve-outs). **Compile warnings:** `0` across all 5 reactor modules. **Stderr ERROR flood:** `0` (LibraryException + DefaultObservable both fixed). **JDK:** 25 LTS. **`mvn clean verify deploy`:** end-to-end success; deploys jquantlib-1.0.0.jar to local Nexus (port 7910). **Repo hygiene:** only `main` + pre-existing `temp-p1b-test` branches (all P1/P2/P3/P3F worktrees + transient branches removed local+remote).
9898

9999
**3 documented carve-outs** (explicit; NOT silent deferrals):
100100
1. **PseudoSqrt Hypersphere/LowerDiagonal**`hypersphereOptimize` is ported (from C++ `pseudosqrt.cpp:141-263`); Java `ConjugateGradient` doesn't converge on the ill-conditioned target. UOE replaced with descriptive deferred-port message routing users to `Higham` / `Principal` alternatives. Closure requires Java optimizer hardening pass.

docs/migration/perf-observer-optimization.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ The 90× was deliberately re-measured under the same cold-start isolation as the
6060
2. **Parity-safe only.** Same algorithm, no FP reorder → bit-identical → probes green by construction. No tolerance touched, nothing re-baselined.
6161
3. **Benchmark-gate keep-vs-revert** on a clean-baseline-vs-after comparison under *identical* conditions. Keep only if bit-green **and** faster; else revert.
6262

63-
## Remaining candidates (not pursued; pursue iff asked)
63+
## Why the parity-safe perf thread was closed here (2026-06-02)
6464

65-
The same JFR profile flagged further parity-safe targets — notably `org.jquantlib.time.Date.clone()` (the #1 CPU leaf). These remain open. The methodology above is ready to repeat. Nothing is pending unless the owner asks.
65+
After this win, the next-flagged leaf — `org.jquantlib.time.Date.clone()` — was profiled and **deliberately declined**:
66+
67+
- In the original JFR it was a *distant second* to the observer churn (46 CPU / 142 alloc samples vs ~40k for the CoW `Object[]`), notable only as "the top thing that isn't the observer bug." Once the O(n²) was removed, that framing is gone.
68+
- `Date.clone()` is a shallow `Object.clone()` of a one-`long`-field object — **called often but cheap per call**, with no algorithmic pathology to fix. The best achievable is a diffuse few-percent, not a step-change.
69+
- The only genuinely structural Date change — lazy-init the per-`Date` `WeakReferenceObservable` (every transient calculation-Date currently allocates an observable + list it never uses) — touches a **load-bearing, mutable, `Observable`, shallow-cloned, concurrency-sensitive** class (the eval-date `Settings.DateProxy` is genuinely observed under multi-threading). High blast radius for an uncertain, diffuse payoff — the opposite of this win's risk/reward.
70+
- The current dominant suite cost is heavy **Monte-Carlo / finite-difference option pricing** (e.g. the `AsianOptionTest` MC method, `QuantoOptionTest`, `VppTest`) — i.e. the *algorithm and sample counts*, which are **off-limits** under the parity-safe rule (changing them alters results and breaks C++ cross-validation).
71+
72+
**Conclusion:** the one clear, high-value, low-risk parity-safe win was harvested; the remaining headroom lives in numerics we must not touch. **Thread closed.** The profile-first / clean-baseline-gate methodology above is recorded and ready to repeat if a new pathological hotspot ever surfaces.

0 commit comments

Comments
 (0)