As the title says... Chat on...

User avatar
By Nubble
#16542 Hi,
I wrote my first Lua set of scripts last week and before even beginning ran out of memory- which seems to be a common thing using the nodeMcu firmware. I split my code into a few files ,removed any tables, local vars,etc to save memory. This helped a little but any indepth scripts run out of memory. imo.
[TerryE: you said you would would post a guide to save memory in nodeMcu scripts. Any update??]

Anyway, t electrodragon I see that the new Wi07-12 has 4M (from some posts I believe this is 4MBytes) of flash.
Im guessing that this would seriously help the running out of memory issue with nodeMcu, or am I on the wrong path. What do the current modules have in total?

Im thinking to order some of these 4M chips before commencing further on Lua script development.

thanks in advance
User avatar
By TerryE
#16604
Nubble wrote:TerryE: you said you would would post a guide to save memory in nodeMcu scripts. Any update?

Sorry, still on my todo list :(

I think that the main thing is that Lua essentially fields an event with associated with subroutine invocation which runs to completion at which it the garbage collects any disused code and data and optionally waits for the the next event to fire.

Events can be things like timer alarms, network on() events, an many of the hardware drivers can have associated events as well. So just make sure that you don't keep in scope links that you don't need -- e.g.
  • If an event routine has upvalues then its defining routing can't be garbage collected etc., and if has locals pointing to other functions then they might not get collected either: upvalues are bad news for event routines. Stick to globals if you want to pass context into them unless you really understand the consequences
  • Some event handlers don't properly reference their accociated event functions hence doing things like:
    Code: Select alltmr.alarm(x,10000,0,print) tmr.stop(x)
    wifi.sta.getap(type)
  • just remember that variables hold table and functions s by reference, so it is easy to collect multiple references accidentally, and as long as one stasg in scope, then the table can't be collected..
  • For example require"rtn" generates an entry package.loaded.rtn equal to the loadfile function.
My framework contains the following handler
Code: Select allLoad = setmetatable(
      {ip = c.ip, name= "Load"},
      {__index = function (this,key)   
           if key:sub(1,1)=='_' then return nil end
           return require(this.name.."_"..key)
         end
       })
where Load is one of the few globals. Hence if I have Load_fred.lua or Load_fred.lc which is a straight loadsource-type function which uses ... to read its parameters. So long as this includes the line
Code: Select allpackage.loaded.Load_fred = nil -- make routine effemeral

then I can happily do a
Code: Select allresult = Load.fred(a,b,d)
knowing that it will be loaded on demand, run and vanish like a ghost.

But what about the load overhead you may ask. Well you can time loading an lc form of a 100 line long script -- it's under 1 mSec, -- hardly an issue for an IoT device, eh?
User avatar
By TerryE
#16633
cal wrote:unfortunately more flash does only help if you file system runs out of memory. Typically you run out of ram.


Too true, but we might improve the RAM situation by leaning down the firmware build's RAM footprint. We can magic more Flash capacity out of the air. That takes a module replacement. :)