-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
perf(common): code size reduction of ngFor
directive
#44315
Conversation
Note: the total size savings for the todo example app is 395 bytes. The removal of the insertion tuples buffer also reduces runtime memory pressure. |
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.
This PR is in the draft mode (possibly in the "work in progress" state), but I wanted to leave a quick comment with an additional idea anyways :)
@@ -234,42 +237,32 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh | |||
const view = this._viewContainer.createEmbeddedView( | |||
this._template, new NgForOfContext<T, U>(null!, this._ngForOf!, -1, -1), | |||
currentIndex === null ? undefined : currentIndex); | |||
const tuple = new RecordViewTuple<T, U>(item, view); | |||
insertTuples.push(tuple); | |||
applyViewChange(view, item); | |||
} else if (currentIndex == null) { | |||
this._viewContainer.remove( | |||
adjustedPreviousIndex === null ? undefined : adjustedPreviousIndex); | |||
} else if (adjustedPreviousIndex !== null) { | |||
const view = this._viewContainer.get(adjustedPreviousIndex)!; | |||
this._viewContainer.move(view, currentIndex); |
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.
The changes look great, thanks @JoostK 👍
One more idea that we can explore is to extract the this._viewContainer
into a local const, so it's better minified:
const viewContainer = this._viewContainer;
// ...
viewContainer.move(view, currentIndex);
would be minified to something like this:
var v = this._viewContainer;
// ...
v.move(view, currentIndex);
and given the fact that we have 7 instances of this._viewContainer
inside the function - we'd get more savings.
Also, that may be a tiny perf runtime improvement as well, since we'd avoid extra property reads.
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.
Thanks Andrew, that's an excellent idea!
Cool, we're now at 497 fewer bytes! I'll see if I can get the tests green (mostly golden updates) before marking this for review. |
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.
@JoostK thanks for the perf improvement 👍
ce68a0d
to
5f697f6
Compare
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.
Reviewed-for: size-tracking
Merge assistance: presubmits for this change are successful. |
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.
LGTM 🍪
reviewed-for: size-tracking
This commit makes several changes to the implementation of `NgForOf` to reduce its code size in production builds: 1. The tailor-made message for an unsupported differ is fully tree-shaken in production builds, in favor of the exception from the differ factory itself. 2. The private `_perViewChange` method was changed into a free-standing function, to allow its name to be minimized. 3. The need for an intermediate `RecordViewTuple` was avoided by applying the operation in-place, instead of collecting all insertions into a buffer first. This is safe as the `_perViewChange` operation that used to be done on each `RecordViewTuple` is entirely local to the tuple itself. Hence, it is invariant to execution ordering which means that the `_perViewChange` can be executed directly during the `forEachOperation` loop.
5f697f6
to
a724d4b
Compare
FYI, there was a problem merging this PR, so I did a rebase. Will try to merge it again once CI is completed. |
This PR was merged into the repository by commit 1336297. |
This commit makes several changes to the implementation of `NgForOf` to reduce its code size in production builds: 1. The tailor-made message for an unsupported differ is fully tree-shaken in production builds, in favor of the exception from the differ factory itself. 2. The private `_perViewChange` method was changed into a free-standing function, to allow its name to be minimized. 3. The need for an intermediate `RecordViewTuple` was avoided by applying the operation in-place, instead of collecting all insertions into a buffer first. This is safe as the `_perViewChange` operation that used to be done on each `RecordViewTuple` is entirely local to the tuple itself. Hence, it is invariant to execution ordering which means that the `_perViewChange` can be executed directly during the `forEachOperation` loop. PR Close #44315
This commit makes several changes to the implementation of `NgForOf` to reduce its code size in production builds: 1. The tailor-made message for an unsupported differ is fully tree-shaken in production builds, in favor of the exception from the differ factory itself. 2. The private `_perViewChange` method was changed into a free-standing function, to allow its name to be minimized. 3. The need for an intermediate `RecordViewTuple` was avoided by applying the operation in-place, instead of collecting all insertions into a buffer first. This is safe as the `_perViewChange` operation that used to be done on each `RecordViewTuple` is entirely local to the tuple itself. Hence, it is invariant to execution ordering which means that the `_perViewChange` can be executed directly during the `forEachOperation` loop. PR Close angular#44315
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
This commit makes several changes to the implementation of
NgForOf
toreduce its code size in production builds:
tree-shaken in production builds, in favor of the exception from the
differ factory itself.
_perViewChange
method was changed into a free-standingfunction, to allow its name to be minimized.
RecordViewTuple
was avoided byapplying the operation in-place, instead of collection all insertions
into a buffer first. This is safe as the
_perViewChange
operationthat used to be done on each
RecordViewTuple
is entirely local tothe tuple itself. Hence, it is invariant to execution ordering which
means that the
_perViewChange
can be executed directly during theforEachOperation
loop.