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

Use weakref.proxy where parent=self. #2223

Merged
merged 3 commits into from
Jan 19, 2023
Merged

Use weakref.proxy where parent=self. #2223

merged 3 commits into from
Jan 19, 2023

Conversation

nbiederbeck
Copy link
Contributor

We dug a little to Fix #2218.

We found that the garbage collector of python does not clean up after tests have run. This seems to be the case because the tools specify parent=self, and when the tools are out of scope, somehow their children stay in memory and thus the references to the tools via the parent are still valid, which is why it cannot be garbage-collected.

We replaced parent=self with parent=weakref.proxy(self), which does not increment the reference counter. This makes it possible to be collected once the tools are out of scope.

We needed to fix a single test, where before we asserted that the parent of a children is the object itself, which is no longer valid, because it now is a Proxy.

These changes have two great outcomes: the total test time decreases in fact a little, and the total memory consumption is decreased more than 50% !

The root cause is probably in the configsystem, where we need the references to the parents. Changing this would likely fix the problem, and not just the symptoms.

The black line in the plot is this branch, the blue line is the current master.
mprof

Co-authored-by: Lukas Nickel lukas.nickel@tu-dortmund.de
Co-authored-by: Rune Dominik rune.dominik@tu-dortmund.de

Co-authored-by: Lukas Nickel <lukas.nickel@tu-dortmund.de>
Co-authored-by: Rune Dominik <rune.dominik@tu-dortmund.de>
@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@nbiederbeck nbiederbeck requested review from maxnoe and kosack and removed request for watsonjj and HealthyPear January 18, 2023 11:26
@maxnoe
Copy link
Member

maxnoe commented Jan 18, 2023

Nice!

Copy link
Member

@maxnoe maxnoe left a comment

Choose a reason for hiding this comment

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

Very good catch!

While I think it is the right thing to do, this needs a better usability. Can we somehow do this automatically in Component.__init__? E.g. do super().__init__(parent=weakref.proxy(parent)) ?

Any downside to this?

@nbiederbeck
Copy link
Contributor Author

Any downside to this?

didn't think of that, I will check if that works.

@nbiederbeck
Copy link
Contributor Author

nbiederbeck commented Jan 18, 2023

diff --git a/ctapipe/core/component.py b/ctapipe/core/component.py
index 09294c38..0525f57e 100644
--- a/ctapipe/core/component.py
+++ b/ctapipe/core/component.py
@@ -1,5 +1,6 @@
 """ Class to handle configuration for algorithms """
 import warnings
+import weakref
 from abc import ABCMeta
 from inspect import cleandoc, isabstract
 from logging import getLogger
@@ -155,6 +156,8 @@ class Component(Configurable, metaclass=AbstractConfigurableMeta):
         with warnings.catch_warnings():
             warnings.filterwarnings("error", message=".*Config option.*not recognized")
             try:
+                if parent is not None:
+                    parent = weakref.proxy(parent)
                 super().__init__(parent=parent, config=config, **kwargs)
             except UserWarning as e:
                 raise TraitError(e) from None

black: master, blue: this branch, red: only the changes (relative to master) in the diff above.
mprof-1

might be the better approach.

@nbiederbeck
Copy link
Contributor Author

what doesn't get proxied is when calling Reconstructor.read, because there we don't go via the __init__ but attach the parent via kwargs and setattr.

But I still like the two-line change much more and will implement it.

This will then fix the symptoms for quite some time, until we can fix the root cause.

@maxnoe
Copy link
Member

maxnoe commented Jan 18, 2023

@nbiederbeck Ok, but special-casing that only in Reconstructor.read is I think the much better solution and that method is already very "by hand" anyway

@nbiederbeck
Copy link
Contributor Author

@nbiederbeck Ok, but special-casing that only in Reconstructor.read is I think the much better solution and that method is already very "by hand" anyway

I didn't even want to special-case that, just leave it as is. Still has a great improvement vs. master

@nbiederbeck
Copy link
Contributor Author

Here are the changes from Component.__init__, additional including those in Reconstructor.read and using proxy in run_tool. As you can see, those additional changes don't make any difference.

I need to partially withdraw my earlier comment.

mprof

@nbiederbeck nbiederbeck force-pushed the weakref branch 2 times, most recently from 71c7e0f to f24bb1e Compare January 18, 2023 15:11
@maxnoe maxnoe added this to the v0.18.0 milestone Jan 18, 2023
maxnoe
maxnoe previously approved these changes Jan 18, 2023
@maxnoe
Copy link
Member

maxnoe commented Jan 18, 2023

Still, using weakref is the correct solution I think. So we should add it also to the Reconstructor.read method.

Fixes #2218, where the CI fails with OOM, by allowing python
to garbage-collect Tools after tests.

Co-authored-by: Lukas Nickel <lukas.nickel@tu-dortmund.de>
Co-authored-by: Rune Dominik <rune.dominik@tu-dortmund.de>
@nbiederbeck
Copy link
Contributor Author

Still, using weakref is the correct solution I think. So we should add it also to the Reconstructor.read method.

done

Copy link
Contributor

@kosack kosack left a comment

Choose a reason for hiding this comment

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

nice fix! This is much better than requiring component devs to understand that they need a weakref.

@maxnoe maxnoe merged commit 5d0504c into master Jan 19, 2023
@maxnoe maxnoe deleted the weakref branch January 19, 2023 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CI Tests failing with Exit Code 143
3 participants