-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make useExpressionDataSources and useValidationDataSources cheaper #2720
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Phenomenal!! I think I understood at least 80% of this, and reading this has finally forced me to learn more about useSyncExternalStore()
(which I've wanted for some time now). Thanks for that! 😅
Co-authored-by: Ole Martin Handeland <github@olemartin.org>
…nd store, making it far more accessible (also removes the need for selecting it in a hookContext)
# Conflicts: # src/utils/layout/NodesContext.tsx # src/utils/layout/generator/LayoutSetGenerator.tsx
…er typing for simple delayed selector props
…red when the route changes. This caused a node item to remain 'undefined', blocking the state from becoming ready. Also adding a tripwire for this.
…e-renders of FormProvider (which in turn causes all-node removal and re-adds). Requiring conditions on all set-hooks in the future.
Quality Gate passedIssues Measures |
Description
When profiling loading a form with many repeating group rows, as well as when filling out data in a large repeating group, one of the largest contributors to timing and memory allocation is
useExpressionDataSources
anduseValidationDataSources
. Both of these hooks use a lot of simple hooks within them as well as a lot of delayed selectors. When having a thousands of nodes these hooks are called A LOT, and so optimizing these makes a big difference even though you may not think these are expensive in regular use. There are primarily two optimizations introduced here, one for simple hooks, and one for delayed selectors.createHookContext
method that allows you to run the hook once for the entire node generator and then reuse the value with a useContext instead. It turns out that even a direct subscription to a zustand store via a useSelector is much more expensive than using a simple context value. Some other hooks likeuseExternalAPI
(useQuery) is also expensive when used at this scale.useRef
, 1xuseState
, 1xuseEffect
, and 2xuseCallback
. For expression data sources we probably had something like 10 delayed selectors (there were some overlap as some other hooks used them internally), we use something like up to 4 expressiondatasources for each node (markhidden, runexpressions, options, sourceoptions). With 10 000 nodes, this becomes a cool couple million hooks 🤯 (of just delayed selectors). Now its more like 80 000 hooks for 10 000 nodes of useExpressionDataSources (of just delayed selectors). Delayed selectors are now implemented using only 1xuseRef
, and 1xuseSyncExternalStore
. Additionally, you can create an arbitrary number of delayed selectors withuseMultipleDelayedSelectors
that also just has a fixed 1xuseRef
and 1xuseSyncExternalStore
.Related Issue(s)
Verification/QA
kind/*
label to this PR for proper release notes grouping