Conversation
|
Hi @secitr! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
PR Draft: VirtualizedList — reduce allocations in the render and scroll path
Branch:
fix/virtualizedlist-reduce-allocationsBase:
react/react-nativemain (c687a35)Summary:
VirtualizedList/FlatList/SectionListre-run a small amount ofbookkeeping on every render and on every scroll event (60–120 Hz on
ProMotion displays). This PR removes four allocations from those hot
paths without changing any observable behavior:
VirtualizedList.renderno longer builds aSetforstickyHeaderIndiceson every render when the prop is not provided(the common case). The Set is now only created when the prop is
present; the two
.has()lookups are null-guarded.ChildListCollection.forEachreturns early when there are no nestedchild lists (the common case) instead of allocating a
Map.values()iterator. This is called from_onScrolland the fourother scroll callbacks on every scroll event.
_orientation()caches its result and only rebuilds the objectwhen the
horizontalprop changes.I18nManager.isRTLis amodule-load constant (only changes on app reload), so the cache is
invalidated solely by the
horizontalprop. The object is replaced,never mutated, which keeps
ListMetricsAggregator's field-basedinvalidation correct.
keyExtractordoes a singletypeofcheck instead ofone per property lookup. It is called per item on every render and on
every viewability scan.
Changelog:
[GENERAL][CHANGED] - Reduce allocations in the
VirtualizedListrender and scroll path (avoid per-renderSetallocation forstickyHeaderIndices, per-scroll-eventMapiterator for the empty nested-list collection, per-callorientationobject allocation, and duplicatetypeofchecks in the defaultkeyExtractor)Test Plan:
yarn test packages/virtualized-lists→ 9 suites, 192 passed, 69snapshots (previously 179 tests; +13 new):
VirtualizeUtils-test.js:keyExtractortruth table (key/idprecedence, explicit
nullkey, falsy keys,null/undefined/primitive/array items)
ChildListCollection-test.js(new): forEach over populated/emptycollection, removal,
forEachInCell/anyInCellVirtualizedList-test.js:stickyHeaderIndicesnot forwarded whenthe prop is absent (with
ListHeaderComponent), forwarded whenprovided; orientation cache identity + invalidation on
horizontalchangeyarn flow-check→ 0 errorsyarn lint→ 0 errors, 0 warningsyarn format-check(changed files)Micro-benchmark (Node v24, V8, 2M iterations, before vs after, same
machine; the real-world benefit is dominated by reduced GC pressure,
which is largest on low-end Android):
I could not run Fantom integration tests (
FlatList-itest.js,SectionList-itest.js) as they require a native build environment.