perf(ivy): avoid creating holey LView Arrays (#31839)

PR Close #31839
This commit is contained in:
Pawel Kozlowski 2019-07-25 14:27:10 +02:00 committed by Andrew Kushnir
parent a9ec3db91a
commit 78659ec0b0
2 changed files with 23 additions and 5 deletions

View File

@ -22,6 +22,21 @@ Great reads:
See benchmark [here](https://jsperf.com/mono-vs-megamorphic-property-access). See benchmark [here](https://jsperf.com/mono-vs-megamorphic-property-access).
## Packed vs. holey Array
V8 represents arrays internally in a different way depending on:
- type of elements in the array;
- presence of holes (indexes that were never assigned).
Generally speaking packed arrays (a set of continuous, initialized indexes) perform better as compared to arrays with holes. To assure that arrays are packed follow those guidelines:
* create array literals with known values whenever possible (ex. `a = [0];` is better than `a = []; a.push[0];`;
* don't use `Array` constructor with the size value (ex. `new Array(5)`) - this will create a `HOLEY_ELEMENTS` array (even if this array is filled in later on!);
* don't delete elements from an array (ex. `delete a[0]`) - this will create a hole;
* don't write past the array length as this will create holes;
Great reads:
- [Elements kinds in V8](https://v8.dev/blog/elements-kinds)
## Exporting top level variables ## Exporting top level variables
Exporting top level variables should be avoided where possible where performance Exporting top level variables should be avoided where possible where performance

View File

@ -642,11 +642,14 @@ export function createTView(
} }
function createViewBlueprint(bindingStartIndex: number, initialViewLength: number): LView { function createViewBlueprint(bindingStartIndex: number, initialViewLength: number): LView {
const blueprint = new (ngDevMode ? LViewBlueprint ! : Array)(initialViewLength) const blueprint = ngDevMode ? new LViewBlueprint !() : [];
.fill(null, 0, bindingStartIndex)
.fill(NO_CHANGE, bindingStartIndex) as LView; for (let i = 0; i < initialViewLength; i++) {
blueprint.push(i < bindingStartIndex ? null : NO_CHANGE);
}
blueprint[BINDING_INDEX] = bindingStartIndex; blueprint[BINDING_INDEX] = bindingStartIndex;
return blueprint;
return blueprint as LView;
} }
export function createError(text: string, token: any) { export function createError(text: string, token: any) {
@ -1562,7 +1565,7 @@ export function componentRefresh(hostLView: LView, adjustedElementIndex: number)
function syncViewWithBlueprint(componentView: LView) { function syncViewWithBlueprint(componentView: LView) {
const componentTView = componentView[TVIEW]; const componentTView = componentView[TVIEW];
for (let i = componentView.length; i < componentTView.blueprint.length; i++) { for (let i = componentView.length; i < componentTView.blueprint.length; i++) {
componentView[i] = componentTView.blueprint[i]; componentView.push(componentTView.blueprint[i]);
} }
} }