Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce Dynamo ViewModel memory leak Part I #9993

Merged
merged 22 commits into from
Oct 22, 2019
Merged

Conversation

QilongTang
Copy link
Contributor

@QilongTang QilongTang commented Sep 20, 2019

Please Note:

  1. Before submitting the PR, please review How to Contribute to Dynamo
  2. Dynamo Team will meet 1x a month to review PRs found on Github (Issues will be handled separately)
  3. PRs will be reviewed from oldest to newest
  4. If a reviewed PR requires changes by the owner, the owner of the PR has 30 days to respond. If the PR has seen no activity by the next session, it will be either closed by the team or depending on its utility will be taken over by someone on the team
  5. PRs should use either Dynamo's default PR template or one of these other template options in order to be considered for review.
  6. PRs that do not have one of the Dynamo PR templates completely filled out with all declarations satisfied will not be reviewed by the Dynamo team.
  7. PRs made to the DynamoRevit repo will need to be cherry-picked into all the DynamoRevit Release branches that Dynamo supports. Contributors will be responsible for cherry-picking their reviewed commits to the other branches after a LGTM label is added to the PR.

Purpose

This PR is an example of things need to be done to dispose object in correct order to avoid memory leak.

  • PortViewModels are disposed correctly now
  • RunSettingsViewModel is disposed correctly now
  • InfoBubbleViewModels are disposed correctly now
  • HomeworkspaceViewModel are disposed correctly but still retained because of workspaceView leak on resource dictionary
  • WPF binding leak addressed. Notifications collection on notificationExtension are disposed correctly now
  • NodeCategoryViewModels are now disposed correctly
  • NodeSearchElementViewModels are now disposed correctly
  • DynamoViewModel no longer keeps a valid duplicate SearchViewModel now

The following is a comparison using our sample Geometry - Solids as file open candidate.

Baseline -> 2.4.0
Memory Consumption Difference between Dynamo StartUp-> File Open Once -> File Open 10x

image

File Open Once
image

File Open 10x
image

After -> Release build of this branch (2.5.0)
Memory Consumption Difference between Dynamo StartUp-> File Open Once -> File Open 10x

image

File Open Once
image

File Open 10x
image

Declarations

Check these if you believe they are true

  • The code base is in a better state after this PR
  • Is documented according to the standards
  • The level of testing this PR includes is appropriate
  • User facing strings, if any, are extracted into *.resx files
  • All tests pass using the self-service CI.
  • Snapshot of UI changes, if any.
  • Changes to the API follow Semantic Versioning, and are documented in the API Changes document.

Reviewers

@DynamoDS/dynamo

FYIs

/// </summary>
internal void Dispose()
{
this.workspaceViewModel = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the cases where this needs to be done in c# are small in number, why do we need to do it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe something here is preventing HomeworkspaceViewModel to be disposed, not sure if it is related to the readonly field or simply calling dispose, will give it another try tomorrow

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the retention paths you captured screenshots of it looks like the DynamoView is indirectly holding onto an instance of RunSettingsViewModel that is in turn holding onto the HomeWorkspaceViewModel. I think we should try and dispose off the HomeWorkspaceViewModel from DynamoView in that case, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe DynamoView is a singleton as well as the RunSettingsControl. So we won't be able to know when to dispose specifically from the view, but we can do that when closing the currentWorkspace. WorkspaceRemoved event will be triggered and then Dispose() on HomeWorkspaceModel will be called, that's why I added the logic there.

@QilongTang
Copy link
Contributor Author

Running Self CI, I think this PR is good for review. It does not address all the issues, but is a good step.

@QilongTang QilongTang changed the title Prevent Dynamo Workspace close memory leak Prevent Dynamo Workspace close memory leak Part I Sep 27, 2019
@@ -81,12 +81,12 @@ public RunTypeItem(RunType runType)
/// notifications as those notifications are raised when the value is set on the
/// model.
/// </summary>
public class RunSettingsViewModel : NotificationObject
public class RunSettingsViewModel : ViewModelBase
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is an API break.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or - could be, we need to be very careful changing the base class of a public class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we find out? ViewModelBase implements NotificationObject and IDisposal so I believe doing this will not remove any public property, that's actually why I thought it is not API breaking. Same reason below.

@@ -89,7 +89,7 @@ public interface ISearchEntryViewModel : INotifyPropertyChanged, IDisposable
ElementTypes ElementType { get; }
}

public class NodeCategoryViewModel : NotificationObject, ISearchEntryViewModel
public class NodeCategoryViewModel : ViewModelBase, ISearchEntryViewModel
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here. can this be accomplished without changing the base class by just adding more interfaces?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can check this doc:
https://stackoverflow.com/questions/1456785/a-definitive-guide-to-api-breaking-changes-in-net

and do some thought experiments or real experiments with extensions using that class before and after.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public abstract class ViewModelBase : NotificationObject,IDisposable I dont think switching out the baseclass here break API backward compatibility because it only adds two APIs

IsDebugBuild

and

Dispose

@QilongTang
Copy link
Contributor Author

Updated screenshots and could be more useful for our discussion

public ObservableCollection<Logging.NotificationMessage> Notifications { get; private set; }

private ObservableCollection<Logging.NotificationMessage> notifications;
public ObservableCollection<Logging.NotificationMessage> Notifications
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this is kind of argg - we need to implement INotifyPropertyChanged to have .net gc this collection?

Can we add a comment saying as much so that in a year we don't delete it all when we see it is unused 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only because the collection is binding to WPF UI, I can add comments

@QilongTang
Copy link
Contributor Author

All Unit tests passing, Ready for review

@QilongTang QilongTang changed the title Prevent Dynamo Workspace close memory leak Part I Reduce Dynamo ViewModel memory leak Part I Oct 21, 2019
@mjkkirschner
Copy link
Member

LGTM

@mjkkirschner mjkkirschner added the LGTM Looks good to me label Oct 22, 2019
@QilongTang QilongTang merged commit 1ad9596 into master Oct 22, 2019
@QilongTang QilongTang deleted the DynamoMemoryLeak branch October 22, 2019 17:29
@QilongTang QilongTang mentioned this pull request Feb 12, 2020
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LGTM Looks good to me
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants