While working on Calligra Words, I did some optimization work on our text loading system and realized that for some documents a lot of time was spent in QTextDocumentPrivate::adjustDocumentChangesAndCursors.
For each fragment of text inserted to the document, this function will go through each cursor held against the document to update its position.
In the common case of appending text fragments to a document, this is completely sub-optimal since most cursors won't be modified by the change.
I built a demonstration code that highlights this issue by creating a document with N blocks, and optionaly keeping a cursor to each block. For 10k blocks, on my computer, I get a 0.05s vs 2s run time.
A (deeply flawed) proof of concept patch that changes QTextDocumentPrivate::cursors to a QList instead of a QSet, and keep the list ordered at insertion (but not maintaining the order afterwards yet, it's a proof of concept), makes this difference much much smaller. There is a similar behaviour in ::finishEdit, but since this code has no knowledge of the altered parts of the document, it's not as easy to improve.
The bug also applies to Qt 5, and is even worse in Qt5 due to, it seems, differences in implementation of QSet.