Skip to content

Connect controllers without listing every context: 3,000 controllers start 43% faster - #925

Open
czj wants to merge 1 commit into
hotwired:mainfrom
czj:perf/outlet-dependent-contexts
Open

czj wants to merge 1 commit into
hotwired:mainfrom
czj:perf/outlet-dependent-contexts

Conversation

@czj

@czj czj commented Oct 28, 2026 •

Copy link
Copy Markdown

Each time a controller connects, its OutletObserver#start refreshes the controllers that declare it as an outlet. To find them, dependentContexts filtered router.contexts, which builds an array of every connected context of every controller, on every connection, even in an application where no controller declares an outlet. Connecting N controllers is therefore O(N²).

dependentContexts now filters router.modules by identifier first, then collects their contexts: the same contexts, in the same order, without walking the others. We noticed it on back-office pages of our app that hold more than 1,000 controllers; below a few hundred the difference is noise.

The new test in application_tests.ts counts reads of router.contexts while loading controllers, and fails on main. Sibling PR: #926 makes the lookups behind outlets O(1).

Measurements

Application#start on a page of N <div data-controller="row">, each with 2 targets, 2 values, 1 class and a button with 2 actions; no outlets. main at 4145d26 and this branch, bundled with esbuild, Chrome 156 on an Apple Silicon Mac, median of 9 page loads.

Controllers main This branch
300 9.0 ms 8.9 ms
1,000 23.0 ms 18.9 ms
3,000 78.9 ms 45.2 ms

Is this an area you would like to see improved, or would you rather keep OutletObserver as is for now?


🤖 Generated with Claude Code, but prompted, read, and verified by @czj, a caring human :)

Every controller connection refreshes the controllers declaring it as an
outlet. Finding them listed the contexts of every controller in the
application, even when no controller declares outlets, so connecting N
controllers cost O(N²). Filter the modules by identifier first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant