Components: 100% reproducible memory leak

Created on 26 Mar 2018  路  8Comments  路  Source: angular/components

Bug, feature request, or proposal:

Bug

What is the expected behavior?

What is the current behavior?

Any overlay control (menu, popup) if opened and closed enough times affects the performance of all the input boxes. As funny as it seems, it does!

What are the steps to reproduce?

Try material's website: https://material.angular.io

  1. Navigate to the "Form Controls -> Input" to load the input page
  2. Navigate to "Navigation -> Menu"
  3. Open and close the menu 150 times or more by clicking on the "Menu" button.
  4. Navigate to the "Form Controls -> Input". (to see the issue better, try to repeat steps 2 to 4)
    5- Try to type quickly in any of the input boxes and you will see it's typing slowly. Try to delete the text by holding the backspace key and you will see it's lagging.

What is the use-case or motivation for changing an existing behavior? We are building a software that will be running for the entire day. Obviously the menus will open for more than 150 times. So it's not a dramatic number. After a lot of investigation on why it's slowing down, we realized that it's the menu causing that. We tried it on material's own website and we were able to replicate the issue

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

The latest stable version: 5.2.4
We even tried on 6.0.0-beta.4

Is there anything else we should know?

P3 has pr

Most helpful comment

It looks like the leak might be because of leaked rxjs subscription in CdkConnectedOverlay._createOverlay() method (which is called every time you open a modal/menu):
https://github.com/angular/components/blob/e512581a81aee546a23aa003898399a5068769b8/src/cdk/overlay/overlay-directives.ts#L284

I've checked the code of OverlayRef class and found that there are 2 streams involved - one is inner subject that is used to dispatch events from services (like OverlayKeyboardDispatcher) and another outer observable that subscribes internally to that subject and forwards events further:

https://github.com/angular/components/blob/ee96e05e8251aa0b9757c4002119d0fccaba9057/src/cdk/overlay/overlay-ref.ts#L48-L57

The problem with this is that those 2 observables are not connected and so despite the fact that inner subject is completed (cleaned up) in OverlayRef.dispose() method it's outer counterpart will remain subscribed and thus causing potential memory leaks.

_NOTE:_ This was discovered by the streaming dude in his video course on CDK Overlays (it's just to give him credit).

All 8 comments

I managed to reproduce something similar on the docs site where it looks like there's a keydown event that is leaking somewhere, however I wasn't able to reproduce the same against master. This sounds very similar to https://github.com/angular/material2/pull/10160, although the PR should've landed in 5.2.4 which is deployed on the docs site.

@crisbeto Although #10160 was tagged with 5.2.4, it seems like it isn't actually in the 5.2.4 release.

I made a quick stackblitz to check it out which just prints out the 5.2.4 OverlayKeyboardDispatcher.ngOnDestroy() method here, which should have been changed as part of that PR (link)

Can be related to : https://stackblitz.com/edit/issue-error-message ?

For one input with formControlName, at the first load i enter 4 times in the getErrorMessage function, and 6 times, each time i open or close the mat-accordion. All this, multiplied by the number of formControlName inside my HTML...

It's seem independant from the number of validators (eg : Validators.required in TS or required in HTML).

Perhaps it's can be a performance issue, but if it's not linked to #10573 i will open another issue :+1:

I'm using Augury to look at the component graph. So the menu is a child component. I see that every time the menu opens/shows, it creates a new object in the graph.
How about fixing that?

angular v: 6.0.4
material v: 6.2.1

will there be any update on this issue, this is impacting applications developed using angular material, we are hit with a bad performance, the components not getting destroyed on route change.

Looks like mat-form-field is causing the memory issue, and checking the form-field.ts I dont see how the components get destructed.

It looks like the leak might be because of leaked rxjs subscription in CdkConnectedOverlay._createOverlay() method (which is called every time you open a modal/menu):
https://github.com/angular/components/blob/e512581a81aee546a23aa003898399a5068769b8/src/cdk/overlay/overlay-directives.ts#L284

I've checked the code of OverlayRef class and found that there are 2 streams involved - one is inner subject that is used to dispatch events from services (like OverlayKeyboardDispatcher) and another outer observable that subscribes internally to that subject and forwards events further:

https://github.com/angular/components/blob/ee96e05e8251aa0b9757c4002119d0fccaba9057/src/cdk/overlay/overlay-ref.ts#L48-L57

The problem with this is that those 2 observables are not connected and so despite the fact that inner subject is completed (cleaned up) in OverlayRef.dispose() method it's outer counterpart will remain subscribed and thus causing potential memory leaks.

_NOTE:_ This was discovered by the streaming dude in his video course on CDK Overlays (it's just to give him credit).

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Miiekeee picture Miiekeee  路  3Comments

shlomiassaf picture shlomiassaf  路  3Comments

vitaly-t picture vitaly-t  路  3Comments

kara picture kara  路  3Comments

3mp3ri0r picture 3mp3ri0r  路  3Comments