Repository navigation
Conversation
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.
Saving a collection tree checks each moved page's URI against its siblings'.
validateUniqueUris()rebuilds every sibling's URI for every moved page, and because the check runs with the URI cache off, each of those builds its parent's URI again, all the way up the tree. Moving a branch of 200 pages under a page 11 levels down works out to about 70,000 URL builds to compare a few hundred URIs.validateUniqueUris()keeps them for each parent and reuses them for every moved page under it.Page, so the parent's URI and its ancestors' are built once rather than once per sibling. It's only read whenTree::disableUriCache()has been called, which in core is this validation. With the cache on,Page::uri()behaves as before. It's forgotten whenever the page's entry, parent, depth, route, root flag or tree is set.Which trees are rejected, and the URI named in the error, are unchanged.
Benchmark
Saving the tree of a structured collection of 2,011 entries, 11 levels deep with 20 pages per level and the route
{parent_uri}/{slug}, on6.42.0and on this PR, run alternately, six runs each, every run in a fresh process (Apple M3 Pro, PHP 8.5, file cache store, Stache watcher off). It runs whatCollectionTreeController::update()runs: the validation, then the save with theCollectionTreeSavedlisteners. Medians:The ranges for the branch move don't overlap: validation took 5,394 to 5,934 ms against 106 to 118 ms. The one-page move is within noise (41.9 to 59.4 ms against 40.1 to 44.1 ms). Memory is unchanged; the cost was time. What's left of the branch move is the save itself, which this PR doesn't touch.
Benchmark scripts
Run from the root of a Statamic site whose default site handle is
default.gen.phpwrites the collection and its entries, thenstache:warm, thenbench.php initsaves the tree.run-ab.shswitchesvendor/statamic/cmsbetween two checkouts for each round.gen.phpbench.phprun-ab.shTests
UpdateCollectionTreeTestcounts the URL builds while two sibling pages under one parent are swapped. On6.xeach sibling's URI is built twice and their parent's 4 times; with this PR every page's URI is built once.PageTestchecks that a page's URI follows a change of route while the URI cache is off. The tests were committed before the changes they cover, so they can be seen failing.Closes #9236