Re: [Rosegarden-devel] Rosegarden Qt performance optimization

2022-03-28 Thread Ted Felix

On 3/28/22 2:53 AM, mark_at_yahoo via Rosegarden-devel wrote:

On 3/27/22 4:17 PM, Ted Felix wrote:

   Should be something of a performance bump.  Please test latest git.
I tried the change (in the context of my branch's HEAD) and didn't see 
much difference, either positive or negative. Maybe what I test isn't 
hitting the palette code. Regardless, in my opinion the new version is 
indisputably more correct.


  Yeah.  I noticed little improvement myself.  Usually QSettings 
absolutely destroys performance.  We would have noticed it earlier if it 
were being hit really frequently.


  The real issues are in the drawing code.  Both the Segment Canvas 
(CompositionView which is where I have focused my efforts) and likely 
the editors.  I usually monitor cpu usage closely with "top" or some 
other tool while running an unoptimized debug build on an old anemic 
machine.  (I'm currently using a 10-year-old Core i3, and it's still too 
fast for my tastes.)  Then I remove pieces to see which one is the 
culprit.  I've found this approach to be much more reliable than profilers.


  Some of the history and current status of performance in Rosegarden 
is covered in bug #1391:


https://sourceforge.net/p/rosegarden/bugs/1391/

Ted.


___
Rosegarden-devel mailing list
Rosegarden-devel@lists.sourceforge.net - use the link below to unsubscribe
https://lists.sourceforge.net/lists/listinfo/rosegarden-devel

Re: [Rosegarden-devel] Rosegarden Qt performance optimization

2022-03-27 Thread mark_at_yahoo via Rosegarden-devel

On 3/27/22 4:17 PM, Ted Felix wrote:
   Turns out no one was ever writing to those settings, so they weren't 
actually being used at all.  I removed the use of QSettings in 
GUIPalette and pushed as [bcc713e7].


   Should be something of a performance bump.  Please test latest git.


I tried the change (in the context of my branch's HEAD) and didn't see 
much difference, either positive or negative. Maybe what I test isn't 
hitting the palette code. Regardless, in my opinion the new version is 
indisputably more correct.



On 3/27/22 3:07 PM, mark_at_yahoo wrote:
> Thanks, David. I'm primarily seeing pauses when switching ME display
> modes, particularly with the new ones I've added in my FR
> branches. I'll see if I can come up with a recreatable example
> using only note names in master.

I did, and yes, it was the same QSettings problem. The [659efa2699] 
commit to implement FR #489 instantiates and queries a QSettings in 
MatrixElement::reconfigure(timeT,timeT,int,int) which is called for each 
note in each displayed segment. With 10K+ notes this was taking 20-30 
seconds in some cases when turning off note names.


Once again ironically, when I implemented similar per-note configuration 
for FR #501 and #503 I instinctively cached the persistent QSettings 
values for quick access. I didn't, and don't now, know the full 
implications, but I suspected that at best accessing the database, and 
at worst going to disk (or the "registry" under Windows), would be an 
unacceptable performance hit.


But that brings up another question: Even though in most cases the 
QSettings performance isn't a problem, what would be the implications of 
(taken to the extreme) creating a global instance when Rosegarden 
starts, using it everywhere in the code, and destructing it at program 
exit? You wrote that the constructor does the expensive read of the 
config file(s)/registry. I'm assuming that QSettings::value() does not 
and is therefore at least reasonable fast. But when are the 
files/registry written? In the QSettings destructor, or at each 
QSettings::setValue() call? In other words, if there was a global 
QSettings instance, or more reasonably separate/individual long-lived 
ones (per editor or something) and Rosegarden crashes or otherwise exits 
incorrectly, are pending user-changed settings lost?



One more performance-y thing: I implemented both hide()/show() instead 
of removeItem()/addItem() for the thousands of note names, and also 
changing to QGraphicsView::NoViewportUpdate before doing them. Neither 
made much speed difference, especially compared to the 
orders-of-magnitude boost from removing the QSettings constructor calls.



___
Rosegarden-devel mailing list
Rosegarden-devel@lists.sourceforge.net - use the link below to unsubscribe
https://lists.sourceforge.net/lists/listinfo/rosegarden-devel

Re: [Rosegarden-devel] Rosegarden Qt performance optimization

2022-03-27 Thread Ted Felix

On 3/27/22 6:53 PM, Ted Felix wrote:
   I'll take a look and fix this.  We have a Preferences class that we 
introduced to solve this exact problem in other places.


  Turns out no one was ever writing to those settings, so they weren't 
actually being used at all.  I removed the use of QSettings in 
GUIPalette and pushed as [bcc713e7].


  Should be something of a performance bump.  Please test latest git.

Ted.


___
Rosegarden-devel mailing list
Rosegarden-devel@lists.sourceforge.net - use the link below to unsubscribe
https://lists.sourceforge.net/lists/listinfo/rosegarden-devel

Re: [Rosegarden-devel] Rosegarden Qt performance optimization

2022-03-27 Thread Ted Felix

On 3/27/22 4:57 PM, David Faure wrote:

The main reason why this operation uses lots of CPU is the following:
LoopRuler::paintEvent() and others call GUIPalette::getColor() which *creates*
a QSettings object every time. That's slow, it means parsing one or multiple
config files from disk! The QSettings instance should be kept around.


  I'll take a look and fix this.  We have a Preferences class that we 
introduced to solve this exact problem in other places.


Ted.


___
Rosegarden-devel mailing list
Rosegarden-devel@lists.sourceforge.net - use the link below to unsubscribe
https://lists.sourceforge.net/lists/listinfo/rosegarden-devel


Re: [Rosegarden-devel] Rosegarden Qt performance optimization

2022-03-27 Thread mark_at_yahoo via Rosegarden-devel
Thanks, David. I'm primarily seeing pauses when switching ME display 
modes, particularly with the new ones I've added in my FR branches. I'll 
see if I can come up with a recreatable example using only note names in 
master.


Ironically I have made some small changes (in my branches) to reuse 
QSettings instances instead of creating new ones, but they were all at 
startup or mode switch, not during scrolling. It wasn't a performance 
issue, just seemed like the right thing to do.


I'll try profiling to see if the topics I asked about are the cause of 
the slowdowns I've noticed. On the other hand, even if not, shouldn't I 
be following "best practices" anyway? If calling 
QGraphicsScene::removeItem(item) before "delete item" is recommended, 
why not add that one extra line?  If keeping large numbers of hidden 
items is known to have an impact, regardless how small, and removing 
them doesn't involve trade-offs like the ones I speculated about, I'd 
tend to factor that into the new code I'm writing.



On 3/27/22 1:57 PM, David Faure wrote:

Rule number 1 of optimizing performance is to run a profiler in order to find
out what is slow.

Since you referenced FR#489 I opened a .rg file, opened the matrix editor and
enabled View / Show Note Names. Scrolling left/right isn't actually slow on my
machine, but this uses quite some CPU so I profiled that operation using
hotspot (https://github.com/KDAB/hotspot/).

The main reason why this operation uses lots of CPU is the following:
LoopRuler::paintEvent() and others call GUIPalette::getColor() which *creates*
a QSettings object every time. That's slow, it means parsing one or multiple
config files from disk! The QSettings instance should be kept around.

Apart from this, it all seems fine, actually.
Can you give me a .rg file where you see "unacceptable performance",
together with instructions on how to trigger that? Then I can give you another
profiling result. But better fix that QSettings usage first :-)

Cheers,
David.

On dimanche 27 mars 2022 21:29:42 CEST mark_at_yahoo via Rosegarden-devel
wrote:

I have some questions regarding the above subject line, directed towards
anyone who'd care to offer advice. I ask because I'm seeing unacceptable
(to me) performance in the Matrix Editor with compositions containing a
large number of notes. (I run on a very fast system and imagine it would
be far worse on less capable hardware.) The questions are particularly
applicable to the code I've written to implement feature requests #501
and #503 and am currently writing for #500, but regardless whether those
will eventually be merged into the master branch, the issues also apply
to the existing codebase, particularly FR #489.

I've researched these topics online and haven't found any definitive
answers, or in fact many at all. I apologize if my poor search skills
are to blame.

1) Qt documentation explicitly states:

  https://doc.qt.io/qt-5/qgraphicsitem.html#dtor.QGraphicsItem
  QGraphicsItem::~QGraphicsItem()
  Destroys the QGraphicsItem and all its children. If this item is
  currently associated with a scene, the item will be removed from
  the scene before it is deleted.
  Note: It is more efficient to remove the item from the
  QGraphicsScene before destroying the item.

This is not currently being done in the Matrix Editor. Is the
performance hit for not doing so significant? This applies not only to
destructing large numbers of MatrixElements when an ME is closed, but
more importantly if they are going to be dynamically created and
destroyed, pending answers to the following questions.


2) QGraphicsItem::hide() vs QGraphicsScene::removeItem(QGraphicsItem *item)

Is having a large number of hidden items in a scene a performance hit?
I'm guessing that if they're kept in a separate list and not tested for
QGraphicsView visibility the answer is "no", but I don't know if that's
the case.

I came across:


https://forum.qt.io/topic/41184/solved-qgraphicsscene-clear-delete-items/10
  Asperamanca May 13, 2014, 2:56 AM
  If all you really want to do is hiding and showing them, then
  just call hide() and show(), and leave them in the scene. Adding
  and removing items (and especially widgets!) from a scene is a
  pretty expensive operation.

If that's true (or still true, see "2014" above) and hidden items *do*
slow down rendering, then obviously the two factors need to be weighed
against each other. In the case of small numbers of items that will be
re-shown later it's obviously one answer, and for large numbers that
likely will not it's another. Also, the removeItem() and addItem() hit
happen very infrequently compared to constant panning/zooming view changes.


3)
When doing a large number of addItem() calls, is it worthwhile to consider:

  https://doc.qt.io/qt-5/qgraphicsview.html#ViewportUpdateMode-enum
  enum QGraphicsView::ViewportUpdateMode

  https://doc.qt.io/qt-5/qgraphicsview.html#viewportUpdateM

Re: [Rosegarden-devel] Rosegarden Qt performance optimization

2022-03-27 Thread David Faure
Rule number 1 of optimizing performance is to run a profiler in order to find 
out what is slow.

Since you referenced FR#489 I opened a .rg file, opened the matrix editor and 
enabled View / Show Note Names. Scrolling left/right isn't actually slow on my 
machine, but this uses quite some CPU so I profiled that operation using 
hotspot (https://github.com/KDAB/hotspot/).

The main reason why this operation uses lots of CPU is the following:
LoopRuler::paintEvent() and others call GUIPalette::getColor() which *creates* 
a QSettings object every time. That's slow, it means parsing one or multiple 
config files from disk! The QSettings instance should be kept around.

Apart from this, it all seems fine, actually.
Can you give me a .rg file where you see "unacceptable performance",
together with instructions on how to trigger that? Then I can give you another 
profiling result. But better fix that QSettings usage first :-)

Cheers,
David.

On dimanche 27 mars 2022 21:29:42 CEST mark_at_yahoo via Rosegarden-devel 
wrote:
> I have some questions regarding the above subject line, directed towards
> anyone who'd care to offer advice. I ask because I'm seeing unacceptable
> (to me) performance in the Matrix Editor with compositions containing a
> large number of notes. (I run on a very fast system and imagine it would
> be far worse on less capable hardware.) The questions are particularly
> applicable to the code I've written to implement feature requests #501
> and #503 and am currently writing for #500, but regardless whether those
> will eventually be merged into the master branch, the issues also apply
> to the existing codebase, particularly FR #489.
> 
> I've researched these topics online and haven't found any definitive
> answers, or in fact many at all. I apologize if my poor search skills
> are to blame.
> 
> 1) Qt documentation explicitly states:
> 
>  https://doc.qt.io/qt-5/qgraphicsitem.html#dtor.QGraphicsItem
>  QGraphicsItem::~QGraphicsItem()
>  Destroys the QGraphicsItem and all its children. If this item is
>  currently associated with a scene, the item will be removed from
>  the scene before it is deleted.
>  Note: It is more efficient to remove the item from the
>  QGraphicsScene before destroying the item.
> 
> This is not currently being done in the Matrix Editor. Is the
> performance hit for not doing so significant? This applies not only to
> destructing large numbers of MatrixElements when an ME is closed, but
> more importantly if they are going to be dynamically created and
> destroyed, pending answers to the following questions.
> 
> 
> 2) QGraphicsItem::hide() vs QGraphicsScene::removeItem(QGraphicsItem *item)
> 
> Is having a large number of hidden items in a scene a performance hit?
> I'm guessing that if they're kept in a separate list and not tested for
> QGraphicsView visibility the answer is "no", but I don't know if that's
> the case.
> 
> I came across:
> 
> 
> https://forum.qt.io/topic/41184/solved-qgraphicsscene-clear-delete-items/10
>  Asperamanca May 13, 2014, 2:56 AM
>  If all you really want to do is hiding and showing them, then
>  just call hide() and show(), and leave them in the scene. Adding
>  and removing items (and especially widgets!) from a scene is a
>  pretty expensive operation.
> 
> If that's true (or still true, see "2014" above) and hidden items *do*
> slow down rendering, then obviously the two factors need to be weighed
> against each other. In the case of small numbers of items that will be
> re-shown later it's obviously one answer, and for large numbers that
> likely will not it's another. Also, the removeItem() and addItem() hit
> happen very infrequently compared to constant panning/zooming view changes.
> 
> 
> 3)
> When doing a large number of addItem() calls, is it worthwhile to consider:
> 
>  https://doc.qt.io/qt-5/qgraphicsview.html#ViewportUpdateMode-enum
>  enum QGraphicsView::ViewportUpdateMode
> 
>  https://doc.qt.io/qt-5/qgraphicsview.html#viewportUpdateMode-prop
>  viewportUpdateMode : ViewportUpdateMode
> 
>  https://doc.qt.io/qt-5/qgraphicsview.html#updateScene
>  QGraphicsView::updateScene(const QList &rects)
> 
> In the default QGraphicsView::MinimalViewportUpdate mode, are the
> visibility tests and redrawing done after each addItem()? If so, is it
> worth switching to QGraphicsView::NoViewportUpdate before adding the
> items and then doing an explicit updateScene() and restoring
> MinimalViewportUpdate afterwards?
> 
> 
> Thanks for any feedback. Yes, I'm both an optimization nutjob, and
> largely focused on the Matrix Editor (which is my primary use for RG).
> 
> 
> ___
> Rosegarden-devel mailing list
> Rosegarden-devel@lists.sourceforge.net - use the link below to unsubscribe
> https://lists.sourceforge.net/lists/listinfo/rosegarden-devel


-- 
David Faure, fa...@kde.org, http://www.davidfaure.fr
Working on KDE Fra