Qt-interest Archive, December 2007
How to create a large table without leaking memory
Message 1 in thread
Hello,
I want to create a QAbstractTableModel to display a table of data
stored in another place. To test it, I created a large model
(10000x10000) which doesn't store data, but instead returns a computed
string for every cell.
The problem is that it leaks a lot of memory. If I enlarge the window
and start scrolling slowly, the memory usage of the process grows very
fast, to hundreds of megabytes. My guess is that the returned strings
aren't deleted, but perhaps it's something else. Is there anything I
can do about it?
"leak.cpp" can be found here: http://cpp.pastebin.com/f50b43111
"leak.h" can be found here: http://cpp.pastebin.com/d7609755c
The code is actually by Phil Thompson - I actually want to use PyQt,
but it turns out that an equivalent C++ code leaks, so the problem is
not with PyQt but with Qt itself.
Thanks,
Noam
--
[ signature omitted ]
Message 2 in thread
On Monday 24 December 2007 15:28:00 Noam Raphael wrote:
> Hello,
>
> I want to create a QAbstractTableModel to display a table of data
> stored in another place. To test it, I created a large model
> (10000x10000) which doesn't store data, but instead returns a computed
> string for every cell.
>
> The problem is that it leaks a lot of memory. If I enlarge the window
> and start scrolling slowly, the memory usage of the process grows very
> fast, to hundreds of megabytes. My guess is that the returned strings
> aren't deleted, but perhaps it's something else. Is there anything I
> can do about it?
>
> "leak.cpp" can be found here: http://cpp.pastebin.com/f50b43111
> "leak.h" can be found here: http://cpp.pastebin.com/d7609755c
>
I have not run your code, but there are two things possibly wrong:
1) Your mode actually returns a tree with infinite nodes since each node has
1000 children with no limit. This should not matter for a "table", but
something might be up there. You should change your code to:
public:
int rowCount(const QModelIndex &index = QModelIndex()) const
{
if (false == index.isValid())
return 1000;
else
return 0;
}
2) You should only return calculated strings for the DisplayRole. There are
lots of other roles the model can handle, but from your code you are only
handling one. Change your code to:
QVariant TableModel::data(const QModelIndex &index, int role) const
{
if( index.isValid() && role == Qt::DisplayRole )
return QString("(%1, %2)").arg(index.row()).arg(index.column());
else
return QVariant();
}
Good Luck,
--Justin
--
[ signature omitted ]
Message 3 in thread
On Monday 24 December 2007 15:41:41 Justin Noel wrote:
> On Monday 24 December 2007 15:28:00 Noam Raphael wrote:
> > Hello,
> >
> > I want to create a QAbstractTableModel to display a table of data
> > stored in another place. To test it, I created a large model
> > (10000x10000) which doesn't store data, but instead returns a computed
> > string for every cell.
> >
> > The problem is that it leaks a lot of memory. If I enlarge the window
> > and start scrolling slowly, the memory usage of the process grows very
> > fast, to hundreds of megabytes. My guess is that the returned strings
> > aren't deleted, but perhaps it's something else. Is there anything I
> > can do about it?
> >
> > "leak.cpp" can be found here: http://cpp.pastebin.com/f50b43111
> > "leak.h" can be found here: http://cpp.pastebin.com/d7609755c
>
> I have not run your code, but there are two things possibly wrong:
>
> 1) Your mode actually returns a tree with infinite nodes since each node
> has 1000 children with no limit. This should not matter for a "table", but
> something might be up there. You should change your code to:
> public:
> int rowCount(const QModelIndex &index = QModelIndex()) const
> {
> if (false == index.isValid())
> return 1000;
> else
> return 0;
> }
>
> 2) You should only return calculated strings for the DisplayRole. There are
> lots of other roles the model can handle, but from your code you are only
> handling one. Change your code to:
>
> QVariant TableModel::data(const QModelIndex &index, int role) const
> {
> if( index.isValid() && role == Qt::DisplayRole )
> return QString("(%1, %2)").arg(index.row()).arg(index.column());
> else
> return QVariant();
> }
I finally ran your code and saw the memory grow to ~100MB. My guess is that
this is because the view is caching values from the unused roles if the
variant is valid even if it is of the wrong variant type.
With the two above changes to your model there is ~3MB of ram used with at
table of 100,000 rows x 1000 columns.
Good Luck,
--Justin
--
[ signature omitted ]
Message 4 in thread
Great! Thanks a lot!
Noam
2007/12/24, Justin Noel <justin@xxxxxxx>:
> On Monday 24 December 2007 15:41:41 Justin Noel wrote:
> > On Monday 24 December 2007 15:28:00 Noam Raphael wrote:
> > > Hello,
> > >
> > > I want to create a QAbstractTableModel to display a table of data
> > > stored in another place. To test it, I created a large model
> > > (10000x10000) which doesn't store data, but instead returns a computed
> > > string for every cell.
> > >
> > > The problem is that it leaks a lot of memory. If I enlarge the window
> > > and start scrolling slowly, the memory usage of the process grows very
> > > fast, to hundreds of megabytes. My guess is that the returned strings
> > > aren't deleted, but perhaps it's something else. Is there anything I
> > > can do about it?
> > >
> > > "leak.cpp" can be found here: http://cpp.pastebin.com/f50b43111
> > > "leak.h" can be found here: http://cpp.pastebin.com/d7609755c
> >
> > I have not run your code, but there are two things possibly wrong:
> >
> > 1) Your mode actually returns a tree with infinite nodes since each node
> > has 1000 children with no limit. This should not matter for a "table", but
> > something might be up there. You should change your code to:
> > public:
> > int rowCount(const QModelIndex &index = QModelIndex()) const
> > {
> > if (false == index.isValid())
> > return 1000;
> > else
> > return 0;
> > }
> >
> > 2) You should only return calculated strings for the DisplayRole. There are
> > lots of other roles the model can handle, but from your code you are only
> > handling one. Change your code to:
> >
> > QVariant TableModel::data(const QModelIndex &index, int role) const
> > {
> > if( index.isValid() && role == Qt::DisplayRole )
> > return QString("(%1, %2)").arg(index.row()).arg(index.column());
> > else
> > return QVariant();
> > }
>
>
> I finally ran your code and saw the memory grow to ~100MB. My guess is that
> this is because the view is caching values from the unused roles if the
> variant is valid even if it is of the wrong variant type.
>
> With the two above changes to your model there is ~3MB of ram used with at
> table of 100,000 rows x 1000 columns.
>
> Good Luck,
> --Justin
>
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
>
--
[ signature omitted ]