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

Reply via email to