Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 6

Qt-interest Archive, April 2007
QListView Performance Analysis


Message 1 in thread

I've written a program that adds an item to a QListView every 100ms.
I'm using the new model/view architecture.  The item consists of an icon
and a string.

On my dual core 3Ghz, the CPU usage hits 100% at about 1600 entries.
I'm running a stock RHEL5 system, except of course for Qt4.2, which I
intalled myself.

After further analysis, it appears that each time an item is added, the
model's QAbstractItem::data() virtual method is called multiple times
for each entry in the listview -- even the ones that are not seen, and even
if the new item is not displayed.  

This is complexity of O(n).  Complexity of the old item based Qt 3 lists
was O(1), and lists of thousands of items was not a CPU problem.  For the
1600th entry, the data() method was called over 8000 times.  Please tell me
I'm doing something wrong, and there is a way to get back to O(1).
Otherwise, should I go back to using Qt3 widgets?

The project can be downloaded via

    wget http://www.intrig.com/lvtest.tgz

    Just run qmake and make.  The executable is placeded in the obj directory.

Here's the pertinent part of the model.

// Here's the data() implemenation
int Count=0;
QVariant ListModel::data(const QModelIndex &index, int role) const
{
    Count++;
    switch (role) {
        case Qt::DisplayRole :
        {
            QString s;
            s.append(QString::number(index.row()));
            s.append(": ");
            s.append(QString::number(_msgs[index.row()]));
            return QVariant(s);
        }
        case Qt::DecorationRole :
            return QVariant(QIcon(QPixmap("rightarrow.xpm")));
            break;
    }
    return QVariant();
}

// This is called via a timer every 100 ms.
void ListModel::addValue()
{
    beginInsertRows(QModelIndex(), _msgs.size(), _msgs.size());
    _msgs.push_back(Count);
    endInsertRows();
    Count = 0;
}
-- 
 [ signature omitted ] 

Message 2 in thread

> -----Original Message-----
> From: Mark Beckwith [mailto:mark@xxxxxxxxxx]
> Sent: Friday, April 20, 2007 2:40 PM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: QListView Performance Analysis
> 
> 
> I've written a program that adds an item to a QListView every 100ms.
> I'm using the new model/view architecture.  The item consists of an
icon
> and a string.
> 
> On my dual core 3Ghz, the CPU usage hits 100% at about 1600 entries.
> I'm running a stock RHEL5 system, except of course for Qt4.2, which I
> intalled myself.
> 
> After further analysis, it appears that each time an item is added,
the
> model's QAbstractItem::data() virtual method is called multiple times
> for each entry in the listview -- even the ones that are not seen, and
> even
> if the new item is not displayed.
> 
> This is complexity of O(n).  Complexity of the old item based Qt 3
lists
> was O(1), and lists of thousands of items was not a CPU problem.  For
the
> 1600th entry, the data() method was called over 8000 times.  Please
tell
> me
> I'm doing something wrong, and there is a way to get back to O(1).
> Otherwise, should I go back to using Qt3 widgets?
> 
> The project can be downloaded via
> 
>     wget http://www.intrig.com/lvtest.tgz
> 
>     Just run qmake and make.  The executable is placeded in the obj
> directory.
> 
> Here's the pertinent part of the model.
> 
> // Here's the data() implemenation
> int Count=0;
> QVariant ListModel::data(const QModelIndex &index, int role) const
> {
>     Count++;
>     switch (role) {
>         case Qt::DisplayRole :
>         {
>             QString s;
>             s.append(QString::number(index.row()));
>             s.append(": ");
>             s.append(QString::number(_msgs[index.row()]));
>             return QVariant(s);
>         }
>         case Qt::DecorationRole :
>             return QVariant(QIcon(QPixmap("rightarrow.xpm")));
>             break;
>     }
>     return QVariant();
> }
> 
> // This is called via a timer every 100 ms.
> void ListModel::addValue()
> {
>     beginInsertRows(QModelIndex(), _msgs.size(), _msgs.size());
>     _msgs.push_back(Count);
>     endInsertRows();
>     Count = 0;
> }

Try setting the lists layoutmode to Batched...

Ie, add the following before your list->show() in your main.cpp

	list->setLayoutMode( QListView::Batched );

--
 [ signature omitted ] 

Message 3 in thread

> 
> Try setting the lists layoutmode to Batched...
> 
> Ie, add the following before your list->show() in your main.cpp
> 
> 	list->setLayoutMode( QListView::Batched );
> 
Another addin... 

Keep track in your add item, and only call the row added calls at some
counted interval...  

Something like

_msgs.push_back(Count);
updateCnt++;
if ( updateCnt < 5 )
	return;

updateCnt = 0;
beginInsertRows(QModelIndex(), _msgs.size()-5, _msgs.size());
endInsertRows();


This way the updatelayout only gets called 1 out of 5 times... But the
layout itself is a O(N) call it seems like

Scott 

--
 [ signature omitted ] 

Message 4 in thread

Scott,

Thanks for the response.

On Fri, Apr 20, 2007 at 03:29:50PM -0700, Scott Aron Bloom wrote:
> 
> But the layout itself is a O(N)
 
This is really, really unfortunate.  I've tried the other things you
suggested but it doesn't get around this problem.  If this is true, then
Qt 4 is just not ready for primetime.  

It would be nice for a Troll to chime in on this one.  Also, the complexity
of O(n) should be posted in the documentation so poor guys like me don't
spend the time to port to model/view.

Mark

On Fri, Apr 20, 2007 at 03:29:50PM -0700, Scott Aron Bloom wrote:

-- 
 [ signature omitted ]