Re: [Rosegarden-devel] Rosegarden Qt performance optimization
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
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
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
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
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
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