[Qt-interest] QTreeView and custom QAbstractItemModel performance problem

Felix Brack fb at ltec.ch
Thu Jul 8 16:09:52 CEST 2010


On 08.07.2010 12:50, Andreas Pakulat wrote:
> On 08.07.10 11:51:38, Felix Brack wrote:
>> On 08.07.2010 10:58, Andreas Pakulat wrote:
>>> On 08.07.10 10:14:11, Felix Brack wrote:
>>>> By subclassing QAbstractItemModel I have create a custom model that
>>>> stores data from a communication trace row by row. Every row has
>>>> multiple columns such as a time stamp, the data traced from the
>>>> communication, etc. The number of rows in the data model is limited,
>>>> let's say to 100 rows. When adding row 101 it is appended and the first
>>>> row (i.e. the one with the oldest data) is removed.
>>>>
>>>> To show the information to the user I use a QTreeView which shows each
>>>> row of the data in the model line by line, i.e. the model is not
>>>> hierarchic, all rows have the same parent (root) and consist of multiple
>>>> columns.
>>>>
>>>> Things are working so far but performance is very poor and the CPU load
>>>> is incredible (even with just 100 rows). The reason for this is that
>>>> whenever I append a row to the model the view calls the models 'data'
>>>> member for all rows and all columns.
>>>>
>>>> It seems that I'm missing something fundamental here and that appending
>>>> a row of data to my model looks for the view like the entire data has
>>>> changed. I will have to change something so only the data from the newly
>>>> append row is queried by the view.
>>>>
>>>> I just don't know how to do that... Can anybody push me into the right
>>>> direction?
>>>
>>> Can you post your model implementation? It sure sounds like you're doing
>>> the appending wrong, but without having a look at the code its not possible
>>> to say what exactly is wrong.
>>>
>>> A blind guess could be that you're reset'ting you're model every time you
>>> add a row instead of using begin/endInsertRows correctly. See the example
>>> models in Qt.
>>>
>>> Also I'd suggest to use a QTableView instead of QTreeView as that one is
>>> significantly faster on non-tree structures (you can tweak it to have no
>>> lines etc.) in case you ever get more than 100 rows.
>>
>> Hello Andreas,
>>
>> Thanks for your response. The code below is my 'AppendRow' method. The
>> variable 'm_Data' and 'm_IconKey' are just arrays containing the textual
>> data as well as an icon that gets displayed in the first column.
>>
>> QModelIndex CMultiColumnListModel::AppendRow(QString IconKey,
>> QStringList Data)
>> {
>>     beginInsertRows(QModelIndex(), m_Data.size(), m_Data.size()) ;
>>     m_Data.push_back(Data);
>>     m_IconKey.push_back(IconKey);
>>     endInsertRows();
>>
>>     if ((m_nMaxRows!=0)&&  ((int)(m_Data.size())>m_nMaxRows)) {
>>       // remove oldest element from list
>>       beginRemoveRows(QModelIndex(), 0, 0);
>>       m_Data.erase(m_Data.begin());
>>       m_IconKey.erase(m_IconKey.begin());
>>       endRemoveRows();
>>     }
>>
>>     return index(m_Data.size()-1, 0);
>> }
>>
>> Do you see any problem here?
>
> No, can't see anything obvious wrong. Could be the removal of the first
> element is the culprit. In general the data() function of your model should
> be as fast as humanly possible using as little computed data and as much
> pre-computed data as you can get.
>
> Andreas
>

The removal operation in my AppendRow() function is only executed when 
there are more rows then m_nMaxRows. Setting m_nMaxRows to 200 however 
shows that the performance breakdown and the excessive CPU load occurs 
way before a row has to be removed (starting at approximately 20 rows).

Well,I just changed my data() function to look as follows:

QVariant CMultiColumnListModel::data(const QModelIndex& Index, int 
nRole) const
{
   // sanity check
   if (!Index.isValid()) {
     return QVariant::Invalid;
   }

   if (nRole==Qt::DisplayRole) {
     // return text data
     return QString("Test");
   }

   // we do not support other roles for now
   return QVariant::Invalid;
}

I know it is stupid but I can't think of a faster data() function. As I 
expected the problem is exactly the same: very slow with 100 rows and a 
CPU load of more then 50%.



More information about the Qt-interest-old mailing list