I noticed that my Angular 2 app gets painfully slow after a while of usage.
I profiled the CPU time and found out that there are massive change detection executions going on.
CPU profile right after page load ...
... compared to the CPU profile after using the page for a while.
I used a lot of EventEmitter
in different services to communicate between a lot of components.
After testing a while it seems that the emitter for the window scroll event causes a big part of the heavy load.
The CPU profile after using the page for a while without emitting scroll events:
Here the implementation of the service:
@Injectable()
export class WindowService {
@Output() scrolled$: EventEmitter<WindowScrolled> = new EventEmitter();
private scrollDebounceTime = 25;
constructor() {
this.addEvent(window, 'scroll', this.debounce((event) => {
this.scrolled$.emit(new WindowScrolled(window.scrollX, window.scrollY));
}, this.scrollDebounceTime));
}
// ... other functions
}
EventEmitter
wrong, how do I use it correctly?In addition I post the grid tree component, because the changes might be caused by the recursive tree structure my components build.
@Component({
selector: 'hierarchy-grid-tree',
moduleId: __moduleName, // use `__moduleName` from System.js for relative styleUrls and templateUrls
styleUrls : [`hierarchy-grid.css`],
template: `<div class="flex-container">
<div class="flex-item" *ngFor="#node of nodes; #i = index" [ngClass]="{'intermediate': node.has()}" [ngStyle]="{'flex-grow': flexGrow(node), 'flex-basis': visRepConf.nodeWidth+'px', 'order': (i+1)}">
<hierarchy-node [node]="node" [visRepConf]="visRepConf" #hnInstance></hierarchy-node>
<hierarchy-grid-tree [nodes]="node.children()" [visRepConf]="visRepConf" [show-depth]="showDepth" [curr-depth]="currDepth + 1" *ngIf="(showDepth === -1 || currDepth < depth) && node.has() && !hnInstance.isCollapsed"></hierarchy-grid-tree>
</div>
</div>`,
providers: [],
directives: [HierarchyGridTreeComponent, HierarchyNodeComponent]
})
export class HierarchyGridTreeComponent {
@Input() nodes: Array<Node> = [];
@Input() visRepConf:VisRepresentationConfig;
@Input('show-depth') showDepth = -1;
@Input('curr-depth') currDepth = 1;
constructor() {
}
flexGrow(node) {
if(node.has()) {
return node.numChildrenRecursive();
}
return 'auto';
}
}
// see html demo at http://codepen.io/anon/pen/pgqjPP
@Component({
selector: 'hierarchy-grid',
moduleId: __moduleName, // use `__moduleName` from System.js for relative styleUrls and templateUrls
styleUrls : [`hierarchy-grid.css`],
template: `<div class="color-{{color}}" [ngClass]="{'selects-infra':selectsInfra}" (click)="selectInfra($event)">
<p *ngIf="showInfraTitle" class="title">{{title}}</p>
<hierarchy-node *ngIf="external" [node]="external" [visRepConf]="visRepConf"></hierarchy-node>
<hierarchy-grid-tree [nodes]="nodes" [visRepConf]="visRepConf"></hierarchy-grid-tree>
</div>`,
providers: [],
directives: [HierarchyGridTreeComponent, HierarchyNodeComponent]
})
export class HierarchyGridComponent implements OnInit, OnChanges {
@Input('vis-config') visConfig:string = '';
@Input('infra') infra:Infrastructure;
@Input('show-external') showExternal:boolean = false;
@Input('show-infra-title') showInfraTitle:boolean = false;
@Input('selects-infra') selectsInfra:boolean = false;
private visRepConf:VisRepresentationConfig;
private external:ExternalNode;
private nodes:Array<Node>;
private color:string;
private title:string;
constructor(private nodeSelection:NodeSelectionService) {
}
ngOnChanges(changes) {
if(changes.infra !== undefined && this.infra !== undefined) {
this.visRepConf = this.infra.visConfig.get(this.visConfig);
this.nodes = [this.infra.root];
if(this.showExternal) {
this.external = this.infra.external;
}
this.color = this.infra.color;
this.title = this.infra.name;
}
}
selectInfra($event) {
if(this.selectsInfra) {
this.nodeSelection.infra = this.infra;
}
}
}
The resulting hierarchy grid:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With