1

In my project, I have a function that recursively iterates over the model of a QTreeView. At certain points, I append values to a QStringList that is stored in each item's Qt::UserRole.

Here's the issue... the recursive scanning does a ton of checking, reading from JSON file, importing icons from disk, etc etc HOWEVER, all of that is miles faster than simply appending 1 or 2 strings to the QStringList for about 5% of the items in the model.

I did some basic profiling and found that if I comment out all calls to QStringList::append() but LEAVE IN all the crazy JSON reading, icon setting, color changing, etc, it is 3 times faster than if I left them in. And it is noticeably slower... frustratingly slower.

So I decided to narrow it down to only 1 call to QStringList::append() on about 5% of the items. Here is the example of code:

QStringList rightClickList = mainItem->data(Qt::UserRole+8).toStringList();
rightClickList.append("customName");//comment this out and it runs 3x faster 
                                    //than allllll the recursive scanning combined!
mainItem->setData(rightClickList, Qt::UserRole+8);

I would estimate about 5% of all the items in a given model have any QStringList changes at all. The rest are left alone. Are QStringList types really that slow? If so, what alternative would you recommend?

Thanks for your time!

mrg95
  • 2,371
  • 11
  • 46
  • 89
  • How many items in total? More than 10,000? More than 1,000,000? – piedar Apr 08 '17 at 01:43
  • 1
    Around 1200 items – mrg95 Apr 08 '17 at 01:49
  • Be sure to read http://doc.qt.io/qt-5/implicit-sharing.html If you are using copies, writing to them unshares. If you are using copies recursively ... they will recursively unshare. – Zan Lynx Apr 08 '17 at 03:09
  • @ZanLynx Thanks for this link. I'm aware of that, however the performance problem happens outside of the recursion. It's just that I use a recursive function to loop through all the items. Each item has it's own QStringList and they dont get passed along. The slowdown occurs in a different function and definitely has to do with QList. I've resorted to changing my logic to no longer require those types since they were seriously hurting performance. – mrg95 Apr 08 '17 at 03:13
  • Well, just notice that `data()` returns a QVariant, out of which you *copy* a `QStringLisŧ`, that then you detach by appending data to it, and finally *copy* it back. Now the copies are cheap because of implicit sharing, but the detach is not, and the final copy back likely deletes what's stored in the model. I would run a memory profiler at those lines, because I suspect a lot of temporary allocations to be happening. – peppe Apr 09 '17 at 10:17
  • @peppe I haven't had great experiences with profilers. I there aren't many free options for Windows and Qt iirc. Regardless, I realized that even if I sped things up a bit, since the amount of items vary greatly and it could potentially be massive, any speed improvements would go unnoticed up there. So I've decided to try to multi thread things as best as I can as to not freeze the GUI. I appreciate the help, but I think for my case I asked the wrong question. I should have changed logic instead of changing types. :/ Thanks though! – mrg95 Apr 09 '17 at 11:58

1 Answers1

0
  • It could be memory pressure: as array-based storage grows, the runtime stops and allocates storage to keep up.
  • It could also be a side-effect of recursion; if the problem persists, try a stack-based recursion.
piedar
  • 2,599
  • 1
  • 25
  • 37
  • To clarify. I have a recursive function that scans each item. If an item "passes", it is sent to another function. The QStringList gets appended in that other function (among other tasks I would assume are heavier, like file input and JSON parsing). The QStringList is never READ from in any of these functions. Only appending. At most, a QStringList will have about 3 QStrings, but 95% of items will have 0. Removing all calls to append speeds it up by 3. – mrg95 Apr 08 '17 at 01:54
  • @mrg95 Does setData() accept other collections like list or vector? – piedar Apr 08 '17 at 01:59
  • setData accepts QVariant's, which can hold anything. QStringList is the same as QList and I read it's the recommended type. Could I be wrong? – mrg95 Apr 08 '17 at 02:00
  • I'll test it with QVector which is the other collection you mentioned. – mrg95 Apr 08 '17 at 02:02
  • 1
    Tested with QVector. There is an improvement, but it's marginal. Hmmm. I'll keep profiling. – mrg95 Apr 08 '17 at 02:14
  • I've resorted to changing the logic of my code to no longer use any QLists or QVectors. I had to get creative with QBitArray and one long QString, but the performance is better. – mrg95 Apr 08 '17 at 03:10