Real time note transmittor / splitter

Great @NewIgnis ! One question, how do you see the available memory/how much you have consumed?

I have the same question sent to Martin.

for now, the only way is sending a sysex to the CTRL port:

F0 00 21 45 02 7E F7

…returns info about free memory

@martin I’ve been coding for a week a full app in LUA . The console says 37% free Ram, but I just hit the dreaded error=not enough memory in LUA. So seems that the console ram is not what LUA uses, right? By making tests, I found out that the variable names DO COUNT as space (since it is interpreted). Currently have been coding 47K, and the code is crystal clear. Is my only option to have really short variable names to make it fit in memory? How much is the memory allocated to LUA? Is there any way we can allocate more even if we just run one preset?

1 Like

Electra One console updates the info about RAM just after the preset is loaded. That means that if you allocate memory after that moment, it will not be reflected in console app. Electra keeps info about free ram and has a C++ interface to retrieve it. I will add a Lua interface for it. That means you would be able to get exact info whenever you need.

The free (or available) RAM is shared. There is no dedicated memory segment for Lua. There are three parties that use it. The base system - around 50k, the rest goes to the preset and Lua. Depending on the size of Preset Lua has something between 190k - 40k RAM available. There is always only one preset in the memory.

The Lua garbage collection is forced to run at least once in 10secs. I can imagine this could be too long in certain situations. We can try to adjust that. In general I suspect that the issue is not about not having free memory, but possibly having the memory fragmented so that a new allocation does not fit anywhere. I am planning to work intensively with the Notes Transmittor to see what is happening there. If you provide me the link to your preset I can use it for tracing the memory usage too.

I could play the Notes Splitter for about half an hour yesterday before it froze without any warning. So behaviour in the beta 3.0 is now very similar as in the regular firmware.

I have been making some tests on how to lower the memory of my code. I indeed never had issues with long variable names using spaces (the beauties of compiled code). anyway, I did find a way by reducing lots of stuff and being more careful on saving resources, and that allowed me to proceed :slight_smile:
Im actually using over 500 controls in this preset (obviously that is not possible, but that is the beauty of reusing stuff)

1 Like

Hey @NewIgnis , I think the freezing of the Electra One you did experienced after playing 30 minutes was due to a heap-stack crash. In your code, you create tables all the time, and different sizes. that fragments the memory, little by little, until one moment the stack gets right in the heap.

Thanks for looking into. Thankfully most tables are used for configuration purposes so they don’t change often. In order however to do proper voice allocation I need three dynamics tables, into which I add info on top and take out elements from the bottom. Any suggestions on how to avoid those memory leaks?

Would the problem be 100% solved if the tables were made fairly large (let’s say 256 entries each), but instead of changing its size, I’d rather change the individual content of each member and use a pointer to hint to the current member?

Give me some time, in the weekend i’ll make some tests to see what I can find. Maybe it is not a leak, but a fragmentation issue. and i’m a newbie at lua, i don’t know how the gc works, but since it’s close to C, i’m assuming table manipulation (pointers) are the culprit.

i already have some ideas on how to test it. :slight_smile:

1 Like

thanks, appreciated!

And yes, pre allocation of tables is the solution! but uses too much memory.

try making a control button to start and stop a loop, and inside that loop, put a do-end block that sends a note to your system, outside the do-end block, a garbage collection count (and print it to console) that way you can measure leaks and, more importantly, make it crash sooner.

I made some tests to see memory defragmentation using regular table management, and the solution is indeed pre-population of tables.

  1. Tables that contains elements that are added and removed, need to be pre-populated:

t = {false, false, false, false, false, ...}

  1. Put this in your code BEFORE you use the original table library:
allocTable = {
    -- insert a value to the end of the table.
    -- if no space remains, nothing will be done.
    -- Table, Element
    insert = function(t, v) -- Table, Value
        for i = 1, #t do
            if (t[i] == false) then 
                t[i] = v
                return
            end
        end

        return
    end,
    -- removes a value from the table, shifting everything to the left.
    remove = function(t, v) -- Table, Value
        if (not allocTable.has(t, v)) then return end
        local prev = false
        local tmp
        for i = #t, 1, -1 do
            tmp = t[i]
            t[i] = prev
            if (tmp == v) then return end
            prev = tmp
        end
    end,
    -- returns index if value is found in the table
    -- false if not found
    has = function(t, v)
        for i = 1, #t do
            if (t[i] == v) then 
                return i
            end
        end

        return false
    end,
    -- counts not false values in the table
    count = function(t)
        local c = 0
        for i = 1, #t do
            if t[i] then 
                c = c + 1
            end
        end
        
        return c
    end
}

  1. And then replace the current table library with it. This will change the behavior of all the table.remove() and table.insert() calls.
table = allocTable
  1. The not-so-easy part: All table counts tableName# of those tables need to be replaced by table.count(tableName)

Good luck!

3 Likes