So, while we figure out a way to get a new RT-safe engine implanted into
LMMS (maybe Unison, maybe something else), and we have plans for
kickstarters and all that which is still a good idea, but meanwhile,
I've also been working on figuring out the possibilities for improving
the current engine. Can't hurt to try, right? And it's still doubtful if
the "new engine kickstarter" idea will ever even work out, so it's
better to keep doing something.

So, I've had some very interesting discussions on irc about this
subject, HarryHaaren in particular has been very helpful. So, here are
some things we've come up with.


1. Is the removal of the global mixer lock. Entire removal.

This is work which I'm already working on, slowly but surely, and in
fact I just merged the banish-all-locks branch to master, which is
another step towards removing the need for global mixer lock. What still
needs to be done is hunt through the code for all places that lock the
global lock, and change them so that they use other methods instead -
smaller local locks, or some fancy trickery with atomics or other things
that subvert the need for mixer thread locking.

This is important because the mixer thread must be non-blocking. The
mixer thread must never be in a situation where it has to wait for other
threads to fiddle things. Other threads (GUI and such) should do their
work in such a way that the mixer thread can keep on chuggin' while they
do it.


2. Removal of excessive dynamic allocation of objects during playing.

This needs a bit of layman-exposition. The problem is the way we handle
notes. When notes are played (either live notes or from the pattern),
every time a note starts, a new NotePlayHandle -object is constructed.
This is bad, because when objects are constructed in that way, they get
allocated in the heap, which is a costly, non-RT-safe operation -
meaning, it can't be predicted how long it will take to allocate the
memory. Heap memory allocations should be avoided for that reason.

So what we should do is instead cache the notes and re-use them, so we
don't have to keep constantly allocating and deallocating heap memory. I
have a hunch that doing this would hugely improve RT-safety and cut down
on CPU-spikes, making LMMS faster, and making my project files actually
listenable without exporting...

So for starters, I'm thinking of setting a discrete "polyphony limit"
for all instruments: say, every instrument track gets 128 static
NotePlayHandles, which get used and re-used, but never
destructed/constructed, instead their state is just reset. Later on, we
can make this polyphony limit configurable, so that if there are corner
cases where you need more than 128 notes playing at the same time, you
can just increase the limit. Even later on, we can make some kind of
auto-extension mechanism, which automatically increases the polyphony
limit on a track-by-track basis when needed, but for starters I think a
static amount is fine.


2.5. NotePlayHandles aren't the only thing suffering from problem #2

Instruments also allocate new synth objects for each note, and attach
them to NotePlayHandles. The same fix can be applied here: the synth
objects can also be cached and reused, and they can use the same
polyphony limit as the NPH's.


3. Speaking of NotePlayHandles - revise the handling of subNotes, ie.
chords/arpeggios

When chords/arpeggios are enabled, they work by creating subNotes for
each NotePlayHandle. These subNotes not only have all the problems that
NotePlayHandles have (see #2), but they're also handled very
inefficiently: subNotes are added into an array inside the parent NPH,
and they're then processed linearily within the processing function of
the parent NPH.

Obviously, it would be more effective to process the subNotes in
parallel, multi-threadedly. So what we'll do is, change subNotes so that
they become ordinary NPH's and use the same cacheable/reusable NPH's in
the polyphony stack (see #2), and the parent note will only contain
pointers to them. The parent note can still control the
activation/deactivation of the subNotes like it does now.

------

There are some additional other things where we can improve things by
caching and recycling, but I think listing all of them would get a bit
repetitive and boring, so I won't - feel free to ask if you're
interested, person who has managed to read this email all the way here.

Anyway, all of these things listed here are very much doable, even with
our current resources. Meaning, that I'm able to imagine in my brain
ways to actually make them happen. I also think these can potentially
hugely improve the core of LMMS and produce a not insignificant
performance boost.

So for now, all other plans for 1.2 are taking back seat, and this
improvement of core functions is getting priority. Of course, I'm only
speaking for myself, everyone else is still free to work on whatever
they want to work on... for example, grejppi is making some good
progress on his LV2 branch, I wouldn't ask him to interrupt that.

------------------------------------------------------------------------------
_______________________________________________
LMMS-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lmms-devel

Reply via email to