-
Notifications
You must be signed in to change notification settings - Fork 747
Deleted dotnet object does not get garbage collected #1872
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
Comments
You are not calling .NET GC |
@lostmsu I get the same results if I add Full code for reference: import gc
import clr
import psutil
import matplotlib.pyplot as plt
import System
# Create dict store count of objects left
types = [
str,
System.String,
]
types = {obj: 0 for obj in types}
N = 1_000
str_size = 1_000_000
memory_py = [0 for _ in range(N + 2)]
memory_py[0] = psutil.virtual_memory().used
for ii in range(N):
s_py = str('a' * str_size)
del s_py
memory_py[ii + 1] = psutil.virtual_memory().used - memory_py[0]
gc.collect()
System.GC.Collect()
# See what types of objects are still present
for obj in gc.get_objects():
if type(obj) in list(types.keys()):
types[type(obj)] += 1
print(types)
memory_py[ii + 2] = psutil.virtual_memory().used - memory_py[0]
memory_py[0] = 0
memory_net = [0 for _ in range(N + 2)]
memory_net[0] = psutil.virtual_memory().used
s_py = str('a' * str_size)
for ii in range(N):
s_net = System.String(s_py)
del s_net
memory_net[ii + 1] = psutil.virtual_memory().used - memory_net[0]
gc.collect()
System.GC.Collect()
# See what types of objects are still present
for obj in gc.get_objects():
if type(obj) in list(types.keys()):
types[type(obj)] += 1
print(types)
memory_net[ii + 2] = psutil.virtual_memory().used - memory_net[0]
memory_net[0] = 0
|
Hmm, this tells us that Python is not releasing the wrapper objects for some reason. Can you check the refcount and referrers for these? |
I used objgraph to display the backrefs. The output of import gc
import sys
import clr
import objgraph
import System
s_net = System.String('a')
del s_net
gc.collect()
System.GC.Collect()
for obj in gc.get_objects():
if type(obj) == System.String:
print(f'Refcount: {sys.getrefcount(obj)}')
print(f'Num Referrers: {len(gc.get_referrers(obj))}')
objgraph.show_backrefs(obj, filename='backref.png')
|
@filmor an update from my debugging the issue: From this code I am getting a refcount import ctypes
from System import Uri
u = Uri('http://google.com')
addr = id(u)
rc = ctypes.c_long.from_address(addr).value
del u
# tp_dealloc not called Replacing The issue does not seem to happen when objects are created from .NET. E.g. this does not produce extra references: var uri = new Uri("http://google.com").ToPython();
// uri.Refcount == 1
uri.Dispose();
// `tp_dealloc` called Looks like we leak references when constructing new .NET objects from Python. |
Looks good, the Thanks @lostmsu ! |
Environment
Details
Create dotnet-object and delete it. If I do that a lot I get memory issues. It seems the never get cleared by the Python- or dotnet-gc. This is not a problem in pythonnet 2.5.2
You can also visualize the memory consumption:
You can execute the same code with pythonnet 2.5.2 (Python 3.9.13) and get the following figure
The text was updated successfully, but these errors were encountered: