[Qt-interest] QTreeView and custom QAbstractItemModel performance problem
Andreas Pakulat
apaku at gmx.de
Thu Jul 8 16:35:58 CEST 2010
On 08.07.10 16:09:52, Felix Brack wrote:
> 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%.
Then you'll have to hit your app with a profiler, I don't see another way
of finding out where all those cpu-cycles are burnt (certainly not in that
data function).
Andreas
--
Perfect day for scrubbing the floor and other exciting things.
More information about the Qt-interest-old
mailing list