Skip to content

Commit 01af94c

Browse files
pkozlowski-opensourcealxhub
authored andcommitted
perf(ivy): extract template's instruction first create pass processing (#33856)
This refactorings clearly separates the first and subsequent creation execution of the `template` instruction. This approach has the following benefits: - it is clear what happens during the first vs. subsequent executions; - we can avoid several memory reads and checks after the first creation pass (there is measurable performance improvement on various benchmarks); - the template instructions becomes smaller and should become a candidate for optimisations / inlining faster; PR Close #33856
1 parent 456ea5c commit 01af94c

File tree

2 files changed

+51
-34
lines changed

2 files changed

+51
-34
lines changed

packages/core/src/render3/instructions/container.ts

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import {assertDataInRange, assertEqual} from '../../util/assert';
9-
import {assertHasParent} from '../assert';
9+
import {assertFirstCreatePass, assertHasParent} from '../assert';
1010
import {attachPatchData} from '../context_discovery';
1111
import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, registerPostOrderHooks} from '../hooks';
1212
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
1313
import {ComponentTemplate} from '../interfaces/definition';
1414
import {LocalRefExtractor, TAttributes, TContainerNode, TNode, TNodeType, TViewNode} from '../interfaces/node';
1515
import {isDirectiveHost} from '../interfaces/type_checks';
16-
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TVIEW, TViewType, T_HOST} from '../interfaces/view';
16+
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TVIEW, TView, TViewType, T_HOST} from '../interfaces/view';
1717
import {assertNodeType} from '../node_assert';
1818
import {appendChild, removeView} from '../node_manipulation';
1919
import {getBindingIndex, getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
@@ -44,6 +44,36 @@ export function ɵɵcontainer(index: number): void {
4444
setIsNotParent();
4545
}
4646

47+
function templateFirstCreatePass(
48+
index: number, tView: TView, lView: LView, templateFn: ComponentTemplate<any>| null,
49+
decls: number, vars: number, tagName?: string | null, attrsIndex?: number | null,
50+
localRefsIndex?: number | null): TContainerNode {
51+
ngDevMode && assertFirstCreatePass(tView);
52+
ngDevMode && ngDevMode.firstCreatePass++;
53+
const tViewConsts = tView.consts;
54+
// TODO(pk): refactor getOrCreateTNode to have the "create" only version
55+
const tNode = getOrCreateTNode(
56+
tView, lView[T_HOST], index, TNodeType.Container, tagName || null,
57+
getConstant<TAttributes>(tViewConsts, attrsIndex));
58+
59+
resolveDirectives(tView, lView, tNode, getConstant<string[]>(tViewConsts, localRefsIndex));
60+
registerPostOrderHooks(tView, tNode);
61+
62+
const embeddedTView = tNode.tViews = createTView(
63+
TViewType.Embedded, -1, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry,
64+
null, tView.schemas, tViewConsts);
65+
const embeddedTViewNode = createTNode(tView, null, TNodeType.View, -1, null, null) as TViewNode;
66+
embeddedTViewNode.injectorIndex = tNode.injectorIndex;
67+
embeddedTView.node = embeddedTViewNode;
68+
69+
if (tView.queries !== null) {
70+
tView.queries.template(tView, tNode);
71+
embeddedTView.queries = tView.queries.embeddedTView(tNode);
72+
}
73+
74+
return tNode;
75+
}
76+
4777
/**
4878
* Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
4979
*
@@ -69,40 +99,27 @@ export function ɵɵtemplate(
6999
localRefExtractor?: LocalRefExtractor) {
70100
const lView = getLView();
71101
const tView = lView[TVIEW];
72-
const tViewConsts = tView.consts;
102+
const adjustedIndex = index + HEADER_OFFSET;
73103

74-
// TODO: consider a separate node type for templates
75-
const tContainerNode = containerInternal(
76-
lView, index, tagName || null, getConstant<TAttributes>(tViewConsts, attrsIndex));
77-
78-
if (tView.firstCreatePass) {
79-
ngDevMode && ngDevMode.firstCreatePass++;
80-
resolveDirectives(
81-
tView, lView, tContainerNode, getConstant<string[]>(tViewConsts, localRefsIndex));
82-
registerPostOrderHooks(tView, tContainerNode);
83-
84-
const embeddedTView = tContainerNode.tViews = createTView(
85-
TViewType.Embedded, -1, templateFn, decls, vars, tView.directiveRegistry,
86-
tView.pipeRegistry, null, tView.schemas, tViewConsts);
87-
const embeddedTViewNode = createTNode(tView, null, TNodeType.View, -1, null, null) as TViewNode;
88-
embeddedTViewNode.injectorIndex = tContainerNode.injectorIndex;
89-
embeddedTView.node = embeddedTViewNode;
90-
91-
if (tView.queries !== null) {
92-
tView.queries.template(tView, tContainerNode);
93-
embeddedTView.queries = tView.queries.embeddedTView(tContainerNode);
94-
}
95-
}
104+
const tNode = tView.firstCreatePass ?
105+
templateFirstCreatePass(
106+
index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) :
107+
tView.data[adjustedIndex] as TContainerNode;
108+
setPreviousOrParentTNode(tNode, false);
96109

97-
if (isDirectiveHost(tContainerNode)) {
98-
createDirectivesInstances(tView, lView, tContainerNode);
99-
}
110+
const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : '');
111+
appendChild(comment, tNode, lView);
112+
attachPatchData(comment, lView);
100113

101-
if (localRefsIndex !== null) {
102-
saveResolvedLocalsInData(lView, tContainerNode, localRefExtractor);
114+
addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode));
115+
116+
if (isDirectiveHost(tNode)) {
117+
createDirectivesInstances(tView, lView, tNode);
103118
}
104119

105-
setIsNotParent();
120+
if (localRefsIndex != null) {
121+
saveResolvedLocalsInData(lView, tNode, localRefExtractor);
122+
}
106123
}
107124

108125
/**

packages/core/test/bundling/todo/bundle.golden_symbols.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,9 +443,6 @@
443443
{
444444
"name": "concatString"
445445
},
446-
{
447-
"name": "containerInternal"
448-
},
449446
{
450447
"name": "createContainerRef"
451448
},
@@ -1301,6 +1298,9 @@
13011298
{
13021299
"name": "syncViewWithBlueprint"
13031300
},
1301+
{
1302+
"name": "templateFirstCreatePass"
1303+
},
13041304
{
13051305
"name": "textBindingInternal"
13061306
},

0 commit comments

Comments
 (0)