Skip to content

perf: skip org unit/period resolution in dimension recommendations#24264

Open
jason-p-pickering wants to merge 3 commits into
masterfrom
perf-recommendations-skip-ou-dimension
Open

perf: skip org unit/period resolution in dimension recommendations#24264
jason-p-pickering wants to merge 3 commits into
masterfrom
perf-recommendations-skip-ou-dimension

Conversation

@jason-p-pickering

@jason-p-pickering jason-p-pickering commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes https://dhis2.atlassian.net/browse/DHIS2-21671

/api/dimensions/recommendations resolved every dimension on the request via
DataQueryService.getFromRequest, including ou:LEVEL-*. On a large hierarchy this hydrates all org
units at that level as full Hibernate entities and sorts them — ~4.5s CPU and ~3.2 GB allocated in
production profiling (Nigeria EMIS) — yet the result is discarded: getRecommendedDimensions
only reads the data (dx) dimension's data elements / program indicators (plus org unit group sets
loaded separately). The org unit and period dimensions are never read.

This PR scopes the request to the dx dimension before resolving it, so getFromRequest never
resolves/hydrates the unused dimensions.

Profiling (before)

Metric Value
Duration 4,487 ms
CPU 4,480 ms
Allocated memory 3.2 GB
DB time ~5 ms (not DB-bound)
Response 304

Flame graph hot path: getFromRequestgetOrgUnitDimension
getOrganisationUnitsAtLevelsHibernateOrganisationUnitStore.getOrganisationUnits
(full-entity hydration) → ComparableTimSort/Collections.sort.

Change

Set<String> dataDimensionsOnly =
    request.getDimension() == null ? null
        : request.getDimension().stream()
            .filter(param -> DATA_X_DIM_ID.equals(getDimensionFromParam(param)))
            .collect(Collectors.toSet());

DataQueryParams params =
    dataQueryService.getFromRequest(
        DataQueryRequest.newBuilder().dimension(dataDimensionsOnly).build());

The sole caller (DimensionController) sets only the dimension param, so this is
behaviour-equivalent for everything the endpoint consumes. No change to DataQueryService,
getOrganisationUnitsAtLevels, or HibernateOrganisationUnitStore — zero blast radius on other callers.

Tests

New unit test DefaultAnalyticsDimensionServiceTest.getRecommendedDimensionsResolvesOnlyDataDimension
captures the DataQueryRequest passed to getFromRequest and asserts only the dx param survives
(ou / pe stripped). Verified failing before the fix, passing after.

Notes

  • Same large-hierarchy org-unit hydration pattern seen in geoFeatures / dataSets-no-fields /
    getMetaData OUG-count issues — but here the work is pure dead work, not a needed result.
  • JIRA ticket writeup to be filed; this is a self-contained server-side fix.

🤖 Generated with Claude Code

The /api/dimensions/recommendations endpoint resolved every dimension on
the request via DataQueryService.getFromRequest, including ou:LEVEL-*.
On a large hierarchy this hydrates all org units at the level as full
entities and sorts them (~4.5s CPU, ~3.2 GB allocated in production
profiling) — but getRecommendedDimensions only reads the data (dx)
dimension's data elements/program indicators, so the org unit (and
period) resolution is discarded.

Scope the request to the dx dimension before resolving, so getFromRequest
never resolves/hydrates the unused dimensions. Behaviour-equivalent for the
sole caller (DimensionController sets only the dimension param), with no
change to DataQueryService/getOrganisationUnitsAtLevels callers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jason-p-pickering jason-p-pickering requested review from a team and jbee June 22, 2026 07:30
@david-mackessy david-mackessy requested a review from a team June 22, 2026 08:52
@jason-p-pickering jason-p-pickering added the run-api-analytics-tests Enables analytics e2e tests label Jun 22, 2026
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-api-analytics-tests Enables analytics e2e tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants