Ngx-charts: perf: run logic outside ngZone

Created on 6 Aug 2018  路  5Comments  路  Source: swimlane/ngx-charts

I'm submitting a ... (check one with "x")

  • [x] bug report - search github for a similar issue or PR before submitting
  • [ ] feature request
  • [ ] support request - use StackOverflow (add the ngx-charts tag) or the gitter chat for support questions

Current behavior
The mouseOver event runs inside the ngZone, which leads to hundreds of Angular check which impacts performance.

Expected behavior
Some events must run outside the ngZone, only template changes should run inside the ngZone.

Reproduction of the problem
https://stackblitz.com/edit/angular-ks78z1?file=src%2Fapp%2Fapp.component.html

What is the motivation / use case for changing the behavior?
Perf matters.

  • ngx-charts version: 9.0.0

  • Angular version: 6.1.1

  • Browser: N/A

  • Language: N/A

Most helpful comment

The event is not the problem, the problem is that it runs in the zone.
One solution could be to register the event with regular js:

private showToolTip = false;

constructor(
  private ngZone: NgZone
) { }

myFunction(){
  ngZone.runOutsideAngular(() => {
      node.addEventListener('mouseover', () => {
        // compute the new state of the tooltip
        let new_showToolTip = ...
        // detect if the state changes
        if(new_showToolTip != this.showToolTip ){
          // if it does, run inside ngZone, this will trigger change detection
          ngZone.run(() => {
            this.showToolTip = new_showToolTip;
          })
        } // if not, it will not trigger change detection
      })
  })
}

I don't think there is a memory impact since no additional variables are used.

Even though the computation is a tiny bit more heavy, in the end you skip hundreds of change detection cycles.

All 5 comments

The mouseOver event is needed for the tooltip. Any idea how to make that work without a mouseOver event?

The event is not the problem, the problem is that it runs in the zone.
One solution could be to register the event with regular js:

private showToolTip = false;

constructor(
  private ngZone: NgZone
) { }

myFunction(){
  ngZone.runOutsideAngular(() => {
      node.addEventListener('mouseover', () => {
        // compute the new state of the tooltip
        let new_showToolTip = ...
        // detect if the state changes
        if(new_showToolTip != this.showToolTip ){
          // if it does, run inside ngZone, this will trigger change detection
          ngZone.run(() => {
            this.showToolTip = new_showToolTip;
          })
        } // if not, it will not trigger change detection
      })
  })
}

I don't think there is a memory impact since no additional variables are used.

Even though the computation is a tiny bit more heavy, in the end you skip hundreds of change detection cycles.

@marjan-georgiev Tell me if you need more information!

up

@Ploppy3 @4ctarus https://github.com/swimlane/ngx-charts/issues/1162#issuecomment-510093587

workaround -- I'll be making a pull request from ngx-charts-extra later this month, need to further test possible side-effects as it's a major change.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

merinshaji picture merinshaji  路  3Comments

tobigit picture tobigit  路  4Comments

ianfdk picture ianfdk  路  3Comments

Hypercubed picture Hypercubed  路  3Comments

amcdnl picture amcdnl  路  4Comments