Skip to content

ci: publish candidate image for #24810 performance validation (do not review) - #24859

Closed
netroms wants to merge 4 commits into
masterfrom
ci/l2-cache-24810-candidate-image
Closed

ci: publish candidate image for #24810 performance validation (do not review)#24859
netroms wants to merge 4 commits into
masterfrom
ci/l2-cache-24810-candidate-image

Conversation

@netroms

@netroms netroms commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Not for review. This draft PR exists only to make CI publish dhis2/core-pr:<this PR number>, the candidate image for the performance comparison requested on #24810 (fork PRs cannot publish images because they have no access to the Docker Hub secrets).

Content is identical to #24810 (same commits, head 809d8e332d). All review happens there. This PR will be closed once the performance comparison runs are done.

AI Assisted

Every cached region in DHIS2 uses READ_WRITE, whose access strategy holds
one ReentrantReadWriteLock PER REGION (not per key): every get takes the
region read lock and every putFromLoad takes the region WRITE lock, even
when it writes nothing (entities are unversioned, so an existing entry is
never overwritten from a load). Under concurrent load on option-heavy
metadata this serialises a whole region behind single-key work: measured
14-15% of ALL JVM wall samples parked in AbstractReadWriteAccess.

Switches the static reference bucket (Option*, PeriodType, DataElement,
Category*, OptionSet.options, Legend*, Indicator*, OrgUnit hierarchy;
30 files, 71 declarations) to NONSTRICT_READ_WRITE, which has no region
lock. Trade-off: a brief staleness window after a write, accepted for
reference metadata (sign-off: Morten, 2026-08-07). Period/RelativePeriods
stay READ_WRITE.

Measured on a tracker-import ramp: parked-in-region-lock 14.15% -> 0.05%,
p99 at 100 concurrent users 58.4s -> 20.7s as an isolated change.

AI Assisted
Regions created on demand through the jsr107 template are store-by-value:
every get and put copies the entry through SerializingCopier, inside the
READ_WRITE region lock critical section. Predefining a region in
ehcache.xml keeps ehcache-native store-by-reference semantics (Hibernate
caches disassembled, immutable entries, so by-reference is safe; 2.41 ran
Ehcache 2 by-reference for years).

Region list and heap bounds come from measured traffic: the hot metadata
regions from a read/write metadata ramp, plus the tracker-import hot set
(the Option region alone takes ~98M gets per 25 minute import run).
Measured effect in the full combination: SerializingCopier wall samples
236,287 -> 1,057.

AI Assisted
dataElementCountDoesNotScaleQueryCount compares a metadata export with 3
data elements against one with 8 and asserted the two select counts were
equal. With the cache changes in this branch the second export legitimately
issues FEWER selects (21 vs 22): what the first export loaded is still
cached during the second. Assert the invariant the test name and comment
state - the count must not grow - so the test keeps catching a
reintroduced N+1 without failing on a cache improvement.

AI Assisted
The previous six hour TTL was inherited from the old Ehcache 2 configuration.
TTL is the upper bound on how long a stale cache entry can survive, whether it
went stale through an out-of-band database change (no load ever refreshes an
existing entry for unversioned entities) or through a late cache-put
re-inserting a value just evicted by a concurrent write under
NONSTRICT_READ_WRITE. One hour tightens that bound for every region at the
cost of one reload per entry per hour, which is noise at production request
rates. Instances with stricter staleness expectations can override the whole
file via cache.ehcache.config.file.

Also rewrites the region declaration comments in neutral terms: why declared
caches are store-by-reference while runtime-created ones are forced
store-by-value by the JCache defaults, how the region list and heap bounds
were chosen, and how to tune both from the per-region metrics exposed at
/api/metrics.

AI Assisted
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 New issue
1 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@netroms

netroms commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Image published: dhis2/core-pr:24859 (content = #24810 head 809d8e3). Closing since the image is all this PR was for; it stays pullable. Will reopen briefly only if #24810 gains commits and the candidate image needs refreshing. AI Assisted

@netroms netroms closed this Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant