Overhead cost of using Qt models

I decided to run very simple test to have glance on performance of Qt models and overhead cost of using them.
Something very simple as make 1M random strings with random size (note: rnd_str(int) return some random string with specified size)

	int n = 1000000;
	QStandardItemModel std(n, 1);
	for(int row =0; row <n; ++row)
		std.setData(std.index(row,0), rnd_str(rand() % 16));

versus just vector of strings

	QVector<QString> vec;
	for(int i =0; i< n; ++i)
		vec.push_back(rnd_str(rand() % 16));

Then just compare time of iterating through them:

	QTime t = QTime::currentTime();
	for(int row =0; row< n; ++row)
		std.index(row,0).data().toString();
	qDebug() << "mod msecs" << t.msecsTo(QTime::currentTime());

	t = QTime::currentTime();
	for(int i =0; i< n; ++i)
		vec[i];
	qDebug() << "vec msecs" << t.msecsTo(QTime::currentTime());

Results: 138 msecs (model) vs 18 msecs (vector)
Consider another methodology, let's sort both: model by QSortFilterProxyModel and vector by qSort():

	t = QTime::currentTime();
	QSortFilterProxyModel srt;
	srt.setSourceModel(&std);
	srt.sort(0);
	qDebug() << "mod sort" << t.msecsTo(QTime::currentTime());

	t = QTime::currentTime();
	qSort(vec);
	qDebug() << "vec sort" << t.msecsTo(QTime::currentTime());

Results: 7317 msecs (model) vs 1057 msecs (vector)
Assuming that QSortFilterProxyModel is implemented as much efficient as possible we see that result ~7:1 correlates with previous compares.

So accessing (I emphasize that only accessing) with Qt models may be about 7 times slower than you can reach with stl/qtl.

To my mind to serve Gui it is not critical at all, but if sorting is part of that, then we really may loose performance 7 times. (or any other model manipulations that involve iterations through all items and we have tons of them)

Conclusion and some ideas to squeeze maximum performance from models: for example my implemented models may have some UserRole for accessing const QVector & (of known data type), and then if such model need sorting, I may implement my custom sort model which checks such UserRole for const access to vector and get a sorted through referencing pointers? Will I get performance of sort 7 times? Interesting...

UPDATE: as people mentioned in comments, the difference is also related to inefficient implementation of QStandardItemModel which add overhead on top, so changing to use QStringListModel in "debug" we have 5032 msecs (model) vs 1023 msecs (vector), so performance loose is really less we had in previous testing.

I think it to be continued...

This entry was posted in Blog, C++, Models, Qt, Research. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

3 Comments

  1. Bill King
    Posted February 20, 2013 at 08:39 | Permalink

    Using it wrong… :) Models are best for dynamic retrieval of data (eg displaying data from a list). A good example (from the Qtopia project…) was keeping a dynamic buffer of +10 entries front/back for the document list display. Rather than spending 10 minutes retrieving the list, populating the model/view, the icons, etc etc, the model would allow us to retrieve the next 10 in the set when we’d used up the buffer. This of course dramatically improved performance, and memory usage (in a massively constrained environment, we’re talking 16M here…)nnSo… these sort of measurements… don’t really equate. Lemons to cucumbers.

  2. Uku Buku
    Posted February 20, 2013 at 12:08 | Permalink

    It is not about a way of efficient programming the models itself – dynamic retrieval or populating with full data. It is good point about the access. If you need some view with sorted items then you have to use QSortFilterModel or sort your data manually, and there is no way to avoid iterations of all rows. Author gives good point about the cost of accessing model.

  3. Jan Kundru00e1t
    Posted February 20, 2013 at 15:08 | Permalink

    You are working with the QStandardItemModel, not with “Qt models” — the QSIM is a rather basic implementation which is not ideal for big or complicated models. It is optimized towards the ease of use, not high performance.nnThe lesson to learn here is clear — any abstraction has its costs, and when using the Qt models (i.e. subclasses of a QAbstractItemModel), you will have to pay it. One of these costs is in the QVariant marshalling; it is no wonder that extracting a QString stored in a QVariant is more expensive than accessing a QString directly.nnOn the other hand, what the QAIM abstraction does provide as a clear benefit is the separation of the actual data storage and organizing (which shall happen in the model and the associated proxy models) and display (which is delegated to the views and delegates and other proxy models).nnThe use case of sorting is actually a nice example of the costs vs. benefits of these “standardized” abstraction interfaces. The actual performance of a properly-done sort can be a lot better; your model could very well perform the sorting on its own, using direct access to whatever data structure you keep your data in. On the other hand, in this case you will have to write (at least) some glue code which makes a generic sort algorithm work with your custom data format as used by the model. That’s a lot of work which can be avoided (at the cost of run-time performance) if you just use the QSortFilterProxyModel.nnAnyway, not saying that the QAIM’s abstraction is perfect; one thing which I’m missing are proper callbacks for QPersistentModelIndex creation/destruction. But it’s a tool which has reasonable benefits (and you can always sidestep the abstraction via QModelIndex::internalPointer() in situations where the overhead is too high).nnHave fun :),nJan

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Clef two-factor authentication