Skip to content

Commit

Permalink
perf(core): cache LiveCollectionLContainerImpl (angular#52227)
Browse files Browse the repository at this point in the history
This change avoid re-creation of the LiveCollectionLContainerImpl instance
every time the repeater runs (on every change detection).

PR Close angular#52227
  • Loading branch information
pkozlowski-opensource authored and ChellappanRajan committed Jan 23, 2024
1 parent 950ee24 commit c245c39
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions packages/core/src/render3/instructions/control_flow.ts
Expand Up @@ -101,7 +101,9 @@ export function ɵɵrepeaterTrackByIdentity<T>(_: number, value: T) {
}

class RepeaterMetadata {
constructor(public hasEmptyBlock: boolean, public trackByFn: TrackByFunction<unknown>) {}
constructor(
public hasEmptyBlock: boolean, public trackByFn: TrackByFunction<unknown>,
public liveCollection?: LiveCollectionLContainerImpl) {}
}

/**
Expand Down Expand Up @@ -197,6 +199,10 @@ class LiveCollectionLContainerImpl extends
this.getLView(index)[CONTEXT].$implicit = value;
}

reset() {
this.needsIndexUpdate = false;
}

updateIndexes() {
if (this.needsIndexUpdate) {
for (let i = 0; i < this.length; i++) {
Expand Down Expand Up @@ -225,11 +231,18 @@ export function ɵɵrepeater(
const hostLView = getLView();
const hostTView = hostLView[TVIEW];
const metadata = hostLView[HEADER_OFFSET + metadataSlotIdx] as RepeaterMetadata;
const containerIndex = metadataSlotIdx + 1;
const lContainer = getLContainer(hostLView, HEADER_OFFSET + containerIndex);
const itemTemplateTNode = getExistingTNode(hostTView, containerIndex);

const liveCollection = new LiveCollectionLContainerImpl(lContainer, hostLView, itemTemplateTNode);
if (metadata.liveCollection === undefined) {
const containerIndex = metadataSlotIdx + 1;
const lContainer = getLContainer(hostLView, HEADER_OFFSET + containerIndex);
const itemTemplateTNode = getExistingTNode(hostTView, containerIndex);
metadata.liveCollection =
new LiveCollectionLContainerImpl(lContainer, hostLView, itemTemplateTNode);
} else {
metadata.liveCollection.reset();
}

const liveCollection = metadata.liveCollection;
reconcile(liveCollection, collection, metadata.trackByFn);

// moves in the container might caused context's index to get out of order, re-adjust if needed
Expand All @@ -238,7 +251,7 @@ export function ɵɵrepeater(
// handle empty blocks
if (metadata.hasEmptyBlock) {
const bindingIndex = nextBindingIndex();
const isCollectionEmpty = lContainer.length - CONTAINER_HEADER_OFFSET === 0;
const isCollectionEmpty = liveCollection.length === 0;
if (bindingUpdated(hostLView, bindingIndex, isCollectionEmpty)) {
const emptyTemplateIndex = metadataSlotIdx + 2;
const lContainerForEmpty = getLContainer(hostLView, HEADER_OFFSET + emptyTemplateIndex);
Expand Down

0 comments on commit c245c39

Please sign in to comment.