Important: Please read the Qt Code of Conduct -

QTableView::scrollToBottom and performance

  • Hello Qt developpers,

    i am solving performace problems of my setup, which is de facto very large table in QTableView that
    can be filtered by regexps and such mechanisms via proxy.
    Actualy i'd like to say few words on this. In the initial implementation i've used QSortFilterProxyModel
    and as soon as i filled the table a bit, a huge performance bottleneck showed up.
    So i had to replace that monster with custom class FilterProxyModel : public QAbstractProxyModel
    that works just fine for my needs.
    But perhaps it could be mentioned in the documentation that if using QSortFilterProxyModel one has to
    consider performance impacts.

    But there is another performance hit that is lesser than the one mentioned above, but it is still dominant in the whole program. The sequence goes cca like this:
    Function Name Number of Calls
    QAbstractItemView::scrollToBottom () 616
    +-> QAbstractItemView::doItemsLayout () 616
    +-> QTableView::updateGeometries () 616
    +-> QHeaderView::sizeHint () const 1 232
    +-> ::sectionSizeFromContents (int) const 122 601

    I wonder how could i prevent this branch of code of being executed, because i do not
    need that functionality as i handle the column sizes myself (or on user's request).
    I tried messing around disconnecting misc signals, but did not succeeded in any way (yet).
    Perhaps you can help me.

    Best regards and many thanks for great gui toolkit,

  • With large datasets you have to consider performance under typical usage regardless of whether it is Qt, .Net, or any other set of tools. I don't know what would be gained by reminding the programmer of that in the Qt docs.

    QHeaderView::sizeHint() will call QHeaderView::sectionSizeFromContents() if the cached size hint is invalid. It starts off invalid and computed once. It can later be invalidated by a call to any of: resizing sections, adding/removing/moving sections, changing the data of a header, or by style changes. A real enemy here would be operating with QHeaderView::ResizeToContents turned on or changing header data constantly. If all your rows are the same height, i.e. the classic table of numbers, then set the resize mode on the vertical header to Fixed.

    Without more detail we could not say exactly what you are doing to trigger this.

    BTW: Why are you calling scrollToBottom() 600+ times in the first place?

  • Yes, but short notice "look this scales up to hundreds, if you want thousands do it that way" would not hurt i guess. I've seen enough questions from people on the internet on this subject to deserve to be mentioned somewhere.

    Ad QHeaderView: that matches from what I've understood from the code and internet wisdom. I've tried to set header(s) to fixed, I have also removed any usage of ResizeToContents. The horizontal table layout is almost 99.9% of time unchanged, i.e. I do not add columns, I do not resize columns (except for first request or on user interaction) I only add rows that are of the same height as you say. Not sure about the styling though. I'm using some delegate to put ellipsis on the correct side.
    I'll try to debug it more today or tomorrow so I can tell more.

    bq. Why are you calling scrollToBottom() 600+ times in the first place?

    The application custom real time logger. So at the end of every batch (= all stuff received from socket) there is a scrollToBottom call (if the users clicked on AutoScroll checkbox).

  • okay, figured it out the source of the call, it's called from here:
    @void QTableView::updateGeometries()
    int width = 0;
    if (!d->verticalHeader->isHidden()) {
    width = qMax(d->verticalHeader->minimumWidth(), d->verticalHeader->sizeHint().width());@

    for each scrollToBottom. So I've hidden the vertical header and now it's looking better.

Log in to reply