feat(benchmarks): add static tree benchmark
This commit is contained in:
parent
4287f1716d
commit
eef4c22e87
@ -19,6 +19,13 @@ describe('tree benchmark perf', () => {
|
|||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should run for ng2 static', (done) => {
|
||||||
|
runTreeBenchmark({
|
||||||
|
id: 'deepTree.ng2.static',
|
||||||
|
url: 'all/benchmarks/src/tree/ng2_static/index.html',
|
||||||
|
}).then(done, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
it('should run for the baseline', (done) => {
|
it('should run for the baseline', (done) => {
|
||||||
runTreeBenchmark({
|
runTreeBenchmark({
|
||||||
id: 'deepTree.baseline',
|
id: 'deepTree.baseline',
|
||||||
|
@ -18,6 +18,12 @@ describe('tree benchmark spec', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work for ng2 static', () => {
|
||||||
|
testTreeBenchmark({
|
||||||
|
url: 'all/benchmarks/src/tree/ng2_static/index.html',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should work for the baseline', () => {
|
it('should work for the baseline', () => {
|
||||||
testTreeBenchmark({
|
testTreeBenchmark({
|
||||||
url: 'all/benchmarks/src/tree/baseline/index.html',
|
url: 'all/benchmarks/src/tree/baseline/index.html',
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h2>Params</h2>
|
|
||||||
<form>
|
|
||||||
<br>
|
|
||||||
Use Viewcache:
|
|
||||||
<label>
|
|
||||||
Yes<input type="radio" name="viewcache" placeholder="use viewcache" value="true" checked="checked">
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
No<input type="radio" name="viewcache" placeholder="use viewcache" value="false">
|
|
||||||
</label>
|
|
||||||
<br>
|
|
||||||
<button>Apply</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<h2>Angular2 static tree benchmark (depth 10)</h2>
|
|
||||||
<p>
|
|
||||||
<button id="ng2DestroyDom">destroyDom</button>
|
|
||||||
<button id="ng2CreateDom">createDom</button>
|
|
||||||
<button id="ng2UpdateDomProfile">profile updateDom</button>
|
|
||||||
<button id="ng2CreateDomProfile">profile createDom</button>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2>Baseline static tree benchmark (depth 10)</h2>
|
|
||||||
<p>
|
|
||||||
<button id="baselineDestroyDom">destroyDom</button>
|
|
||||||
<button id="baselineCreateDom">createDom</button>
|
|
||||||
<button id="baselineUpdateDomProfile">profile updateDom</button>
|
|
||||||
<button id="baselineCreateDomProfile">profile createDom</button>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<app></app>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<baseline></baseline>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
$SCRIPTS$
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,325 +0,0 @@
|
|||||||
import {NgIf} from '@angular/common';
|
|
||||||
import {Component, NgModule} from '@angular/core';
|
|
||||||
import {ApplicationRef} from '@angular/core/src/application_ref';
|
|
||||||
import {reflector} from '@angular/core/src/reflection/reflection';
|
|
||||||
import {ReflectionCapabilities} from '@angular/core/src/reflection/reflection_capabilities';
|
|
||||||
import {document, gc, window} from '@angular/facade/src/browser';
|
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
|
||||||
import {BrowserDomAdapter} from '@angular/platform-browser/src/browser/browser_adapter';
|
|
||||||
import {DOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
|
||||||
import {bindAction, getIntParameter, getStringParameter, windowProfile, windowProfileEnd} from '@angular/testing/src/benchmark_util';
|
|
||||||
|
|
||||||
function createBindings(): any[] {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupReflector() {
|
|
||||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAX_DEPTH = 10;
|
|
||||||
|
|
||||||
export function main() {
|
|
||||||
BrowserDomAdapter.makeCurrent();
|
|
||||||
|
|
||||||
setupReflector();
|
|
||||||
|
|
||||||
var app;
|
|
||||||
var appRef;
|
|
||||||
var baselineRootTreeComponent;
|
|
||||||
var count = 0;
|
|
||||||
|
|
||||||
function profile(create, destroy, name) {
|
|
||||||
return function() {
|
|
||||||
windowProfile(name + ' w GC');
|
|
||||||
var duration = 0;
|
|
||||||
var count = 0;
|
|
||||||
while (count++ < 150) {
|
|
||||||
gc();
|
|
||||||
var start = window.performance.now();
|
|
||||||
create();
|
|
||||||
duration += window.performance.now() - start;
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
windowProfileEnd(name + ' w GC');
|
|
||||||
window.console.log(`Iterations: ${count}; time: ${duration / count} ms / iteration`);
|
|
||||||
|
|
||||||
windowProfile(name + ' w/o GC');
|
|
||||||
duration = 0;
|
|
||||||
count = 0;
|
|
||||||
while (count++ < 150) {
|
|
||||||
var start = window.performance.now();
|
|
||||||
create();
|
|
||||||
duration += window.performance.now() - start;
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
windowProfileEnd(name + ' w/o GC');
|
|
||||||
window.console.log(`Iterations: ${count}; time: ${duration / count} ms / iteration`);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function noop() {}
|
|
||||||
|
|
||||||
function createData(): TreeNode {
|
|
||||||
var values = count++ % 2 == 0 ? ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*'] :
|
|
||||||
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', '-'];
|
|
||||||
return buildTree(MAX_DEPTH, values, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ng2DestroyDom() {
|
|
||||||
app.initData = null;
|
|
||||||
appRef.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
function ng2CreateDom() {
|
|
||||||
app.initData = createData();
|
|
||||||
appRef.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [BrowserModule],
|
|
||||||
bootstrap: [AppComponentWithStaticTree],
|
|
||||||
providers: createBindings()
|
|
||||||
})
|
|
||||||
class AppModule {
|
|
||||||
}
|
|
||||||
|
|
||||||
function initNg2() {
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule).then((ref) => {
|
|
||||||
var injector = ref.injector;
|
|
||||||
appRef = injector.get(ApplicationRef);
|
|
||||||
|
|
||||||
app = ref.instance;
|
|
||||||
bindAction('#ng2DestroyDom', ng2DestroyDom);
|
|
||||||
bindAction('#ng2CreateDom', ng2CreateDom);
|
|
||||||
bindAction('#ng2UpdateDomProfile', profile(ng2CreateDom, noop, 'ng2-update'));
|
|
||||||
bindAction('#ng2CreateDomProfile', profile(ng2CreateDom, ng2DestroyDom, 'ng2-create'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function baselineDestroyDom() { baselineRootTreeComponent.update(null); }
|
|
||||||
|
|
||||||
function baselineCreateDom() { baselineRootTreeComponent.update(createData()); }
|
|
||||||
|
|
||||||
function initBaseline() {
|
|
||||||
var tree = DOM.createElement('tree');
|
|
||||||
DOM.appendChild(DOM.querySelector(document, 'baseline'), tree);
|
|
||||||
baselineRootTreeComponent = new BaselineAppComponent(tree, MAX_DEPTH);
|
|
||||||
|
|
||||||
bindAction('#baselineDestroyDom', baselineDestroyDom);
|
|
||||||
bindAction('#baselineCreateDom', baselineCreateDom);
|
|
||||||
|
|
||||||
bindAction('#baselineUpdateDomProfile', profile(baselineCreateDom, noop, 'baseline-update'));
|
|
||||||
bindAction(
|
|
||||||
'#baselineCreateDomProfile',
|
|
||||||
profile(baselineCreateDom, baselineDestroyDom, 'baseline-create'));
|
|
||||||
}
|
|
||||||
|
|
||||||
initNg2();
|
|
||||||
initBaseline();
|
|
||||||
}
|
|
||||||
|
|
||||||
class TreeNode {
|
|
||||||
value: string;
|
|
||||||
left: TreeNode;
|
|
||||||
right: TreeNode;
|
|
||||||
constructor(value, left, right) {
|
|
||||||
this.value = value;
|
|
||||||
this.left = left;
|
|
||||||
this.right = right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildTree(maxDepth, values, curDepth) {
|
|
||||||
if (maxDepth === curDepth) return new TreeNode('', null, null);
|
|
||||||
return new TreeNode(
|
|
||||||
values[curDepth], buildTree(maxDepth, values, curDepth + 1),
|
|
||||||
buildTree(maxDepth, values, curDepth + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://jsperf.com/nextsibling-vs-childnodes
|
|
||||||
|
|
||||||
class BaselineAppComponent {
|
|
||||||
tree: BaseLineTreeComponent = null;
|
|
||||||
constructor(public element, public depth: number) {}
|
|
||||||
update(value: TreeNode) {
|
|
||||||
if (value === null) {
|
|
||||||
this.tree = null;
|
|
||||||
DOM.clearNodes(this.element);
|
|
||||||
} else {
|
|
||||||
if (this.tree === null) {
|
|
||||||
this.tree = new BaseLineTreeComponent(this.element, this.depth);
|
|
||||||
}
|
|
||||||
this.tree.update(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var BASELINE_TREE_TEMPLATE = null;
|
|
||||||
class BaseLineTreeComponent {
|
|
||||||
static getTemplate() {
|
|
||||||
if (BASELINE_TREE_TEMPLATE === null) {
|
|
||||||
BASELINE_TREE_TEMPLATE = DOM.createTemplate('<span>_<tree></tree><tree></tree></span>');
|
|
||||||
}
|
|
||||||
return BASELINE_TREE_TEMPLATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
value: BaseLineInterpolation;
|
|
||||||
left: BaseLineTreeComponent;
|
|
||||||
right: BaseLineTreeComponent;
|
|
||||||
terminal: boolean;
|
|
||||||
|
|
||||||
constructor(public element, remainingDepth: number) {
|
|
||||||
var clone = DOM.firstChild(DOM.importIntoDoc(BaseLineTreeComponent.getTemplate().content));
|
|
||||||
DOM.appendChild(this.element, clone);
|
|
||||||
var child = clone.firstChild;
|
|
||||||
this.value = new BaseLineInterpolation(child);
|
|
||||||
this.terminal = remainingDepth === 0;
|
|
||||||
if (!this.terminal) {
|
|
||||||
child = DOM.nextSibling(child);
|
|
||||||
this.left = new BaseLineTreeComponent(child, remainingDepth - 1);
|
|
||||||
child = DOM.nextSibling(child);
|
|
||||||
this.right = new BaseLineTreeComponent(child, remainingDepth - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
update(value: TreeNode) {
|
|
||||||
this.value.update(value.value);
|
|
||||||
if (!this.terminal) {
|
|
||||||
this.left.update(value.left);
|
|
||||||
this.right.update(value.right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BaseLineInterpolation {
|
|
||||||
value: string;
|
|
||||||
textNode;
|
|
||||||
constructor(textNode) {
|
|
||||||
this.value = null;
|
|
||||||
this.textNode = textNode;
|
|
||||||
}
|
|
||||||
update(value: string) {
|
|
||||||
if (this.value !== value) {
|
|
||||||
this.value = value;
|
|
||||||
DOM.setText(this.textNode, value + ' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StaticTreeComponentBase {
|
|
||||||
_value: TreeNode;
|
|
||||||
constructor() { this.data = null; }
|
|
||||||
set data(value: TreeNode) {
|
|
||||||
// TODO: We need an initial value as otherwise the getter for data.value will fail
|
|
||||||
// --> this should be already caught in change detection!
|
|
||||||
value = value !== null ? value : new TreeNode('', null, null);
|
|
||||||
this._value = value;
|
|
||||||
}
|
|
||||||
get data() { return this._value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component(
|
|
||||||
{selector: 'tree', inputs: ['data'], directives: [], template: '<span>{{data.value}} </span>'})
|
|
||||||
class StaticTreeComponent0 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent0],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent1 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent1],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent2 extends StaticTreeComponentBase {
|
|
||||||
data: TreeNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent2],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent3 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent3],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent4 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent4],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent5 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent5],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent6 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent6],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent7 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent7],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent8 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'tree',
|
|
||||||
inputs: ['data'],
|
|
||||||
directives: [StaticTreeComponent8],
|
|
||||||
template:
|
|
||||||
`<span> {{data.value}} <tree [data]='data.right'></tree><tree [data]='data.left'></tree></span>`
|
|
||||||
})
|
|
||||||
class StaticTreeComponent9 extends StaticTreeComponentBase {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app',
|
|
||||||
directives: [StaticTreeComponent9, NgIf],
|
|
||||||
template: `<tree *ngIf="initData != null" [data]='initData'></tree>`
|
|
||||||
})
|
|
||||||
class AppComponentWithStaticTree {
|
|
||||||
initData: TreeNode;
|
|
||||||
}
|
|
26
modules/benchmarks/src/tree/ng2_static/index.html
Normal file
26
modules/benchmarks/src/tree/ng2_static/index.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h2>Params</h2>
|
||||||
|
<form>
|
||||||
|
Depth:
|
||||||
|
<input type="number" name="depth" placeholder="depth" value="9">
|
||||||
|
<br>
|
||||||
|
<button>Apply</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2>Angular2 tree benchmark</h2>
|
||||||
|
<p>
|
||||||
|
<button id="destroyDom">destroyDom</button>
|
||||||
|
<button id="createDom">createDom</button>
|
||||||
|
<button id="updateDomProfile">profile updateDom</button>
|
||||||
|
<button id="createDomProfile">profile createDom</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<tree id="root"></tree>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="../../bootstrap_ng2.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
40
modules/benchmarks/src/tree/ng2_static/index.ts
Normal file
40
modules/benchmarks/src/tree/ng2_static/index.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import {ApplicationRef, NgModule, enableProdMode} from '@angular/core';
|
||||||
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import {bindAction, profile} from '../../util';
|
||||||
|
import {TreeNode, buildTree, emptyTree} from '../util';
|
||||||
|
|
||||||
|
import {AppModule, RootTreeComponent} from './tree';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
var tree: RootTreeComponent;
|
||||||
|
var appRef: ApplicationRef;
|
||||||
|
|
||||||
|
function destroyDom() {
|
||||||
|
tree.data = emptyTree;
|
||||||
|
appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDom() {
|
||||||
|
tree.data = buildTree();
|
||||||
|
appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function noop() {}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
enableProdMode();
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule).then((ref) => {
|
||||||
|
const injector = ref.injector;
|
||||||
|
appRef = injector.get(ApplicationRef);
|
||||||
|
|
||||||
|
tree = appRef.components[0].instance;
|
||||||
|
bindAction('#destroyDom', destroyDom);
|
||||||
|
bindAction('#createDom', createDom);
|
||||||
|
bindAction('#updateDomProfile', profile(createDom, noop, 'update'));
|
||||||
|
bindAction('#createDomProfile', profile(createDom, destroyDom, 'create'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
40
modules/benchmarks/src/tree/ng2_static/tree.ts
Normal file
40
modules/benchmarks/src/tree/ng2_static/tree.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import {Component, Input, NgModule} from '@angular/core';
|
||||||
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import {TreeNode, emptyTree, maxDepth} from '../util';
|
||||||
|
|
||||||
|
function createTreeComponent(level: number, isLeaf: boolean) {
|
||||||
|
const nextTreeEl = `tree${level+1}`;
|
||||||
|
const template = isLeaf ?
|
||||||
|
`<span> {{data.value}} </span>` :
|
||||||
|
`<span> {{data.value}} <span><${nextTreeEl} [data]='data.right'></${nextTreeEl}></span><span><${nextTreeEl} [data]='data.left'></${nextTreeEl}></span></span>`;
|
||||||
|
|
||||||
|
@Component({selector: `tree${level}`, template: template})
|
||||||
|
class TreeComponent {
|
||||||
|
@Input()
|
||||||
|
data: TreeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TreeComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'tree', template: `<tree0 *ngIf="data.left != null" [data]='data'></tree0>`})
|
||||||
|
export class RootTreeComponent {
|
||||||
|
@Input()
|
||||||
|
data: TreeNode = emptyTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createModule(): any {
|
||||||
|
const components: any[] = [RootTreeComponent];
|
||||||
|
for (var i = 0; i <= maxDepth; i++) {
|
||||||
|
components.push(createTreeComponent(i, i === maxDepth));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({imports: [BrowserModule], bootstrap: [RootTreeComponent], declarations: [components]})
|
||||||
|
class AppModule {
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AppModule = createModule();
|
@ -5,7 +5,7 @@ export class TreeNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let treeCreateCount: number;
|
let treeCreateCount: number;
|
||||||
let maxDepth: number;
|
export let maxDepth: number;
|
||||||
let numberData: string[];
|
let numberData: string[];
|
||||||
let charData: string[];
|
let charData: string[];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user