From df8e6750a19adffe3621f0e9fa9a9c859f9babd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Thu, 29 Aug 2019 12:26:50 -0400 Subject: [PATCH] perf(ivy): add a micro benchmark for style and class bindings (#32401) This patch introduces a new micro benchmark that performance tests against style and class bindings in Ivy running together on the same element. PR Close #32401 --- packages/core/test/render3/perf/BUILD.bazel | 8 ++ .../core/test/render3/perf/noop_renderer.ts | 6 +- .../perf/style_and_class_bindings/index.ts | 119 ++++++++++++++++++ 3 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 packages/core/test/render3/perf/style_and_class_bindings/index.ts diff --git a/packages/core/test/render3/perf/BUILD.bazel b/packages/core/test/render3/perf/BUILD.bazel index 1dd489364b..895c452b6b 100644 --- a/packages/core/test/render3/perf/BUILD.bazel +++ b/packages/core/test/render3/perf/BUILD.bazel @@ -51,3 +51,11 @@ ng_rollup_bundle( ":perf_lib", ], ) + +ng_rollup_bundle( + name = "style_and_class_bindings", + entry_point = ":style_and_class_bindings/index.ts", + deps = [ + ":perf_lib", + ], +) diff --git a/packages/core/test/render3/perf/noop_renderer.ts b/packages/core/test/render3/perf/noop_renderer.ts index 2ffb05dc1c..90fe67e9b1 100644 --- a/packages/core/test/render3/perf/noop_renderer.ts +++ b/packages/core/test/render3/perf/noop_renderer.ts @@ -37,8 +37,8 @@ export class NoopRenderer implements ProceduralRenderer3 { removeAttribute(el: RElement, name: string, namespace?: string|null|undefined): void { throw new Error('Method not implemented.'); } - addClass(el: RElement, name: string): void { throw new Error('Method not implemented.'); } - removeClass(el: RElement, name: string): void { throw new Error('Method not implemented.'); } + addClass(el: RElement, name: string): void {} + removeClass(el: RElement, name: string): void {} setStyle(el: RElement, style: string, value: any, flags?: RendererStyleFlags3|undefined): void {} removeStyle(el: RElement, style: string, flags?: RendererStyleFlags3|undefined): void {} setProperty(el: RElement, name: string, value: any): void {} @@ -54,4 +54,4 @@ export class NoopRendererFactory implements RendererFactory3 { createRenderer(hostElement: RElement|null, rendererType: null): Renderer3 { return new NoopRenderer(); } -} \ No newline at end of file +} diff --git a/packages/core/test/render3/perf/style_and_class_bindings/index.ts b/packages/core/test/render3/perf/style_and_class_bindings/index.ts new file mode 100644 index 0000000000..2db4a1f1d8 --- /dev/null +++ b/packages/core/test/render3/perf/style_and_class_bindings/index.ts @@ -0,0 +1,119 @@ +/** + * @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 {ɵɵelementEnd, ɵɵelementStart} from '../../../../src/render3/instructions/element'; +import {ɵɵselect} from '../../../../src/render3/instructions/select'; +import {refreshView} from '../../../../src/render3/instructions/shared'; +import {RenderFlags} from '../../../../src/render3/interfaces/definition'; +import {TVIEW} from '../../../../src/render3/interfaces/view'; +import {AttributeMarker} from '../../../../src/render3/interfaces/node'; +import {ɵɵstyleProp, ɵɵclassProp, ɵɵstyling, ɵɵstylingApply} from '../../../../src/render3/styling_next/instructions'; +import {setupRootViewWithEmbeddedViews} from '../setup'; + +` +
+
+
+
+
+
+
+
+
+
+
+
+
`; +function testTemplate(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelementStart(0, 'div', [AttributeMarker.Classes, 'list']); + ɵɵelementStart(1, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(2, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(3, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(4, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(5, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(6, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(7, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(8, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(9, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementStart(10, 'div', [AttributeMarker.Classes, 'item', AttributeMarker.Styles, 'width', '50px']); + ɵɵstyling(); + ɵɵelementEnd(); + ɵɵelementEnd(); + } + if (rf & 2) { + ɵɵselect(1); + ɵɵstyleProp('width', '0px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(2); + ɵɵstyleProp('width', '100px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(3); + ɵɵstyleProp('width', '200px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(4); + ɵɵstyleProp('width', '300px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(5); + ɵɵstyleProp('width', '400px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(6); + ɵɵstyleProp('width', '500px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(7); + ɵɵstyleProp('width', '600px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(8); + ɵɵstyleProp('width', '700px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(9); + ɵɵstyleProp('width', '800px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + ɵɵselect(10); + ɵɵstyleProp('width', '900px'); + ɵɵclassProp('scale', true); + ɵɵstylingApply(); + } +} + + +const rootLView = setupRootViewWithEmbeddedViews(testTemplate, 11, 10, 1000); +const rootTView = rootLView[TVIEW]; + +// run change detection in the update mode +console.profile('update'); +for (let i = 0; i < 5000; i++) { + refreshView(rootLView, rootTView, null, null); +} +console.profileEnd();