useless calls to layout lines

Dr.-Ing. Christoph Cullmann cullmann at
Sat Mar 24 18:50:30 UTC 2018


> Hey all,
> got me interested in the performance of
> Katepart for long lines again. The culprit on my machine really is line
> layouting - which shouldn't come as a surprise if the line is really long.
> But what *does* surprise me is the amount of layouting we do. The five lines
> in the document get layouted ~40 times, even though nothing really changes in
> the view...
> Biggest culprits seems to be: Moving Ranges :)
> The on-the-fly spellchecker code e.g. is using moving ranges. The moving
> ranges can trigger view updates via notifyAboutRangeChange which gets called
> in quite a few places, e.g.:
> #0  0x00007f5553560458 in KTextEditor::ViewPrivate::delayedUpdateOfView()@plt
> () from /home/milian/projects/compiled/kf5-dbg/lib64/
> #1  0x00007f5553563246 in Kate::TextBuffer::notifyAboutRangeChange
> (this=<optimized out>, view=0x0, startLine=0, endLine=0,
> rangeWithAttribute=false)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/buffer/
> katetextbuffer.cpp:991
> #2  0x00007f55536917f2 in KateOnTheFlyChecker::misspelling
> (this=0x55a29c4922d0, word=..., start=<optimized out>)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/spellcheck/
> ontheflycheck.cpp:609
> Or also the following. Note there's a frame for TextRange::setFeedback missing
> below somehow (devirtualization?!):
> #0  0x00007f9aaddf3458 in KTextEditor::ViewPrivate::delayedUpdateOfView()@plt
> () from /home/milian/projects/compiled/kf5-dbg/lib64/
> #1  0x00007f9aaddf6246 in Kate::TextBuffer::notifyAboutRangeChange
> (this=<optimized out>, view=0x0, startLine=0, endLine=0,
> rangeWithAttribute=false)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/buffer/
> katetextbuffer.cpp:991
> #2  0x00007f9aadf234a6 in KateOnTheFlyChecker::deleteMovingRangeQuickly
> (this=this at entry=0x55e2bd1f9390, range=range at entry=0x55e2bddac920)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/spellcheck/
> ontheflycheck.cpp:863
> #3  0x00007f9aadf2361c in KateOnTheFlyChecker::spellCheckDone
> (this=0x55e2bd1f9390) at /home/milian/projects/kf5/src/frameworks/ktexteditor/
> src/spellcheck/ontheflycheck.cpp:633
> This will then eventually trigger a relayout:
> #0  0x00007f554ea21f28 in QTextLine::layout_helper(int) () from /usr/lib/
> #1  0x00007f554ea231a1 in QTextLine::setLineWidth(double) () from /usr/lib/
> #2  0x00007f555361bd28 in KateRenderer::layoutLine (this=0x55a29c4cc9e0,
> lineLayout=..., maxwidth=1810, cacheLayout=<optimized out>)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/render/
> katerenderer.cpp:1033
> #3  0x00007f55536217e6 in KateLayoutCache::line
> (this=this at entry=0x55a29ca0e2c0, realLine=realLine at entry=0,
> virtualLine=virtualLine at entry=-1)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/render/
> katelayoutcache.cpp:313
> #4  0x00007f5553621f58 in KateLayoutCache::updateViewCache
> (this=this at entry=0x55a29ca0e2c0, startPos=..., newViewLineCount=48,
> newViewLineCount at entry=-1,
>    viewLinesScrolled=viewLinesScrolled at entry=0) at /home/milian/projects/kf5/
> src/frameworks/ktexteditor/src/render/katelayoutcache.cpp:242
> #5  0x00007f555366caa0 in KateViewInternal::tagLines (this=0x55a29c3ead80,
> start=..., end=..., realCursors=realCursors at entry=true)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/view/
> kateviewinternal.cpp:2203
> #6  0x00007f555366cd49 in KateViewInternal::tagLines (this=<optimized out>,
> start=<optimized out>, end=<optimized out>, realLines=realLines at entry=true)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/view/
> kateviewinternal.cpp:2176
> #7  0x00007f55536548ff in KTextEditor::ViewPrivate::tagLines
> (this=this at entry=0x55a29ca46050, start=<optimized out>, end=<optimized out>,
> realLines=realLines at entry=true)
>    at /home/milian/projects/kf5/src/frameworks/ktexteditor/src/view/
> kateview.cpp:2012
> #8  0x00007f5553663735 in KTextEditor::ViewPrivate::slotDelayedUpdateOfView
> (this=0x55a29ca46050) at /home/milian/projects/kf5/src/frameworks/ktexteditor/
> src/view/kateview.cpp:3385
> I don't see an easy way around this. I just note that some calls to
> `m_buffer.notifyAboutRangeChange` in katetextrange.cpp are guarded with
> if (m_attribute || m_feedback)
> while others are not, e.g. in TextRange::setFeedback. Adding those checks
> could potentially remove some relayouting calls, but I'm not sure whether this
> is OK to do or not. Christoph?
> I'll dig a bit deeper and see if more can be found and removed...
I will take a look, too.

What could be possible would be to avoid to re-layout if only ranges change that
don't affect the layout. e.g. I don't need to relayout if I only have some color/underline things,
only if we have stuff that changes the font face like "bold" or such.

But perhaps it would be even enough to try to minimize the number of layouts,
thought I did think we already group them together with some delayed signal for the range
changing that triggers the above slotDelayedUpdateOfView, but that seems not to be sufficient.

Perhaps the spell checking could try to group the range creation better to not
create too many times single ranges but just "a lot" at once, but I am not that familiar with
the spellchecking code.


----------------------------- Dr.-Ing. Christoph Cullmann ---------
AbsInt Angewandte Informatik GmbH      Email: cullmann at
Science Park 1                         Tel:   +49-681-38360-22
66123 Saarbrücken                      Fax:   +49-681-38360-20
GERMANY                                WWW:
Geschäftsführung: Dr.-Ing. Christian Ferdinand
Eingetragen im Handelsregister des Amtsgerichts Saarbrücken, HRB 11234

More information about the KWrite-Devel mailing list