From 7a280b1a21c3919d55d1680a963cc7f8939584aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=A1ko=20Hevery?= Date: Fri, 25 Oct 2019 13:55:43 -0700 Subject: [PATCH] test(ivy): clean up class_binding perf tests for readability (#33413) PR Close #33413 --- .../test/render3/perf/class_binding/index.ts | 318 +++++++++++------- .../core/test/render3/perf/micro_bench.ts | 2 +- 2 files changed, 191 insertions(+), 129 deletions(-) diff --git a/packages/core/test/render3/perf/class_binding/index.ts b/packages/core/test/render3/perf/class_binding/index.ts index c2293deb85d5f..f3a0edb4e3245 100644 --- a/packages/core/test/render3/perf/class_binding/index.ts +++ b/packages/core/test/render3/perf/class_binding/index.ts @@ -7,159 +7,221 @@ */ 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 {Benchmark, createBenchmark} from '../micro_bench'; import {setupTestHarness} from '../setup'; +const PROFILE_CREATE = true; +const PROFILE_UPDATE = true; +const PROFILE_NOOP = true; + + +function benchmark( + name: string, template: ComponentTemplate, baselineTemplate: ComponentTemplate) { + const ivyHarness = setupTestHarness(template, 1, 1, 1000, context, consts); + const baseHarness = setupTestHarness(baselineTemplate, 1, 1, 1000, context, consts); + + if (PROFILE_CREATE) { + const benchmark = createBenchmark('class binding[create]: ' + name); + benchmarks.push(benchmark); + const ivyProfile = benchmark('styling'); + console.profile(benchmark.name + ':' + ivyProfile.name); + while (ivyProfile()) { + ivyHarness.createEmbeddedLView(); + } + console.profileEnd(); + + const baseProfile = benchmark('base'); + console.profile(benchmark.name + ':' + baseProfile.name); + while (baseProfile()) { + baseHarness.createEmbeddedLView(); + } + console.profileEnd(); + } + + if (PROFILE_UPDATE) { + const benchmark = createBenchmark('class binding[update]: ' + name); + benchmarks.push(benchmark); + const ivyProfile = benchmark('styling'); + console.profile(benchmark.name + ':' + ivyProfile.name); + while (ivyProfile()) { + toggle = !toggle; + ivyHarness.detectChanges(); + } + console.profileEnd(); + + const baseProfile = benchmark('base'); + console.profile(benchmark.name + ':' + baseProfile.name); + while (baseProfile()) { + toggle = !toggle; + baseHarness.detectChanges(); + } + console.profileEnd(); + } + + + if (PROFILE_NOOP) { + const benchmark = createBenchmark('class binding[noop]: ' + name); + benchmarks.push(benchmark); + const ivyProfile = benchmark('styling'); + console.profile(benchmark.name + ':' + ivyProfile.name); + while (ivyProfile()) { + ivyHarness.detectChanges(); + } + console.profileEnd(); + + const baseProfile = benchmark('base'); + console.profile(benchmark.name + ':' + baseProfile.name); + while (baseProfile()) { + baseHarness.detectChanges(); + } + console.profileEnd(); + } +} -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 A_1 = 'one'; +const B_1 = A_1.toUpperCase(); +const A_10 = 'one two three four five six seven eight nine ten'; +const B_10 = A_10.toUpperCase(); +let toggle = 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) { - 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(); -} - -`
`; -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); - } -}); - - -`
`; -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); - } -}); - - -`
`; -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); - } -}); +const benchmarks: Benchmark[] = []; +benchmark( + `
`, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div', 0); + } + }, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div', 1); + } + }); -`
`; -benchmark(`class="A B"`, function(rf: RenderFlags, ctx: any) { - if (rf & 1) { - ɵɵelement(0, 'div', 0); - } - if (rf & 2) { - } -}); +benchmark( + `
`, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div'); + } + if (rf & 2) { + ɵɵclassMap(toggle ? A_1 : B_1); + } + }, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div'); + } + if (rf & 2) { + ɵɵproperty('className', toggle ? A_1 : B_1); + } + }); -`
`; -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); - } -}); +benchmark( + `
`, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div'); + } + if (rf & 2) { + ɵɵclassMap(toggle ? A_10 : B_10); + } + }, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div'); + } + if (rf & 2) { + ɵɵproperty('className', toggle ? A_10 : B_10); + } + }); +benchmark( + `
`, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div'); + } + if (rf & 2) { + ɵɵclassMap(toggle ? A_1 : B_1); + } + }, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div'); + } + if (rf & 2) { + ɵɵproperty('className', toggle ? A_1 : B_1); + } + }); -`
`; -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); - } -}); - -`
`; -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); - } -}); +benchmark( + `
`, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div', 0); + } + if (rf & 2) { + ɵɵclassMap(toggle ? A_1 : B_1); + } + }, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div', 1); + } + if (rf & 2) { + ɵɵproperty('className', toggle ? A_1 : B_1); + } + }); -`
`; benchmark( - `class="A B" [class]="CLASSES_10" [class.foo]="exp"`, function(rf: RenderFlags, ctx: any) { + `
`, + 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); + ɵɵclassMap(toggle ? A_10 : B_10); + } + }, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div', 1); + } + if (rf & 2) { + ɵɵproperty('className', toggle ? A_10 : B_10); } }); +benchmark( + `
`, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div', 0); + } + if (rf & 2) { + ɵɵclassMap(toggle ? A_1 : B_1); + ɵɵclassProp('foo', toggle); + } + }, + function(rf: RenderFlags, ctx: any) { + if (rf & 1) { + ɵɵelement(0, 'div', 1); + } + if (rf & 2) { + ɵɵproperty('className', toggle ? A_1 + 'foo' : B_1); + } + }); -`
`; -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(); \ No newline at end of file +benchmarks.forEach(b => b.report()); diff --git a/packages/core/test/render3/perf/micro_bench.ts b/packages/core/test/render3/perf/micro_bench.ts index cc843e41f1e25..4bcb5d7ffc662 100644 --- a/packages/core/test/render3/perf/micro_bench.ts +++ b/packages/core/test/render3/perf/micro_bench.ts @@ -43,7 +43,7 @@ export function createBenchmark(benchmarkName: string): Benchmark { iterationCounter = profile.iterationCount; runAgain = true; // tslint:disable-next-line:no-console - console.log(profileName, '...'); + console.log(benchmarkName, profileName, '...'); } else { profile.sampleCount++; // we came to an end of a sample, compute the time.