From 0653db14e778b45b5caae7b18548d69ebfe21cd3 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Mon, 2 Mar 2020 22:23:27 +0100 Subject: [PATCH] perf(core): add micro benchmark for destroy hook invocation (#35784) Adds a micro benchmark which excercises the logic that invokes `ngOnDestroy` hooks. PR Close #35784 --- packages/core/test/render3/perf/BUILD.bazel | 13 ++++ packages/core/test/render3/perf/setup.ts | 4 +- .../render3/perf/view_destroy_hook/index.ts | 78 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 packages/core/test/render3/perf/view_destroy_hook/index.ts diff --git a/packages/core/test/render3/perf/BUILD.bazel b/packages/core/test/render3/perf/BUILD.bazel index 489907540b..da80ae8b9b 100644 --- a/packages/core/test/render3/perf/BUILD.bazel +++ b/packages/core/test/render3/perf/BUILD.bazel @@ -229,3 +229,16 @@ ng_benchmark( name = "host_binding", bundle = ":host_binding", ) + +ng_rollup_bundle( + name = "view_destroy_hook_lib", + entry_point = ":view_destroy_hook/index.ts", + deps = [ + ":perf_lib", + ], +) + +ng_benchmark( + name = "view_destroy_hook", + bundle = ":view_destroy_hook_lib", +) diff --git a/packages/core/test/render3/perf/setup.ts b/packages/core/test/render3/perf/setup.ts index 2eddc4e5ec..51b2579428 100644 --- a/packages/core/test/render3/perf/setup.ts +++ b/packages/core/test/render3/perf/setup.ts @@ -19,10 +19,12 @@ const rendererFactory: RendererFactory3 = isBrowser ? domRendererFactory3 : new MicroBenchmarkRendererFactory; const renderer = rendererFactory.createRenderer(null, null); -export function createAndRenderLView(parentLView: LView, tView: TView, hostTNode: TViewNode) { +export function createAndRenderLView( + parentLView: LView, tView: TView, hostTNode: TViewNode): LView { const embeddedLView = createLView( parentLView, tView, {}, LViewFlags.CheckAlways, null, hostTNode, rendererFactory, renderer); renderView(tView, embeddedLView, null); + return embeddedLView; } export function setupRootViewWithEmbeddedViews( diff --git a/packages/core/test/render3/perf/view_destroy_hook/index.ts b/packages/core/test/render3/perf/view_destroy_hook/index.ts new file mode 100644 index 0000000000..67f6109560 --- /dev/null +++ b/packages/core/test/render3/perf/view_destroy_hook/index.ts @@ -0,0 +1,78 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {OnDestroy} from '@angular/core'; +import {LViewFlags, TViewType} from '@angular/core/src/render3/interfaces/view'; + +import {ɵɵdefineDirective, ɵɵelement, ɵɵelementEnd, ɵɵelementStart} from '../../../../src/render3/index'; +import {createLView, createTNode, createTView} from '../../../../src/render3/instructions/shared'; +import {RenderFlags} from '../../../../src/render3/interfaces/definition'; +import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node'; +import {destroyLView} from '../../../../src/render3/node_manipulation'; +import {createBenchmark} from '../micro_bench'; +import {createAndRenderLView} from '../setup'; + +class ToDestroy implements OnDestroy { + static ɵfac = () => new ToDestroy(); + static ɵdir = ɵɵdefineDirective({type: ToDestroy, selectors: [['', 'to-destroy', '']]}); + ngOnDestroy() {} +} + +`
+ + + + + + + + + + +
`; +function testTemplate(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelementStart(0, 'div'); + ɵɵelement(1, 'span', 0); + ɵɵelement(3, 'span', 0); + ɵɵelement(5, 'span', 0); + ɵɵelement(7, 'span', 0); + ɵɵelement(9, 'span', 0); + ɵɵelement(11, 'span', 0); + ɵɵelement(13, 'span', 0); + ɵɵelement(15, 'span', 0); + ɵɵelement(17, 'span', 0); + ɵɵelement(19, 'span', 0); + ɵɵelementEnd(); + } +} + +const rootLView = createLView( + null, createTView(TViewType.Root, -1, null, 0, 0, null, null, null, null, null), {}, + LViewFlags.IsRoot, null, null); + +const viewTNode = createTNode(null !, null, TNodeType.View, -1, null, null) as TViewNode; +const embeddedTView = createTView( + TViewType.Embedded, -1, testTemplate, 21, 10, [ToDestroy.ɵdir], null, null, null, + [['to-destroy']]); + +// create view once so we don't profile the first create pass +createAndRenderLView(rootLView, embeddedTView, viewTNode); + +// scenario to benchmark +const viewDestroy = createBenchmark('view destroy hook'); +const runBenchmark = viewDestroy('create'); + +console.profile('view_destroy_hook'); +while (runBenchmark()) { + const currentView = createAndRenderLView(rootLView, embeddedTView, viewTNode); + destroyLView(embeddedTView, currentView); +} +console.profileEnd(); + +// report results +viewDestroy.report();