Lua scripts - saving memory

Post Reply
jfrickmann
Posts: 2
Joined: Tue Nov 21, 2017 10:58 pm
Country: -

Lua scripts - saving memory

Post by jfrickmann »

Hi All,

I have been developing a setup for DLG/F3K gliders for 2-3 years now, which I posted over on RCGroups. As I added new features to the program, memory issues became ever more prominent, and with the latest update, I finally ran out of memory for good, and had to do something radical to cut down on memory usage. I have found some general solutions that work very well, and I want to share them here.

First of all, I added a "library" of shared code and variables by adding a function script that is run one time only. I found this was a good way to share stuff between different telemetry and function scripts.

Secondly, I created a system for transparently loading code when it is needed and unloading when not needed. Here is that part of the above mentioned "library" function script:

Code: Select all

-- JF F3K Library
-- Timestamp: 2017-11-06
-- Created by Jesper Frickmann
-- Has a few shared functions and variables for telemetry and functions scripts
-- Works together with a small shell script to load and unload program and telemetry scripts.
-- Method for loading and unloading telemetry scripts was provided by Guido ter Horst "l shems"

-- For loading and unloading of programs with the small shell script
local programs = {} -- List of loaded programs
local states = {} -- Program states are used for managing loading and unloading
local locked = false -- Lock to ensure that only one program is loaded at a time
local ST_WAITING = 0 -- Wait and mark other programs before loading
local ST_STANDBY = 1 -- Marked programs are swept; standing by for loading
local ST_LOADED = 2 -- Program loaded but not yet initialized
local ST_RUNNING = 3 -- Program is loaded, initialized, and running
local ST_MARKED = 4 -- Programs are marked inactive and swept if not running

-- Load program or forward run() call to the program
function LdRun(file, event)
	if states[file] == nil then
		-- First, acquire the lock
		if locked then
			return
		else
			locked = true
		end
		
		-- Wait and sweep inactive programs before loading
		DrawMenu(" Loading . . .", 0, 0)

		-- Mark all programs as inactive
		for f in pairs(states) do
			states[f] = ST_MARKED
		end

		-- Except this one, which is waiting
		states[file] = ST_WAITING
	elseif states[file] == ST_WAITING then
		-- Sweep inactive programs
		for f, st in pairs(states) do
			if st == ST_MARKED then
				programs[f] = nil
				states[f] = nil
			end
		end
		states[file] = ST_STANDBY
		return collectgarbage()
	elseif states[file] == ST_STANDBY then
		-- Load the program
		local chunk, err = loadScript(file) 

		if chunk then
			programs[file] = chunk()
			states[file] = ST_LOADED			
			return collectgarbage()
		else
			err = string.gsub(err, file .. ":", "")
			lcd.clear()
			lcd.drawText(0, 0, "ERROR loading the script:", SMLSIZE)
			lcd.drawText(0, 10, file, SMLSIZE)
			lcd.drawText(0, 20, err, SMLSIZE)
		end
	elseif states[file] == ST_LOADED then
		states[file] = ST_RUNNING
		locked = false

		-- Pass an init() call to the loaded program
		if programs[file].init then
			return programs[file].init()
		end
	elseif programs[file].run then
		states[file] = ST_RUNNING
		
		-- Pass on the run(event) call to the loaded program
		return programs[file].run(event)
	end
end -- LdRun()

return {}
For each telemetry or function script that needs to be dynamically loaded and unloaded, a "shell script" like the following is used as the script specified in the OpenTX setup:

Code: Select all

-- JF Autoloader
-- Timestamp: 2017-11-02
-- Created by Jesper Frickmann
-- Telemetry script for automatically loading and unloading telemetry scripts
-- Depends on library functions in FUNCTIONS/JFLib.lua

local myFile = "/SCRIPTS/TELEMETRY/JF-LDG.lua" -- Lua file to be loaded and unloaded

local function run(event)
	return LdRun(myFile, event)
end

return {run = run}
As you can see, the only thing that the shell script does, is forwarding the run() call to the library function LdRun() with the file path and the event arguments. So each shell script takes very little memory. And the script files to be loaded do not need other modification than the obvious that they cannot rely on a background() call, as they are subject to being removed when they are in the background.

Please free to comment and ask questions!

Jesper

Post Reply

Return to “openTx for FrSky radios”