F
Frank Millman
Hi all
I don't know whether this will be of interest, but I have just carried
out an exercise that I found useful, so I thought I would share it.
I am writing a multi-user business app, with a multi-threaded server
program to handle client connections. The server should 'serve
forever'. Each client connection is handled within its own thread, and
can run a variety of processes. Each process is a class, and is run by
instantiating it. As each client logs off, or the connection is broken,
the thread is terminated. I wanted to confirm positively that all
objects created by the thread are garbage collected. I was concerned
that if I left a superfluous reference dangling somewhere I might end
up with the equivalent of a memory leak.
I know from previous experience that you cannot confirm deletion of a
class object by printing a message from a __del__() method, if there
are any cyclic references to the object, as it will then not be garbage
collected at all. Therefore I use the 'delwatcher' class that was
explained by Tim Evans in a post on this subject a couple of years ago
-
class DelWatcher:
def __init__(self,obj):
self.objrepr = repr(obj)
def __del__(self):
print '%s deleted' % self.objrepr
class a:
def __init__(self):
self._delwatcher = DelWatcher(self)
You can now see that an object of class a is deleted, even if it has
cyclic references.
I used this technique, and I could see some objects being deleted at
the correct point. Others, however, did not get deleted until the
server program terminated. After some investigation, I found that I was
not generating enough 'dirty' objects to trigger the garbage collector
into running. I fixed that by putting the following lines at the top of
the server program -
import gc
gc.set_threshold(10) # on my system, the default is 700
Now I can see all objects being deleted at or close to the expected
point, and therefore I am confident that I do not have any leaks.
Obviously delwatcher and set_threshold are temporary measures to prove
a point - I have now removed them.
Is this a sensible approach, or are there easier ways to achieve this?
Frank Millman
I don't know whether this will be of interest, but I have just carried
out an exercise that I found useful, so I thought I would share it.
I am writing a multi-user business app, with a multi-threaded server
program to handle client connections. The server should 'serve
forever'. Each client connection is handled within its own thread, and
can run a variety of processes. Each process is a class, and is run by
instantiating it. As each client logs off, or the connection is broken,
the thread is terminated. I wanted to confirm positively that all
objects created by the thread are garbage collected. I was concerned
that if I left a superfluous reference dangling somewhere I might end
up with the equivalent of a memory leak.
I know from previous experience that you cannot confirm deletion of a
class object by printing a message from a __del__() method, if there
are any cyclic references to the object, as it will then not be garbage
collected at all. Therefore I use the 'delwatcher' class that was
explained by Tim Evans in a post on this subject a couple of years ago
-
class DelWatcher:
def __init__(self,obj):
self.objrepr = repr(obj)
def __del__(self):
print '%s deleted' % self.objrepr
class a:
def __init__(self):
self._delwatcher = DelWatcher(self)
You can now see that an object of class a is deleted, even if it has
cyclic references.
I used this technique, and I could see some objects being deleted at
the correct point. Others, however, did not get deleted until the
server program terminated. After some investigation, I found that I was
not generating enough 'dirty' objects to trigger the garbage collector
into running. I fixed that by putting the following lines at the top of
the server program -
import gc
gc.set_threshold(10) # on my system, the default is 700
Now I can see all objects being deleted at or close to the expected
point, and therefore I am confident that I do not have any leaks.
Obviously delwatcher and set_threshold are temporary measures to prove
a point - I have now removed them.
Is this a sensible approach, or are there easier ways to achieve this?
Frank Millman