Questions about patch optimization/abstractions
So my main performance patch is getting big. Like really big. It’s 64 files worth of stuff now (a lot of polys and soundfiles) and the main file itself is 16mb.
I’ve been trying to optimize as I go, but I there’s a lot I don’t know about this stuff, so I’m just taking stabs in the dark.
Another thing is that as big as the patch is, there’s no abstractions at all (only polys).
Here’s a picture of the guts (this is about 1/10th of the visible patch (while unlocked)):
As a reference, it does clean up nice:
So my first(main) question is about abstractions I guess. Is it good practice to make everything abstractable into an abstraction? I find myself using certain things over and over, and certain parts of the patch are duplicates (ie the main looper code). So should I just make them abstractions? How small or big should I go? As in should I make the playback section of my looper an abstraction, or make the whole of it (nearly the whole screenshot above) an abstraction?
Is the use of abstractions this way (and in a patch this big) mainly for ease of coding, or is it more efficient too?
I’ve leaned away from using them as I find myself often going back and editing/fixing things, and I hate having to go back and forth to edit things (all of my polys are pretty much static effects, so I rarely touch the code once it was wrapped up).
The next question is about general patching and structure. There’s oodles of send/receives in my patch. Some are from other sections of the patch (OSC/MIDI control sections etc..), but a bunch are within the screenshot amount of space. My original (poor) thinking was that when I need to duplicate the section, I can copy/paste and then rename the send/receives (as seen in the screenshot). That’s not a great idea, but it does make troubleshooting and visibility better as I know what’s what by looking, and don’t have to click/trace cables.
So I guess the question here is, is having so many send/receives (not audio ones) inefficient?
Lastly, buffers. I have a bunch of buffers throughout the patch that are holding either impulse responses, or tiny samples for triggering etc.. These samples aren’t big by any means, but does taking up buffer/ram space effect performance much? (in terms of CPU/processing, I’m not hitting or near my total RAM available). It’s only 2.5mb total (over 23 files), but this is likely going to go up. Is it worth the work to make my reverb/convolution sections just 1 buffer that loads samples dynamically (as opposed to how I’m doing it now, with all buffers loaded, and I change the code dynamically).
In total my patch idles between 20-30% (with all polys muted etc..) and can go as high as 70 or so (probably higher as there’s some high CPU polys in there, but I rarely use them all at once). I’ve mainly used an I/O vector size of 128, but when I use kontakt I have to go up to 256 (or even 512) or I get crunching coming out of kontakt (which is a bummer). My patch is only getting bigger, so I want to do as much as I can to keep it lean on the way up.
There also seems to be very little in terms of ‘general coding practices for efficiency’ on the forum (at least not 5 years old and/or jitter related).
i found a generic rule about "how small should you go", which is that modules should be always about the same size.
encapsulating 1 object only, or encapsulating a fullfeatured application should be the exception.
also, try to create aubpatches in amanner so that they do not need many inputs.
encapsulate things in amannner that you encapsulate the "many connections" part of your patch.
and you should make a difference between "abstraction" and "subpatcher".
an abstraction is something which is so generic that it will be used in other projects, too.
you looper patcher is specific for this app, so it is not an abstraction. i would still make a file
from it if i need 4 instances, mainly because it can be easier during programming.
That makes sense. Abstractions for general patching, and subpatcher for project specific.
Is there any performance difference between the two?
I’ve been glued to subpatchers as it lets me edit/adjust the code much easier, but many sections of the patch are frozen, so I might start wrapping things into abstractions.
no, patch is patch.
the only difference is that you put your abs in you abs folder, and the specific stuff will go somewhere near the main patcher of the project. :)
i have edited my first answer and added the rule of not too much inlets.
this goes together with what nicolas says; while thinking about where to make the interface
between modules, you adopt the sctructure in your mind, and eventually this also
forces you to optimize and thin the code.
I distribute my patch, so keeping things in the abstraction folder would really jam up my exporting workflow. So I would just leave things living in the patch folder.
So what can you do to improve performance?
I’ve wrapped bypassable or engageable things in polys for muting when not using them (and bang them muted on startup). I’ve tried to use [line 0.] instead of line~ when it only use it sometimes (though all my bypassing is line~ and !-~ 1 based).
I only have a couple of send~/receive~ pairs, and only when it’s unfeasable to have a cable going across three screens worth of patch.
in that case, name all your abstractions project-specific, then you can
copy the ones you like later into your custom abs location (which you
should really have), and rename them.
upward) should go into a poly so that it can be turned off, and in the case
of sequencers/overdrive on runtimes get rid of all GUI stuff (flonum, sliders)
in the hidden code.