Enable Size Caching by default
andersio opened this issue · 1 comments
Problem Statement
Enable size caching by default in Bento, for both UITableView and UICollectionView (if using UICollectionViewFlowLayout).
This helps scrolling performance for use cases with a low frequency of changes & a moderate amount of screen complexity.
The problem is, however, the incurred cost during re-rendering of new Box
s. Bento must invalidate all cached sizes before starting to render any new Box
, unless the component does not change at a given ID path. Pragmatically speaking, this cannot happen for a majority of components (e.g. BentoKit) falling back to the pointer equality (conservative but correct), due to them carrying non-equatable properties e.g. callback.
So if we enable size caching without addressing this issue, for screens that have high burst of state changes e.g. reacting to continuous text input, the cost of precomputation would be incurred every time a new Box
is rendered, which is incredibly unideal.
Synthetic Benchmark
TitledDescription
, 1000 iterations, -O -wholemodule
Source
Item | Result (1000 iterations) |
---|---|
Full equality of layout affecting properties* | Small Strings:
sub 1 ms. 5000+ character strings: sub 2 ms |
Custom Height Computation | sub 100 ms |
AutoLayout height computation | > 1000 ms |
* Style sheets & RAS properties are compared by value.
Observation
Evaluating equality of a subset of component properties is considerably cheaper (2-3 order of magnitude) than computing the actual layout height.
In order words, it is beneficial and pragmatic to evaluate equality so as to avoid as much layout computation as possible, lowering the performance impact of sizing ahead of time.
Proposed optimization
-
Introduce a notion of “component layout equivalence” to replace component equation.
When we say
C.isLayoutEquivalent(a, b) == true
, all properties contributing to the layout from both instances are equal. In other words, renderinga
andb
should result in the same exact layout.Renderable
would however provide afalse
returning default implementation. This effectively replicates the current behaviour (still correct but more expensive), while being (mostly) source compatible.BentoKit components should provide implementations for this requirement.
-
Remove
Equatable
inheritance fromRenderable
.We should not reappropriate
==
for component layout equivalence, since it would violate the substitutability requirement mandated by the Equatable contract. -
With the above two measures in place, Bento may start pre-compute component height using AutoLayout by default .
Bento should invalidate only cached size for ID paths failing the component layout equivalence test.
-
(Optionally) Replacing
HeightCustomizing
with something more general.
Implementation Plan:
-
Introduce(Done, #141)AdapterStore
which is capable of storing cached size and related attributes, and perform invalidation as required.TableViewAdapterBase
would integrateAdapterStore
, but the size caching capability would not be enabled. -
Introduce(Done, #141)SizeCachingTableView
which would have size caching capability enabled. -
Upgrade(Done, #145)BoxViewController
to useSizeCachingTableView
. -
Support pre-sizing layout pass that would enable layouts involving multi-line text to work reliably.(Done, #121) -
Remove
HeightCustomizing
. -
Introduce(Need reevaluation)SizeCachingCollectionView
. -
Upgrade screens using a custom size cache implementation to use(Need reevaluation)SizeCachingCollectionView
. -
Introduce Layout Equivalence.