https://bugs.kde.org/show_bug.cgi?id=524780
--- Comment #7 from [email protected] --- Thanks a lot for looking into this, Ralf. Your QTextBrowser measurements are right: the renderer really does cost noticeable time, and my original report was wrong to call it "ruled out". On my machine, rendering my exported report HTML takes about 1.5 s in a plain QTextBrowser (Qt 5.15 and Qt 6.4 alike). But that does not explain the 50 s I see, so I tried again with the help of Claude (an AI assistant). This time we found the cause and could reproduce it in isolation. I can't judge the C++ details myself, so please check it. **What I tested** - Nightly Flatpak (master, 2026-10-13, Qt 6.11) with my *anonymized file attached to this bug*, report R000183: about **60 s** on my machine (i7-1360P). So with the same code and the same file you get ~8 s and I get ~60 s. The data is not the difference, the environment is. - Profiled that run with the org.kde.kmymoney.Debug symbols (gdb sampling, 197 non-idle samples, build IDs verified): ``` 100.0% KReportTab::showEvent 93.4% reports::PivotTable::renderHTML 51.8% QArrayDataPointer<reports::PivotCell>::reallocateAndGrow (inside renderHTML) 43.1% QArrayDataPointer<reports::PivotCell>::~QArrayDataPointer (inside renderHTML) 6.6% reports::PivotTable::init ``` So almost all of the time is spent *building the HTML string*, not in the report calculation and not in QTextBrowser. This also explains why the HTML export is just as slow for me. **The cause (as far as we can tell): Qt5 → Qt6 change of `QMap::operator[] const`** `renderHTML()` is const and walks the grid with const_iterators. For every cell it reads, twice: ```cpp it_row.value()[rowType][column] // pivottable.cpp, renderHTML, e.g. lines 1944 / 1946 ``` - Qt5: `const T QMap::operator[](const Key&) const` returns a *const* copy, a shallow, refcounted one. `[column]` then uses the const `QList::operator[]`. Nothing is copied. - Qt6: `T QMap::operator[](const Key&) const` returns a *non-const* copy. `[column]` then calls the non-const `QList::operator[]`, which **detaches**, because the data is still shared with the grid. So the *whole row* (all ~871 PivotCells) is deep-copied to read a single cell, and then thrown away. For my report that is roughly 31 rows × 871 columns × 2 accesses × 871 copied cells ≈ 47 million PivotCell copies. The same pattern is used for the inner/outer/grand totals rows in renderHTML, and also in renderCSV. **Isolated reproduction** (same nested QMap/QList types, same access pattern, 31 × 871 cells, only the Qt version differs): | | access as in renderHTML | row taken once as const reference | |---|---|---| | Qt 5.15 | 2 ms | 0 ms | | Qt 6.4 | **1465 ms** | 0 ms | The real code is slower than this mock, because every PivotCell copy goes through AlkValue copy/destroy calls, but the profile signature is identical. **Possible reason why you don't see it:** are you building against Qt5 on openSUSE Leap? With Qt5 this pattern costs nothing, which would leave only the QTextBrowser time you measured (~8 s). The Flatpak is Qt6. KMyMoney 5.1.3 (Qt5) is fast for me. **Possible fix direction:** in the const render methods, take a const reference to the row once instead of indexing through the temporary returned by `QMap::operator[] const`, e.g. ```cpp const PivotGridRow& row = *it_row.value().constFind(rowType); ... row[column] ... ``` (or a small const accessor on PivotGridRowSet that returns `const PivotGridRow&`). In the mock this brings Qt6 back to 0 ms. The QTextBrowser cost you found would be a separate, second issue on top of this. -- You are receiving this mail because: You are watching all bug changes.
