Skip to content

perf: read a view's overrides as rows, and rank each one once - #17

Merged
JDCyllene merged 1 commit into
CylleneDigital:mainfrom
JDCyllene:perf/read-override-rows-not-entities
Oct 16, 2026
Merged

JDCyllene merged 1 commit into
CylleneDigital:mainfrom
JDCyllene:perf/read-override-rows-not-entities

Conversation

@JDCyllene

Copy link
Copy Markdown
Member

What this pull request does

On a locale with thousands of overrides, the reads behind a catalogue view and the translator's cache miss spent their time outside the database: the grouped read built an entity per override of the browsed locale, and three merges re-ranked both locales (LocaleFallback::rank()) in every comparison of their sort.

  • The grouped read selects rows, not entities. OverrideReader::getTranslationsForCatalogues() reads the key, the catalogue and the value of each override of the browsed locale as a scalar row: TranslationOverrideRepository::findValuesByLocaleAndCatalogues() replaces findByLocaleAndCatalogues(), which only it used. The repository is not part of the public contract.
  • Two merges are bucketed by precedence instead of sorted: the effective overrides of a locale (getEffectiveOverridesByCatalogue(), behind the coverage report and the reference columns of a view) and the inherited values of a view.
  • The translator ranks each row once before sorting them on a cache miss.

The results are unchanged: the precedence and its tie-breaks are the same, and the existing tests of the translator, the reader and the coverage pass as they are. The unit tests that stubbed the removed repository method now stub the new one.

Measured from the Sylius plugin's test application (MariaDB), 26 catalogues, 5,018 overrides in fr_FR and in fr:

Read 1.4.2 This branch
getTranslationsForCatalogues(), fr_FR, 26 catalogues 219 - 232 ms 80 - 85 ms
getEffectiveOverridesByCatalogue(), 7 locales 228 - 286 ms 74 - 84 ms
First trans() in fr_FR, override cache empty 344 - 442 ms 161 - 276 ms

With 500 overrides per locale, the first two go from about 20 - 30 ms to 11 - 14 ms. The query count does not change.

Points to watch

  • Tests pass (vendor/bin/phpunit): 692 tests
  • PHPStan and PHP-CS-Fixer are green (vendor/bin/phpstan analyse, vendor/bin/php-cs-fixer check)
  • UPGRADE.md is up to date if the public contract changes: everything
    docs/public-contract.md lists, method signatures included - nothing changes: the repository is internal, and every listed method keeps its signature and its result
  • A decision taken or reversed has its record in docs/adr/ - none
  • No real API key appears in the code, the tests or this description

If the pull request touches the entity mapping

It does not.

If the pull request touches a provider bridge

It does not.

On a locale with thousands of overrides, the reads behind a catalogue
view and the translator's cache miss spent their time outside the
database: the grouped read built an entity per override of the browsed
locale, and three merges re-ranked both locales in every comparison of
their sort.

- The grouped read selects the key, the catalogue and the value of each
  override as a scalar row (findValuesByLocaleAndCatalogues() replaces
  findByLocaleAndCatalogues(), which only it used).
- The effective overrides of a locale and the inherited values are
  bucketed by precedence instead of sorted.
- The translator ranks each row once before sorting.

With 5,018 overrides in fr_FR and in fr: the grouped read of 26
catalogues goes from about 225 ms to 80 ms, the effective overrides of
seven locales from about 250 ms to 80 ms. The results are unchanged.
@JDCyllene
JDCyllene requested a review from a team as a code owner October 16, 2026 06:58
@JDCyllene
JDCyllene merged commit 35ce78c into CylleneDigital:main Oct 16, 2026
12 checks passed
@JDCyllene
JDCyllene deleted the perf/read-override-rows-not-entities branch October 16, 2026 07:04
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