parent
63f0ded5cf
commit
9a5e08f2a7
|
@ -13,6 +13,14 @@ ts_library(
|
|||
],
|
||||
)
|
||||
|
||||
ng_rollup_bundle(
|
||||
name = "class_binding",
|
||||
entry_point = ":class_binding/index.ts",
|
||||
deps = [
|
||||
":perf_lib",
|
||||
],
|
||||
)
|
||||
|
||||
ng_rollup_bundle(
|
||||
name = "directive_instantiate",
|
||||
entry_point = ":directive_instantiate/index.ts",
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* @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 {ɵɵproperty} from '@angular/core/src/core';
|
||||
import {AttributeMarker, TAttributes} from '@angular/core/src/render3/interfaces/node';
|
||||
import {ɵɵelement} from '../../../../src/render3/instructions/element';
|
||||
import {ɵɵclassMap, ɵɵclassProp} from '../../../../src/render3/instructions/styling';
|
||||
import {ComponentTemplate, RenderFlags} from '../../../../src/render3/interfaces/definition';
|
||||
import {createBenchmark} from '../micro_bench';
|
||||
import {setupTestHarness} from '../setup';
|
||||
|
||||
|
||||
const CLASSES_1_A = 'one';
|
||||
const CLASSES_1_B = CLASSES_1_A.toUpperCase();
|
||||
const CLASSES_2_A = 'one two';
|
||||
const CLASSES_2_B = CLASSES_2_A.toUpperCase();
|
||||
const CLASSES_10_A = 'one two three four five six seven eight nine ten';
|
||||
const CLASSES_10_B = CLASSES_10_A.toUpperCase();
|
||||
let toggleClasses = true;
|
||||
|
||||
const consts: TAttributes[] = [
|
||||
[AttributeMarker.Classes, 'A', 'B'] // 0
|
||||
];
|
||||
const context: any = {};
|
||||
const createClassBindingBenchmark = createBenchmark('class binding: create:');
|
||||
const updateClassBindingBenchmark = createBenchmark('class binding: update:');
|
||||
const noopClassBindingBenchmark = createBenchmark('class binding: noop:');
|
||||
function benchmark(name: string, template: ComponentTemplate<any>) {
|
||||
const harness = setupTestHarness(template, 1, 1, 1000, context, consts);
|
||||
|
||||
const createProfile = createClassBindingBenchmark(name);
|
||||
console.profile('create: ' + name);
|
||||
while (createProfile()) {
|
||||
harness.createEmbeddedLView();
|
||||
}
|
||||
console.profileEnd();
|
||||
|
||||
|
||||
const updateProfile = updateClassBindingBenchmark(name);
|
||||
console.profile('update: ' + name);
|
||||
while (updateProfile()) {
|
||||
toggleClasses = !toggleClasses;
|
||||
harness.detectChanges();
|
||||
}
|
||||
console.profileEnd();
|
||||
|
||||
const noopProfile = noopClassBindingBenchmark(name);
|
||||
console.profile('nop: ' + name);
|
||||
while (noopProfile()) {
|
||||
harness.detectChanges();
|
||||
}
|
||||
console.profileEnd();
|
||||
}
|
||||
|
||||
`<div [class]="toggleClasses ? CLASSES_1_A : CLASSES_1_B">`;
|
||||
benchmark(`[class]="CLASSES_1"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div');
|
||||
}
|
||||
if (rf & 2) {
|
||||
ɵɵclassMap(toggleClasses ? CLASSES_1_A : CLASSES_1_B);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
`<div [class]="toggleClasses ? CLASSES_2_A : CLASSES_2_B">`;
|
||||
benchmark(`[class]="CLASSES_2"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div');
|
||||
}
|
||||
if (rf & 2) {
|
||||
ɵɵclassMap(toggleClasses ? CLASSES_2_A : CLASSES_2_B);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
`<div [class]="toggleClasses ? CLASSES_10_A : CLASSES_10_B">`;
|
||||
benchmark(`[class]="CLASSES_10"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div');
|
||||
}
|
||||
if (rf & 2) {
|
||||
ɵɵclassMap(toggleClasses ? CLASSES_10_A : CLASSES_10_B);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
`<div class="A B">`;
|
||||
benchmark(`class="A B"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div', 0);
|
||||
}
|
||||
if (rf & 2) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
`<div class="A B"
|
||||
[class]="toggleClasses ? CLASSES_1_A : CLASSES_1_B">`;
|
||||
benchmark(`class="A B" [class]="CLASSES_1"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div', 0);
|
||||
}
|
||||
if (rf & 2) {
|
||||
ɵɵclassMap(toggleClasses ? CLASSES_1_A : CLASSES_1_B);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
`<div class="A B"
|
||||
[class]="toggleClasses ? CLASSES_10_A : CLASSES_10_B">`;
|
||||
benchmark(`class="A B" [class]="CLASSES_10"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div', 0);
|
||||
}
|
||||
if (rf & 2) {
|
||||
ɵɵclassMap(toggleClasses ? CLASSES_10_A : CLASSES_10_B);
|
||||
}
|
||||
});
|
||||
|
||||
`<div class="A B"
|
||||
[class]="toggleClasses ? CLASSES_1_A : CLASSES_1_B"
|
||||
[class.foo]="toggleClasses">`;
|
||||
benchmark(`class="A B" [class]="CLASSES_1" [class.foo]="exp"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div', 0);
|
||||
}
|
||||
if (rf & 2) {
|
||||
ɵɵclassMap(toggleClasses ? CLASSES_1_A : CLASSES_1_B);
|
||||
ɵɵclassProp('foo', toggleClasses);
|
||||
}
|
||||
});
|
||||
|
||||
`<div class="A B"
|
||||
[class]="toggleClasses ? CLASSES_10_A : CLASSES_10_B"
|
||||
[class.foo]="toggleClasses">`;
|
||||
benchmark(
|
||||
`class="A B" [class]="CLASSES_10" [class.foo]="exp"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div', 0);
|
||||
}
|
||||
if (rf & 2) {
|
||||
ɵɵclassMap(toggleClasses ? CLASSES_10_A : CLASSES_10_B);
|
||||
ɵɵclassProp('foo', toggleClasses);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
`<div [className]="toggleClasses ? CLASSES_10_A : CLASSES_10_B">`;
|
||||
benchmark(`[className]="CLASSES_10"`, function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & 1) {
|
||||
ɵɵelement(0, 'div');
|
||||
}
|
||||
if (rf & 2) {
|
||||
ɵɵproperty('className', toggleClasses ? CLASSES_10_A : CLASSES_10_B);
|
||||
}
|
||||
});
|
||||
|
||||
createClassBindingBenchmark.report();
|
||||
updateClassBindingBenchmark.report();
|
||||
noopClassBindingBenchmark.report();
|
|
@ -5,11 +5,11 @@
|
|||
* 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 {addToViewTree, createLContainer, createLView, createTNode, createTView, getOrCreateTNode, renderView} from '../../../src/render3/instructions/shared';
|
||||
import {addToViewTree, createLContainer, createLView, createTNode, createTView, getOrCreateTNode, refreshView, renderView} from '../../../src/render3/instructions/shared';
|
||||
import {ComponentTemplate} from '../../../src/render3/interfaces/definition';
|
||||
import {TAttributes, TNodeType, TViewNode} from '../../../src/render3/interfaces/node';
|
||||
import {RComment} from '../../../src/render3/interfaces/renderer';
|
||||
import {LView, LViewFlags, TView} from '../../../src/render3/interfaces/view';
|
||||
import {LView, LViewFlags, RENDERER, RENDERER_FACTORY, TView} from '../../../src/render3/interfaces/view';
|
||||
import {insertView} from '../../../src/render3/node_manipulation';
|
||||
|
||||
import {NoopRenderer, NoopRendererFactory, WebWorkerRenderNode} from './noop_renderer';
|
||||
|
@ -25,33 +25,63 @@ export function createAndRenderLView(
|
|||
export function setupRootViewWithEmbeddedViews(
|
||||
templateFn: ComponentTemplate<any>| null, decls: number, vars: number, noOfViews: number,
|
||||
embeddedViewContext: any = {}, consts: TAttributes[] | null = null): LView {
|
||||
return setupTestHarness(templateFn, decls, vars, noOfViews, embeddedViewContext, consts)
|
||||
.hostLView;
|
||||
}
|
||||
|
||||
export interface TestHarness {
|
||||
hostLView: LView;
|
||||
hostTView: TView;
|
||||
embeddedTView: TView;
|
||||
createEmbeddedLView(): LView;
|
||||
detectChanges(): void;
|
||||
}
|
||||
|
||||
export function setupTestHarness(
|
||||
templateFn: ComponentTemplate<any>| null, decls: number, vars: number, noOfViews: number,
|
||||
embeddedViewContext: any = {}, consts: TAttributes[] | null = null): TestHarness {
|
||||
// Create a root view with a container
|
||||
const rootTView = createTView(-1, null, 1, 0, null, null, null, null, consts);
|
||||
const tContainerNode = getOrCreateTNode(rootTView, null, 0, TNodeType.Container, null, null);
|
||||
const rootLView = createLView(
|
||||
null, rootTView, {}, LViewFlags.CheckAlways | LViewFlags.IsRoot, null, null,
|
||||
const hostTView = createTView(-1, null, 1, 0, null, null, null, null, consts);
|
||||
const tContainerNode = getOrCreateTNode(hostTView, null, 0, TNodeType.Container, null, null);
|
||||
const hostLView = createLView(
|
||||
null, hostTView, {}, LViewFlags.CheckAlways | LViewFlags.IsRoot, null, null,
|
||||
new NoopRendererFactory(), new NoopRenderer());
|
||||
const mockRNode = new WebWorkerRenderNode();
|
||||
const lContainer = createLContainer(
|
||||
mockRNode as RComment, rootLView, mockRNode as RComment, tContainerNode, true);
|
||||
addToViewTree(rootLView, lContainer);
|
||||
mockRNode as RComment, hostLView, mockRNode as RComment, tContainerNode, true);
|
||||
addToViewTree(hostLView, lContainer);
|
||||
// run in the host view in creation mode to initialize TNode structures (first template pass)
|
||||
renderView(hostLView, hostTView, null);
|
||||
|
||||
|
||||
// create test embedded views
|
||||
const embeddedTView = createTView(-1, templateFn, decls, vars, null, null, null, null, null);
|
||||
const viewTNode = createTNode(rootTView, null, TNodeType.View, -1, null, null) as TViewNode;
|
||||
const embeddedTView = createTView(-1, templateFn, decls, vars, null, null, null, null, consts);
|
||||
const viewTNode = createTNode(hostTView, null, TNodeType.View, -1, null, null) as TViewNode;
|
||||
const rendererFactory = hostLView[RENDERER_FACTORY];
|
||||
const renderer = hostLView[RENDERER];
|
||||
|
||||
function createEmbeddedLView(): LView {
|
||||
const embeddedLView = createLView(
|
||||
hostLView, embeddedTView, embeddedViewContext, LViewFlags.CheckAlways, null, viewTNode,
|
||||
rendererFactory, renderer);
|
||||
renderView(embeddedLView, embeddedTView, embeddedViewContext);
|
||||
return embeddedLView;
|
||||
}
|
||||
|
||||
function detectChanges(): void {
|
||||
refreshView(hostLView, hostTView, hostTView.template, embeddedViewContext);
|
||||
}
|
||||
|
||||
// create embedded views and add them to the container
|
||||
for (let i = 0; i < noOfViews; i++) {
|
||||
const embeddedLView = createLView(
|
||||
rootLView, embeddedTView, embeddedViewContext, LViewFlags.CheckAlways, null, viewTNode,
|
||||
new NoopRendererFactory(), new NoopRenderer());
|
||||
renderView(embeddedLView, embeddedTView, null);
|
||||
insertView(embeddedLView, lContainer, i);
|
||||
insertView(createEmbeddedLView(), lContainer, i);
|
||||
}
|
||||
|
||||
// run in the creation mode to set flags etc.
|
||||
renderView(rootLView, rootTView, null);
|
||||
|
||||
return rootLView;
|
||||
return {
|
||||
hostLView: hostLView,
|
||||
hostTView: hostTView,
|
||||
embeddedTView: embeddedTView,
|
||||
createEmbeddedLView: createEmbeddedLView,
|
||||
detectChanges: detectChanges,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue