From: Ted F. <te...@te...> - 2012-10-25 01:38:43
|
Well, this is becoming quite the little nightmare. The executive overview goes something like this.... Rosegarden was designed to be a MIDI editor. Then someone decided to add MIDI sequencing to it. But what's ok for a MIDI editor (very CPU intensive updates in response to infrequent edit events from the user) is not at all ok for a MIDI sequencer (constant edit events due to massive amounts of incoming MIDI data courtesy of Herr Beethoven). This is some really complex stuff. It is going to take me months (maybe years) at my current rate of about 5 hours/week. Plan is as follows: 1. Try to understand the Segment notification mechanisms and all of the observers. This is a massive undertaking as the number of observers is very large and the observer code is quite complex. 2. Come up with a plan to fix this issue. 3. Slowly evolve the code in this new direction without disrupting things. ("Refactoring" is the popular, though misleading, term.) Unless somebody has a better idea.... Looks like I'm in this for a very long time. On the upside, this was one of the projects I really wanted to tackle. Wish I had more time than just 5 hours/week. Ted. |
From: Aere G. <Aere@Dvorak-Keyboards.com> - 2012-10-25 04:29:06
|
Ted: Given the difficulty of fixing this, along with the fact that it has never worked before in Rosegarden, I (the submitter of the bug report) consider it to be not worth fixing. I do have a work-around, if I need to record such things, namely to use MusE (which is how I recorded the version you have for testing). - Aere On Wed, 2012-10-24 at 21:38 -0400, Ted Felix wrote: > Well, this is becoming quite the little nightmare. > > The executive overview goes something like this.... Rosegarden was > designed to be a MIDI editor. Then someone decided to add MIDI > sequencing to it. But what's ok for a MIDI editor (very CPU intensive > updates in response to infrequent edit events from the user) is not at > all ok for a MIDI sequencer (constant edit events due to massive amounts > of incoming MIDI data courtesy of Herr Beethoven). > > This is some really complex stuff. It is going to take me months > (maybe years) at my current rate of about 5 hours/week. Plan is as follows: > > 1. Try to understand the Segment notification mechanisms and all of the > observers. This is a massive undertaking as the number of observers is > very large and the observer code is quite complex. > > 2. Come up with a plan to fix this issue. > > 3. Slowly evolve the code in this new direction without disrupting > things. ("Refactoring" is the popular, though misleading, term.) > > Unless somebody has a better idea.... Looks like I'm in this for a > very long time. On the upside, this was one of the projects I really > wanted to tackle. Wish I had more time than just 5 hours/week. > > Ted. > > ------------------------------------------------------------------------------ > Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_sfd2d_oct > _______________________________________________ > Rosegarden-devel mailing list > Ros...@li... - use the link below to unsubscribe > https://lists.sourceforge.net/lists/listinfo/rosegarden-devel -- Sincerely, AereSincerely, Aere Sincerely, Aere |
From: D. M. M. <ros...@gm...> - 2012-10-25 08:45:13
|
On 10/25/2012 12:28 AM, Aere Greenway wrote: > Given the difficulty of fixing this, along with the fact that it has > never worked before in Rosegarden, I (the submitter of the bug report) > consider it to be not worth fixing. We can always add it to the pile of "Live With It" bugs that are perfectly real, and just aren't ever going to get fixed for one reason or another. It would be in good company. -- D. Michael McIntyre |
From: Chris C. <ca...@al...> - 2012-10-25 08:16:44
|
On 25 October 2012 09:13, Chris Cannam <ca...@al...> wrote: > don't even try to update the actual notes on canvas. (I don't have the program in front of me atm either, and I can't actually remember offhand whether we don't show them at all or update them in batches -- either way we shouldn't be having a callback per-note and no edit commands should be firing) Chris |
From: Chris C. <ca...@al...> - 2012-10-25 08:43:40
|
On 25 October 2012 02:38, Ted Felix <te...@te...> wrote: > The executive overview goes something like this.... Rosegarden was > designed to be a MIDI editor. Then someone decided to add MIDI > sequencing to it. But what's ok for a MIDI editor (very CPU intensive > updates in response to infrequent edit events from the user) is not at > all ok for a MIDI sequencer (constant edit events due to massive amounts > of incoming MIDI data courtesy of Herr Beethoven). That's not quite an accurate characterisation -- it was always intended to be a sequencer as well. The idea is (was) that the sequencer process would operate largely asynchronously from the editor process. So when playing, the editor would write a large number of events in advance to a shared memory area, and the sequencer would play back from there. (Editing during playback would run the risk of playing the wrong thing during the edit, but would never hold up the sequencer.) When recording, the sequencer would log incoming events to a buffer and then the editor would pick them up afterwards. The main risk here of course was overflowing the buffer, but the timings should be correct so long as the sequencer thread timer was accurate. In neither case should the number or nature of editor callbacks make any difference to sequencing or recording. For the Qt4 rejig (i.e. what became Rosegarden 10.02) we merged the sequencer and editor processes -- which had previously been quite separate processes communicating using IPC mechanisms -- into separate threads in a single process. But the shared-memory architecture (all the mapped-buffer stuff) stayed the same. I'm afraid I haven't found the time to follow this bug closely, but if Rosegarden is unable to record large volumes of incoming MIDI properly, that suggests that either the inbound buffer is overflowing, or else a change during the 10.02 timescale has introduced a mutex that means writing to the buffer is no longer a safe operation for the sequencer to carry out. Or else there's been some other change that means segment updates affect recording -- segment updates shouldn't be happening in any great quantity during recording, though, because we don't even try to update the actual notes on canvas. Chris |
From: Aere G. <Aere@Dvorak-Keyboards.com> - 2012-10-25 15:04:13
|
Chris: Interesting. Thanks for the historical perspective. One piece of information that I can add, is that I'm pretty sure I originally tried to record the Beethoven piece Ted is using for testing, using the version of Rosegarden that came out with Ubuntu 8.04. That attempt at recording on that level, as I said earlier, was not successful. Which is why I stated that it has 'never' worked. - Aere On Thu, 2012-10-25 at 09:13 +0100, Chris Cannam wrote: > On 25 October 2012 02:38, Ted Felix <te...@te...> wrote: > > The executive overview goes something like this.... Rosegarden was > > designed to be a MIDI editor. Then someone decided to add MIDI > > sequencing to it. But what's ok for a MIDI editor (very CPU intensive > > updates in response to infrequent edit events from the user) is not at > > all ok for a MIDI sequencer (constant edit events due to massive amounts > > of incoming MIDI data courtesy of Herr Beethoven). > > That's not quite an accurate characterisation -- it was always > intended to be a sequencer as well. The idea is (was) that the > sequencer process would operate largely asynchronously from the editor > process. > > So when playing, the editor would write a large number of events in > advance to a shared memory area, and the sequencer would play back > from there. (Editing during playback would run the risk of playing the > wrong thing during the edit, but would never hold up the sequencer.) > > When recording, the sequencer would log incoming events to a buffer > and then the editor would pick them up afterwards. The main risk here > of course was overflowing the buffer, but the timings should be > correct so long as the sequencer thread timer was accurate. > > In neither case should the number or nature of editor callbacks make > any difference to sequencing or recording. > > For the Qt4 rejig (i.e. what became Rosegarden 10.02) we merged the > sequencer and editor processes -- which had previously been quite > separate processes communicating using IPC mechanisms -- into separate > threads in a single process. But the shared-memory architecture (all > the mapped-buffer stuff) stayed the same. > > I'm afraid I haven't found the time to follow this bug closely, but if > Rosegarden is unable to record large volumes of incoming MIDI > properly, that suggests that either the inbound buffer is overflowing, > or else a change during the 10.02 timescale has introduced a mutex > that means writing to the buffer is no longer a safe operation for the > sequencer to carry out. Or else there's been some other change that > means segment updates affect recording -- segment updates shouldn't be > happening in any great quantity during recording, though, because we > don't even try to update the actual notes on canvas. > > > Chris > > ------------------------------------------------------------------------------ > Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_sfd2d_oct > _______________________________________________ > Rosegarden-devel mailing list > Ros...@li... - use the link below to unsubscribe > https://lists.sourceforge.net/lists/listinfo/rosegarden-devel - Sincerely, Aere |
From: Ted F. <te...@te...> - 2012-10-25 11:59:01
|
On 10/25/2012 04:16 AM, Chris Cannam wrote: > (I don't have the program in front of me atm either, and I can't > actually remember offhand whether we don't show them at all or update > them in batches -- either way we shouldn't be having a callback > per-note and no edit commands should be firing) When I try to record the Beethoven piece, Rosegarden hits 120% CPU on my machine (Core i3 2.4GHz). The profiler stuff that's in there shows a massive number of calls and time spent in functions like: CompositionView::viewportPaintEvent() CompositionView::viewportPaintRect() This thing is drawing like mad. It appears to be refreshing the display over 400 times a second. And it gets worse as the recording progresses. The more notes that are in the recording segment, the more work it does. It feels like it is redrawing the entire segment, so as the segment gets larger, it takes even longer. I added profiling to the SegmentObserver related code and it is getting hammered really hard while recording. This is because recording calls Segment::insert() and Segment::erase() (multiple times for each note), both of which fire off numerous SegmentObserver notifications and set the RefreshStatus flags which cause even more work to be done. Here are the numbers of calls after recording the Beethoven piece: Segment::updateRefreshStatuses() 162862 Segment::notifyAdd() 94906 Segment::notifyRemove() 67949 Segment::notifyEndMarkerChange() 37879 The piece is 7 minutes long, so we are seeing a rate of 478 calls per second to the three Notify*() functions. updateRefreshStatuses() is getting called about 388 times per second. The profiler indicates that these are not sucking up too much time, however something else is. I'm guessing the refresh flags are triggering other parts of the system to work. Also, it might be that the profiler can't see across an update() to the corresponding paint event. High CPU usage when recording was one of the first things that I noticed about rg when I started using it a couple years ago with much less capable hardware. It's always been very high on my todo list to fix this. It may be that the problem lies in a single observer of Segment. This is one reason I'm diligently going through all observers to see if something jumps out at me. Regardless, it would probably be a good idea to redesign the Segment notification stuff so that the GUI can force notifications for every user edit, and the MIDI recording feature can just send notifications periodically, like ten times a second or so. I don't think this is going to be easy, however. In addition, Rosegarden is indeed recording the wrong things. However, I have looked at the buffers and mutexes, and everything in there seems ok. There still might be an issue, but pegging the CPU really needs to be addressed before we can be sure it isn't due to inordinate CPU usage. Ted. |
From: D. M. M. <ros...@gm...> - 2012-10-26 09:53:11
|
On 10/25/2012 07:58 AM, Ted Felix wrote: > updateRefreshStatuses() is getting called about 388 times per second. Holy crap, Batman! > Regardless, it would probably be a good idea > to redesign the Segment notification stuff so that the GUI can force > notifications for every user edit, and the MIDI recording feature can > just send notifications periodically, like ten times a second or so. I > don't think this is going to be easy, however. It sounds crazy difficult, but it would surely have all kinds of good side effects. I bet the whole system would just work much more efficiently if you could eliminate that waste and free system resources for other purposes, like avoiding xruns, and reducing the frequency with which the audio server just up and dies. -- D. Michael McIntyre |
From: D. M. M. <ros...@gm...> - 2012-10-26 12:07:26
|
On 10/26/2012 05:52 AM, D. Michael McIntyre wrote: >> Regardless, it would probably be a good idea >> to redesign the Segment notification stuff so that the GUI can force >> notifications for every user edit, and the MIDI recording feature can >> just send notifications periodically, like ten times a second or so. I >> don't think this is going to be easy, however. Just jumped back out of bed to run in here and jot down a random, probably stupid thought. Instead of untangling the skein the right way, I wonder if a less complex hack could work. Start with any custom widgets built on QWidget, change them to inherit RosegardenWidget instead, and RosegardenWidget is just QWidget with an update() method that is aware of the transport rolling status, and just returns 90% of the time by incrementing an internal counter or something. update() still gets called massively too often, but chooses to do nothing most of the time when the transport is rolling. Something like that would be fairly quick to try and see if there is any measurable positive impact on anything. There might not be, because asking the transport its status 488 times a second might be just as expensive as what we're trying to avoid doing, or even more so. If it did have some benefit, we could eventually write a zillion custom widgets just to override update() on all of them. Several such already exist just to override style stuff, and we could tack the update() stuff on those for round two of testing. Assuming you can even override update() in the first place. Probably can, but I'm half asleep, and definitely not even thinking about grazing the API docs. Like I said, probably a stupid thought. Off to bed then to let the real programmers point out why this is sheer idiocy. I don't mind. -- D. Michael McIntyre |
From: Tom B. (Tehom) <te...@pa...> - 2012-10-26 21:59:44
|
> Something like that would be fairly quick to try and see if there is any > measurable positive impact on anything. There might not be, because > asking the transport its status 488 times a second might be just as > expensive as what we're trying to avoid doing, or even more so. If it just checked m_transportStatus, that wouldn't be at all expensive. The main cost would be repeatedly acquiring m_document->getSequenceManager()->getTransportStatus() Even that must be cheap compared to drawing. I notice that because I was looking thru that code a few days ago. Tom Breton (Tehom) |
From: Ted F. <te...@te...> - 2012-10-26 12:20:18
|
On 10/26/2012 05:52 AM, D. Michael McIntyre wrote: > On 10/25/2012 07:58 AM, Ted Felix wrote: >> updateRefreshStatuses() is getting called about 388 times per second. > > Holy crap, Batman! Indeed. We're looking at almost 900 calls per second to Segment notification related functions while recording this piece. The RefreshStatus stuff appears to be an attempt to mitigate this CPU usage problem. However, it is not complete. The Segment::notify*() functions are still there and still in use. I don't think SegmentRefresh is the best solution, however, as it might lead to a system that constantly sucks some sort of idle amount of CPU. Pulling the notification calls out of the mutators (and using the notification mechanisms instead of RefreshStatus) would lead to a system that uses 0 CPU when idling. > RosegardenWidget is just QWidget with an update() method that is aware of the transport rolling status, and just returns 90% of the time That is interesting. I'll keep it in mind while walking through all the observers. It might be helpful as a stopgap measure. CompositionView stands out in the profiler output as the class that needs attention first. But it derives from QAbstractScollArea. So I guess it can't derive from RosegardenWidget instead. We would need a RosegardenAbstractScrollArea. Probably not worth the effort as the improvement is not guaranteed, and it's just a band-aid on a much bigger problem. Could be an interesting experiment, however. Ted. |
From: Ted F. <te...@te...> - 2012-10-26 12:26:33
|
On 10/26/2012 08:20 AM, Ted Felix wrote: > I don't think SegmentRefresh is the best solution, however... Correction: By SegmentRefresh, I mean either RefreshStatus or SegmentRefreshStatus. Ted. |
From: D. M. M. <ros...@gm...> - 2012-10-26 19:44:05
|
On 10/26/2012 08:20 AM, Ted Felix wrote: > needs attention first. But it derives from QAbstractScollArea. So I > guess it can't derive from RosegardenWidget instead. We would need a > RosegardenAbstractScrollArea. It's negligible effort. I'll try to slap something together after work, and see if it looks in any way interesting. Probably won't be, but it shouldn't take more than 15 minutes. (Famous last words.) -- D. Michael McIntyre |
From: Chris C. <ca...@al...> - 2012-10-27 07:17:32
|
On 26 October 2012 13:20, Ted Felix <te...@te...> wrote: > The RefreshStatus stuff appears to be an attempt to mitigate this CPU > usage problem. However, it is not complete. The Segment::notify*() > functions are still there and still in use. Historical note: the RefreshStatus mechanism actually predates the notifiers. It is indeed supposed to be a cheap way to handle aysnchronous updates, but I don't think it was ever expected even so that it would be called for every event while recording... Chris |
From: D. M. M. <ros...@gm...> - 2012-10-29 02:18:54
|
On 10/26/2012 08:20 AM, Ted Felix wrote: > We would need a RosegardenAbstractScrollArea. Probably not worth the effort as the > improvement is not guaranteed, and it's just a band-aid on a much bigger > problem. Could be an interesting experiment, however. If a band-aid can avoid major surgery nobody has time to perform... I've committed the skeleton. Hopefully I'll finish knocking it together before tonight's over, and we can see if it did anything. It's not a big effort if it all comes to naught, so it's worth trying for the merry hell of it. -- D. Michael McIntyre |