Conversation
Rendering a record with a large custom field set is quadratic in (fields x values): - isFieldVisible() is called once per field by the builders, and each call re-runs extractFieldValues(), resolving every field value through the full Eloquent cast chain (~200ms per filled value). 97 filled fields => 9,409 resolutions and a ~20s render. - FieldManager::getFieldType() rebuilds the whole 22-type registry via toCollection() on every call; the builders read $field->typeData (an uncached accessor that hits it) inside their filter loops, so a single render rebuilds the registry hundreds of times. Fixes: - Memoise extractFieldValues() against the loaded customFieldValues relation object via a WeakMap, so the memo has exactly the lifetime of the relation the method already caches: refresh()/load() install a new collection and naturally drop the memo. Keyed by the field-id signature so different field subsets coexist. - Cache getFieldType() results per key in $cachedFieldTypeData, mirroring how getFieldTypeInstance() already caches instances. The registry is effectively immutable once built (getFieldTypes() caches and never invalidates), so this is safe. On the reporter's 97-field entity this takes a single render from ~19.8s to ~0.8s. Fixes relaticle#225
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Rendering a record with a large custom field set is quadratic in
(fields × values)— per the excellent analysis in #225:isFieldVisible()is called once per field by the builders, and each call re-runsextractFieldValues(), resolving every field value through the full Eloquent cast chain. 97 filled fields → 9,409 resolutions → ~20s render.FieldManager::getFieldType()rebuilds the whole 22-type registry viatoCollection()on every call; builders read->typeDatainside their filter loops, causing hundreds of full registry rebuilds per render.Fix
1.
BackendVisibilityService::extractFieldValues()— memoised against the loadedcustomFieldValuesrelation object via aWeakMap:refresh()orload()installs a new collection, which drops the memo with it (no staleness possible).2.
FieldManager::getFieldType()— per-key cache in ``, mirroring howgetFieldTypeInstance()right beside it already caches instances. Safe because `getFieldTypes()` caches and never invalidates — the registry is effectively immutable once built.Result
Same as reported in the issue: 97-field render drops from ~19.8s to ~0.8s.
Verification
php -lpasses on both files.Fixes #225