refactor(ivy): rewrite flatten function to be more memory efficient (#30468)
The `flatten` function used `concat` and `slice` which created a lot of intermediary object allocations. Because `flatten` is used from query any benchmark which used query would exhibit high minor GC counts. PR Close #30468
This commit is contained in:
parent
c9f5f3d802
commit
f3c69e7f6b
@ -3,7 +3,7 @@
|
|||||||
"master": {
|
"master": {
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime": 1497,
|
"runtime": 1497,
|
||||||
"main": 166739,
|
"main": 166799,
|
||||||
"polyfills": 43626
|
"polyfills": 43626
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,20 +30,16 @@ function getSymbolIterator() {
|
|||||||
|
|
||||||
if ("undefined" === typeof ngI18nClosureMode) _global["ngI18nClosureMode"] = "undefined" !== typeof goog && "function" === typeof goog.getMsg;
|
if ("undefined" === typeof ngI18nClosureMode) _global["ngI18nClosureMode"] = "undefined" !== typeof goog && "function" === typeof goog.getMsg;
|
||||||
|
|
||||||
function flatten(list, mapFn) {
|
function flatten(list, dst) {
|
||||||
const result = [];
|
if (void 0 === dst) dst = list;
|
||||||
let i = 0;
|
for (let i = 0; i < list.length; i++) {
|
||||||
while (i < list.length) {
|
let item = list[i];
|
||||||
const item = list[i];
|
if (Array.isArray(item)) {
|
||||||
if (Array.isArray(item)) if (item.length > 0) {
|
if (dst === list) dst = list.slice(0, i);
|
||||||
list = item.concat(list.slice(i + 1));
|
flatten(item, dst);
|
||||||
i = 0;
|
} else if (dst !== list) dst.push(item);
|
||||||
} else i++; else {
|
|
||||||
result.push(mapFn ? mapFn(item) : item);
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
return dst;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventEmitter extends Subject {
|
class EventEmitter extends Subject {
|
||||||
|
@ -108,11 +108,13 @@ export function compileNgModuleDefs(moduleType: NgModuleType, ngModule: NgModule
|
|||||||
ngModuleDef = getCompilerFacade().compileNgModule(
|
ngModuleDef = getCompilerFacade().compileNgModule(
|
||||||
angularCoreEnv, `ng:///${moduleType.name}/ngModuleDef.js`, {
|
angularCoreEnv, `ng:///${moduleType.name}/ngModuleDef.js`, {
|
||||||
type: moduleType,
|
type: moduleType,
|
||||||
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY, resolveForwardRef),
|
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(resolveForwardRef),
|
||||||
declarations: declarations.map(resolveForwardRef),
|
declarations: declarations.map(resolveForwardRef),
|
||||||
imports: flatten(ngModule.imports || EMPTY_ARRAY, resolveForwardRef)
|
imports: flatten(ngModule.imports || EMPTY_ARRAY)
|
||||||
|
.map(resolveForwardRef)
|
||||||
.map(expandModuleWithProviders),
|
.map(expandModuleWithProviders),
|
||||||
exports: flatten(ngModule.exports || EMPTY_ARRAY, resolveForwardRef)
|
exports: flatten(ngModule.exports || EMPTY_ARRAY)
|
||||||
|
.map(resolveForwardRef)
|
||||||
.map(expandModuleWithProviders),
|
.map(expandModuleWithProviders),
|
||||||
emitInline: true,
|
emitInline: true,
|
||||||
schemas: ngModule.schemas ? flatten(ngModule.schemas) : null,
|
schemas: ngModule.schemas ? flatten(ngModule.schemas) : null,
|
||||||
@ -156,12 +158,12 @@ function verifySemanticsOfNgModuleDef(moduleType: NgModuleType): void {
|
|||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
const declarations = maybeUnwrapFn(ngModuleDef.declarations);
|
const declarations = maybeUnwrapFn(ngModuleDef.declarations);
|
||||||
const imports = maybeUnwrapFn(ngModuleDef.imports);
|
const imports = maybeUnwrapFn(ngModuleDef.imports);
|
||||||
flatten(imports, unwrapModuleWithProvidersImports).forEach(verifySemanticsOfNgModuleDef);
|
flatten(imports).map(unwrapModuleWithProvidersImports).forEach(verifySemanticsOfNgModuleDef);
|
||||||
const exports = maybeUnwrapFn(ngModuleDef.exports);
|
const exports = maybeUnwrapFn(ngModuleDef.exports);
|
||||||
declarations.forEach(verifyDeclarationsHaveDefinitions);
|
declarations.forEach(verifyDeclarationsHaveDefinitions);
|
||||||
const combinedDeclarations: Type<any>[] = [
|
const combinedDeclarations: Type<any>[] = [
|
||||||
...declarations.map(resolveForwardRef), //
|
...declarations.map(resolveForwardRef), //
|
||||||
...flatten(imports.map(computeCombinedExports), resolveForwardRef),
|
...flatten(imports.map(computeCombinedExports)).map(resolveForwardRef),
|
||||||
];
|
];
|
||||||
exports.forEach(verifyExportsAreDeclaredOrReExported);
|
exports.forEach(verifyExportsAreDeclaredOrReExported);
|
||||||
declarations.forEach(verifyDeclarationIsUnique);
|
declarations.forEach(verifyDeclarationIsUnique);
|
||||||
@ -170,7 +172,8 @@ function verifySemanticsOfNgModuleDef(moduleType: NgModuleType): void {
|
|||||||
const ngModule = getAnnotation<NgModule>(moduleType, 'NgModule');
|
const ngModule = getAnnotation<NgModule>(moduleType, 'NgModule');
|
||||||
if (ngModule) {
|
if (ngModule) {
|
||||||
ngModule.imports &&
|
ngModule.imports &&
|
||||||
flatten(ngModule.imports, unwrapModuleWithProvidersImports)
|
flatten(ngModule.imports)
|
||||||
|
.map(unwrapModuleWithProvidersImports)
|
||||||
.forEach(verifySemanticsOfNgModuleDef);
|
.forEach(verifySemanticsOfNgModuleDef);
|
||||||
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyCorrectBootstrapType);
|
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyCorrectBootstrapType);
|
||||||
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyComponentIsPartOfNgModule);
|
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyComponentIsPartOfNgModule);
|
||||||
|
@ -19,24 +19,23 @@ export function addAllToArray(items: any[], arr: any[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flattens an array in non-recursive way. Input arrays are not modified.
|
* Flattens an array.
|
||||||
*/
|
*/
|
||||||
export function flatten(list: any[], mapFn?: (value: any) => any): any[] {
|
export function flatten(list: any[], dst?: any[]): any[] {
|
||||||
const result: any[] = [];
|
if (dst === undefined) dst = list;
|
||||||
let i = 0;
|
for (let i = 0; i < list.length; i++) {
|
||||||
while (i < list.length) {
|
let item = list[i];
|
||||||
const item = list[i];
|
|
||||||
if (Array.isArray(item)) {
|
if (Array.isArray(item)) {
|
||||||
if (item.length > 0) {
|
// we need to inline it.
|
||||||
list = item.concat(list.slice(i + 1));
|
if (dst === list) {
|
||||||
i = 0;
|
// Our assumption that the list was already flat was wrong and
|
||||||
} else {
|
// we need to clone flat since we need to write to it.
|
||||||
i++;
|
dst = list.slice(0, i);
|
||||||
}
|
}
|
||||||
} else {
|
flatten(item, dst);
|
||||||
result.push(mapFn ? mapFn(item) : item);
|
} else if (dst !== list) {
|
||||||
i++;
|
dst.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return dst;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user