1

Background: I'm developing application using Qt 5.5.1, compiling with msvc2013. In this app I use my own implementation of QTableView, along with custom QStyledItemDelegate (needed custom cell editing) and QAbstractTableModel. I intend this view to work with massive amount of data that I wrap inside mentioned model. I allow the user few data editing options, custom sorting, 'invalid' rows windup etc.

The problem: scrolling speed of my QTableView subclass is slow - it gets slower the more table is shown (by resizing window), e.g. ~250 cells shown (in fullscreen) = slow, ~70 cells shown (small window) = fast.

Whad did I try so far:

  • First was to check if my model is slowing things down - I have measured times (using QTime::elapsed()) reading 10k samples and it shown 0 or 1ms. Then I have simply altered QTableView::data method to always return predefined string and not acquire any real data.

    QVariant DataSet_TableModel::data(const QModelIndex &index, int role) const { if (role == Qt::ItemDataRole::DisplayRole) { return QVariant("aRatherLongString"); //results in slow scrolling //return QVariant("a"); // this instead results in fast scrolling } else return QVariant(); } As you can see, the speed seems to be affected by number of characters vieved per cell, and not by underlying connections to data source.

  • In my custom implementation of QStyledItemDelegate I have tried same 'trick' as above - this time overriging displayText method:

    QString DataSet_TableModel_StyledItemDelegate::displayText(const QVariant &value, const QLocale &locale) const { return "a" //fast // return "aRatherLongString"; //slow // return QStyledItemDelegate::displayText(value, locale); //default }

  • After some thought with a friend we concluded that maybe we could disable drawing/painting/updating of cells until whole scroll action is done. It might cause some flickering, but it's worth a try. Unfortunately we dont really know how to aproach this. We have everriden QTableView methods: scrollContentsBy(int dx, int dy) and verticalScrollbarAction(int action) - we have captured scroll action properly (either method intercepts it) and tried to somehow disable repainting like this:

    void DataSet_TableView::verticalScrollbarAction(int action) { this->setUpdatesEnabled(false); QTableView::verticalScrollbarAction(action); this->setUpdatesEnabled(true); }

...but it did not have any visible effect. How should we approach it? Do we need to use setUpdatesEnabled() on items that are put inside cells directly? (not sure what those are - widgets?)

Here are screenshots taken as part of testing this problem:

Predefined text, no calls to underlying data structure - slow scrolling, 'full screen'

Predefined text, no calls to underlying data structure - fast scrolling, windowed

Request: Could you kindly help me pinpoint the cause of this and suggest solution if possible? Is it limitation of the classes that I use?

  • Have you tried to analyse it with profiling tools? – Frank Osterfeld Apr 24 '16 at 20:56
  • No, I haven't. I might try using profiler but I have yet to learn how to use it (and find proper tool) - will take some time. – Quaintrovert Apr 25 '16 at 00:12
  • Are your items all the same size - and, if so, did you set the `uniformItemSizes` property of the view. That can have quite an impact on performance. – Toby Speight Apr 25 '16 at 09:58
  • @TobySpeight I did try to do it, but QTableView does not have any property similar to uniformItemSizes (it seems that you talk about QListView). I have tried using setDefaultSectionSize(mySize), setSectionResizeMode(QHeaderView::Fixed) and resizeSections(QHeaderView::Fixed) on both headers in view's constructor (in given order) - no positive change on scrolling speed. – Quaintrovert Apr 25 '16 at 12:14
  • @FrankOsterfeld I did some profiling with a friend, got result like this: [link]https://i.imgsafe.org/9a0d81a.png (using luke stackwalker) - unfortunately we lack knowledge to make anything out of this results for now. Tests contained scrolling actions only. One test was done with empty QVariant and it is fast, the other one with QString inside QVariant - this one was slow. – Quaintrovert Apr 25 '16 at 12:26

1 Answers1

2

First of all, you should also run your application in release mode to check your perfomance, in my experience, the performance decreases greatly when using debug mode.

Secondly, you need to be aware that the model data method and delegates methods are called every time you resize, scroll, focus out, right click etc. These actions trigger those methods to be called for each displayed cell, therefore you would need to make sure that you don't do any unnecessary processing.

The items inside cells are delegates that call their own methods (eg: paint).

Some C++ specific optimisations would be helpful in the implementation of these methods, like using a switch instead of an if statement, see explanation here and here. The usage of Conditional (Ternary) Operators might also speed up the things, more information here, here and some information about expensive checkings here.

Also, QVariant handles text in different ways, as exemplified below, you should try both ways and check if there is any difference in speed. Some conversions are more expensive than others.

v = QVariant("hello");          // The variant now contains a QByteArray
v = QVariant(tr("hello"));      // The variant now contains a QString
Community
  • 1
  • 1
Lex
  • 51
  • 5