On Thu, 17 Feb 2005 17:03:16 -0000 (GMT)
"Phil Thompson" <[EMAIL PROTECTED]> wrote:

> Gentoo (x86 and amd64). I didn't run the C++ test - I was refering to the
> original Python test that Torsten sent me.

Ok, I was confused because I tought that you were having different results
with the C++ test, so I thinked that maybe the problem was in Qt 3.3.3 and
in 3.3.4 it was fixed. 

I talked with the qt-bugs folks, they said (about the C++ test):

 "Yes. The problem is that Xlib allocates memory when you call certain
  functions (which is what the QWidget constructor ends up doing) and
  these memory blocks are not freed before other X functions are called.
  So if you insert a call to QApplication::processEvents() in your loop
  then you will no longer see increased memory usage. You can check this
  yourself by using valgrind and forcing the application to quit after
  the loop is done (i.e. by calling abort(3)) and run valgrind with the
  "--leak-check=yes" argument. You will then see that most, if not all,
  of the memory used at that point is allocated by Xlib. If you call
  QApplication::processEvents() then Xlib will have freed the memory
  before the application terminates. Do note that this is only a problem
  while your loop is spinning, the memory is actually freed when the loop
  returns even though top or vmsize might tell you otherwise."

So I inserted a processEvents() in the middle of the C++ loop, and now it
seems ok. But then I tried doing the same with my Python test, inserting
that processEvents() call, but that didn't fix it. 

Now I have the equivalent program done in C++ and PyQT, and the C++ one
don't leak but the PyQT one keeps leaking. I'm attaching the new version
of both and their output. 

What I don't understand is why you aren't seeing the same behaviour, I
tried with Qt 3.3.3 / 3.3.4, with the sip/pyqt version packaged for Debian
and with the latest sip/pyqt snapshot. So maybe the problem is in another
library, I don't know, maybe I must install your Gentoo version and then
copy one by one the pyqt required libraries to the Debian machine, to see
where the correct behaviour shows. Do you have any idea of how I can
continue the investigation?

Note, the C++ program now have a weird behaviour,when you close the window,
the process didn't finish and the memory usage begins to increase. I
don't think that this is related to the problem.


Saludos,
Nahuel Greco.
#include <qapplication.h>
#include <qmainwindow.h>
#include <qdialog.h>
#include <qevent.h>
#include <qfile.h>
#include <qpushbutton.h>
#include <iostream>

class Main : public QMainWindow {
public:
	void keyPressEvent( QKeyEvent *k);
};

QApplication *app;

void presentMemData() {
        QFile f("/proc/self/status");
        QTextStream stream(&f);                                                
        QString line;          
        QStringList l;
        int vmsize = 0, vmrss = 0;

        f.open(IO_ReadOnly);
        while ( !stream.eof() ) {
                line = stream.readLine();
                l = QStringList::split(" ", line);
                if (l.size() > 1) {
                        if (line.startsWith("VmSize:"))
                                vmsize = l[1].toInt();
			if (line.startsWith("VmRSS:"))
                                vmrss = l[1].toInt();
                }
        }

        f.close();
        std::cout << "* VmSize: " << vmsize
                  << "; VmRss: " << vmrss
                  << std::endl;
}


void Main::keyPressEvent(QKeyEvent *k) {
	if (k->key() == QKeyEvent::Key_Enter || k->key() == QKeyEvent::Key_Return) {
		std::cout << "Creating QDialog's" << std::endl;
		for(int i=0;i<80001;++i) {
			// Note, if you change this for a QPushButton instead
			// of a QDialog, it also leaks!
			// but no for a QCustomEvent!
			QDialog *d = new QDialog(this);
			delete d; 

			if(i%1000 == 0) {
				std::cout << "Pre processEvents()" << std::endl;
				presentMemData();
				app->processEvents();
				std::cout << "Post processEvents()" << std::endl;
			}
		}
	}
}

int main(int argc, char **argv)
{
     app = new QApplication(argc, argv);
     Main w;
     app->setMainWidget(&w);
     w.show();

     std::cout << "QT Version: " << qVersion() << std::endl;
     std::cout << "Focus the Window and press Enter for object creation / destruction loop" << std::endl;

     app->exec();
     
     std::cout << "Pre deleting QApplication" << std::endl;
     presentMemData();
     delete app;
     std::cout << "Post deleting QApplication" << std::endl;
     presentMemData();
     return 1;
}




#!/usr/bin/python
import os, sys, time, gc
from qt import *

def report(s):
    print s
    sys.stdout.flush()

def presentMemData(s=""):
    vmsize = vmrss = 0 
    for l in open('/proc/self/status','r').readlines():
        if l.startswith('VmSize:'):
            vmsize = int(l.split()[1])
        elif l.startswith('VmRSS:'):
            vmrss  = int(l.split()[1])
    report(s+"* VmSize: %d VmRss: %d" % (vmsize,vmrss))


class Main(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

    def keyPressEvent(self, event):
        global app
        NUM_FORMS = 4000
        
        k = event.key()
        if k in (QKeyEvent.Key_Enter, QKeyEvent.Key_Return):
            while 1:
              report("\n*** Creating %d QDialog's" % NUM_FORMS)
              presentMemData("Pre-Creating: \n")
              for x in range(NUM_FORMS):
                  # Leaks if the parent is defined or not
                  # and not only with QDialog, but with QPushButton for
                  # example
                  # with QCustomEvent(1) also leaks but at a lesser rate.
                  f = QDialog(self)
                  f = None
              report("End Creating\nForcing GC")
              col   = gc.collect()
              uncol = len(gc.garbage)
              if col or uncol:
                  report("GC Collected: %d Uncollected: %d" % (col, uncol))
              report("End GC")

              presentMemData("Post-Creating: \n")

              app.processEvents()
              presentMemData("Post QApplication::processEvents(): \n")

        elif k == QKeyEvent.Key_M:
            presentMemData()


app = QApplication(sys.argv)

w = Main()
app.setMainWidget(w)
w.show()
report("QT Version:   "+ qVersion())
report("PYQT Version: "+ PYQT_VERSION_STR)
report("SIP Version:  "+ os.popen('sip -V').read())
report("Focus the Window and press Enter for object creation / destruction loop\n")
presentMemData()
app.exec_loop()



Attachment: test_cpp_leak.log
Description: Binary data

Attachment: test_py_leak.log
Description: Binary data

_______________________________________________
PyKDE mailing list    [email protected]
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde

Reply via email to