I've been having problems with my application consuming too much memory after
some time running and today decided to take a deeper look. I've ended up with
the attach test.py script which either demonstrates PyQt is not freeing memory
appropiately when signals are involved or I simply don't understand how this
works.
As you can see the script creates lists with 100.000 QObjects and prints the
memory used. As python won't free memory but reuse what has already been freed
I expect a call like:
list = []
fill in the list with lots of data
to take as much memory as:
list = []
fill in the list with lots of data
list = []
fill in the list with the same lots of data
If you give it a try, you'll realize that this is true if you create 100.000
objects with no signal connections. But if you connect and disconnect a
signal for those objects, the memory used after the second fill is larger than
after the first one.
It seems to me that some data is being leaked in connect() and disconnect()
functions (which, by the way, take up a lot of memory).
Here's the output of the script in my system:
$ python test.py one no
Executing 'one' without signals
Memory: 21564
$ python test.py one yes
Executing 'one' with signals
Memory: 64992
$ python test.py two yes
Executing 'two' with signals
Memory: 125592
$ python test.py two+remove yes
Executing 'two+remove' with signals
Memory: 93880
$ python test.py three+remove yes
Executing 'three+remove' with signals
Memory: 122808
So "two+remove yes" should be using 64992 Kb (just like "one yes") but it uses
50% more. The same happens with "three+remove yes", again more 30 Mb!
--
Albert Cervera i Areny
http://www.NaN-tic.com
Mòbil: +34 669 40 40 18
import os
import sys
from PyQt4.QtCore import *
def quit():
print "Memory: ", int(os.popen('ps -p %d -o rss | tail -1' % os.getpid()).read())
sys.exit()
class Test(QObject):
def slot(self):
print "SLOT"
def init(self, l):
for x in xrange(100000):
o = QObject()
if signals:
o.connect( o, SIGNAL('destroyed(QObject*)'), self.slot )
o.disconnect( o, SIGNAL('destroyed(QObject*)'), self.slot )
l.append( o )
if len(sys.argv) <= 2:
print "Syntax: test.py one|two|two+remove|three+remove yes|no"
quit()
type=sys.argv[1]
signals=sys.argv[2]
if signals == 'yes':
signals = True
print "Executing '%s' with signals" % type
else:
signals = False
print "Executing '%s' without signals" % type
if type == 'one':
t = Test()
l1 = []
t.init(l1)
quit()
if type == 'two':
t = Test()
l1 = []
t.init(l1)
l2 = []
t.init(l2)
quit()
if type == 'two+remove':
t = Test()
l1 = []
t.init(l1)
l1 = [] # The first list is removed before executing again
l2 = []
t.init(l2)
quit()
if type == 'three+remove':
t = Test()
l1 = []
t.init(l1)
l1 = [] # The first list is removed before executing again
l2 = []
t.init(l2)
l2 = [] # The first list is removed before executing again
l3 = []
t.init(l3)
quit()
_______________________________________________
PyQt mailing list [email protected]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt