The position of an object effects the amount of SRAM it uses?


#1

I have a patch that I've been optimizing for a few days now. It compiles/loads fine currently, but it is right on the edge of using all of the available SRAM as I remove knobs, etc. in an attempt to eke out as much functionality as possible.

So I move a CONST/i up to a different position in my patch and suddenly I'm over the SRAM limit by 32 bytes. I move it back and the patch compiles fine.

Can someone explain this to me as well as best practices to mitigate SRAM usage as it relates to the position of objects in the patcher?


Need help with SRAM usage and custom objects
#2

I'm not sure. Could it be an execution order thing? Is the const/i object above the object it's connected to?

I'm interested in answers to this because I've had some pretty weird things happen when the patch gets this big. Stuff like I've removed some unused inlets/parameters and it's lowered the sram usage, then done exactly the same thing in a second instance of the same object and the sram overflows. And I've also deleted objects and the sram overflows. How would deleting things use more sram?

I assume it's something I'm not understanding about the way the patch is compiled or processed.


#3

I don't recall. I believe it was below both times, however both its horizontal position and vertical changed between the working patch and the overflow version.

After encountering this I purposely put the patch over the SRAM limit and then started to move objects around to see how much over the limit I would be with each movement. It definitely changed each time I moved something however I definitely couldn't predict how it would change. Sometimes it appeared as though I bought a couple hundred bytes by moving a group of objects vertically higher, but then if I tried to buy more free memory by moving up similar objects I would lose it all and then some.

Your comment about other weird quirks makes me question if this phase of "optimization" even bought me any memory at all as I deleted the object that put me over the limit, so for all I know that "reset" any gained resources.


#4

it's "random"... if you hit the sram limit, moving objects around may help.

generally execution order is left to right and top to bottom. so try to avoid upwards connections and right to left connections.

that being said i have seen times when embedding a custom object reduced sram and times where it increased the usage. i removed GUI elements from objects that i did not need and sometimes sram usage increased...


#5

Thanks, hearing that it is "random" and expected behavior actually makes me feel a little better about everything. My takeaway is: Build your patches logically top-bottom/left-right and if you're hitting the SRAM limit, you might be able to jiggle the handle to get over the hump, but don't rely on it.


#6

Just a quick pointer to back here. Presumably, if the order of declaring variables within an object can make a difference, so can ordering of objects that each declare variables. Not helpful in predicting the effects, I know, but maybe helpful to understand the mystery...__


#7

It's not completely random, but the order of the modules does affect the amount of SRAM used, because with a less ideal ordering of the modules, the patcher may need to add temporary variables to hold the values of the various signals.

Basically, the patcher puts the runtime code for all the objects after each other, which is decided by their graphical position in the patch, and then completes the connections between the inlets and outlets. The code is then run in a loop, one sample at a time (this is a simplification, because the Axoloti actually processes 16 samples (k-rate vs. s-rate) at a time, but for the purposes of this discussion this is not important).

Now, say there are two modules in a patch, one sending to another, like an oscillator to an output module. If the oscillator ends up being placed after the output module in a patch, the patcher has to create a temporary variable to hold the output from the oscillator for the next loop when the output module can pick it up on its inlet. This happens automatically so the user doesn't have to worry about module ordering - until there is a shortage of SRAM, when it becomes a very concrete problem.

Hm, here's a thought, it would be nice if the patcher could output the number of such temporary variables it needs to create when the module order is less than ideal, so that it would be easy to check the efficiency of ones patch. In a real patch, it can be hard to eliminate out-of-order modules, but one could at least try to minimize them.


#8

but.... this should be taken care of by left right top to bottom ordering and no upwards connections. however the "problems" i am seeing are really more "random" than that. moving an object around just a few pixels (preserving the downward connection) can change sram usage significantly. so there must be something else going on.

i have even seen cases, where an upward connection decreased sram usage.

i have to say though that this is all with patches that are hitting the limit of sram. so maybe there is some "bug" when you are near the limit. but that is of course also the one case where it is really frustrating. you try to optimise the patch by removing gui stuff etc. and end up eating up more sram. :frowning:


#9

Is there even any indication of the amount of SRAM being used beyond the overflow message you get when you make a patch "live?" I'd like to know how much SRAM I have to play with even when a patch hasn't hit the limit for example.


#10

The SRAM used shows in the patcher info window each time you load a patch into Axloti Core - even if you have not reached overflow. But I don't know if it can be seen before loading (trying to load...) a patch.


#11

Is it this:

And if so, how do I interpret this? What are my limits?


#12

I could be remembering this incorrectly, but I seem to recall that "above" and "below" refer to where the top left pixel of the objects are located relative to each other, regardless of their left-right orientation. So if two objects are located side by side, and the top left pixel of the right hand one is slightly above the left hand one, it is considered to be 'above' it. But as I say this could be wrong, I can't remember how I arrived at that conclusion or if I read it somewhere.


#13

interesting, i will have to tinker with it some more then. i was under the impression that cable connections just have to be downwards i.e. inlet position has to be below outlet position of the other object.


#14

Yeah, i'm pretty sure I read about the top left pixel thing. I've always thought of execution order as being from the very top of the object, not from where the inlets and outlets themselves are.


#15

@MattilynMattroe: Yeah, that's been my impression too.


#16

I'm fairly new to the Axoloti, but the way I understand it is that it executes (as mentioned before) from left to right, top to bottom, with the top-left pixel of the object as the determining point.

Based on that the code is generated, the code will be compiled and optimized accordingly.
The optimization step is the tricky part, because that determines what needs to be stored where and for how long / in what scope. (Optimization tries to keep local things local - unless your specified execution order tells it it can't do that)

Thus, changing the position of objects determines how the compiler optimizes the code.
Changing the position of an object can mean variables have to be stored on the stack respectively in or outside other code blocks, changing the memory usage accordingly.

As it's pretty hard to predict the final optimized compiled byte code from the wysiwyg ui, it will be a matter of trial and error repositioning objects - unless you want to take the effort to dig down into the compiled code to see what's going on.


#17

When I learned this, I started making all of my patches long horizontal rows.