From 435ded0c60906c6db23e6567da3ca2c13ce42eb6 Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Mon, 31 Aug 2015 19:56:21 +0200 Subject: [PATCH 1/2] gluon-announce: build a tree of functions first collect_dir() will now pre-load all files and return a function that will collect all information. --- .../files/usr/lib/lua/gluon/announce.lua | 28 +++++++++++++------ .../files/usr/lib/lua/gluon/announced.lua | 7 ++++- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua b/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua index 444dbd33..8a91e6f8 100644 --- a/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua +++ b/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua @@ -10,24 +10,36 @@ local function collect_entry(entry) if fs.stat(entry, 'type') == 'dir' then return collect_dir(entry) else - return setfenv(loadfile(entry), _M)() + return loadfile(entry) end end function collect_dir(dir) - local ret = { [{}] = true } + local fns = {} for entry in fs.dir(dir) do if entry:sub(1, 1) ~= '.' then - local ok, val = pcall(collect_entry, dir .. '/' .. entry) - if ok then - ret[entry] = val + local fn, err = collect_entry(dir .. '/' .. entry) + if fn then + fns[entry] = fn else - io.stderr:write(val, '\n') + io.stderr:write(err, '\n') end end end - return ret -end + return function () + local ret = { [{}] = true } + for k, v in pairs(fns) do + local ok, val = pcall(setfenv(v, _M)) + if ok then + ret[k] = val + else + io.stderr:write(val, '\n') + end + end + + return ret + end +end diff --git a/package/gluon-announced/files/usr/lib/lua/gluon/announced.lua b/package/gluon-announced/files/usr/lib/lua/gluon/announced.lua index a9de80e6..af2291fe 100644 --- a/package/gluon-announced/files/usr/lib/lua/gluon/announced.lua +++ b/package/gluon-announced/files/usr/lib/lua/gluon/announced.lua @@ -2,9 +2,14 @@ local announce = require 'gluon.announce' local deflate = require 'deflate' local json = require 'luci.jsonc' +local memoize = {} local function collect(type) - return announce.collect_dir('/lib/gluon/announce/' .. type .. '.d') + if not memoize[type] then + memoize[type] = announce.collect_dir('/lib/gluon/announce/' .. type .. '.d') + end + + return memoize[type]() end From 9dffb1284ffed3b1efaccca292c6fbe009993f5b Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Tue, 1 Sep 2015 18:09:00 +0200 Subject: [PATCH 2/2] gluon-announce(d): preload functions, collectgarbage By calling collectgarbage() at various places I was able to reduce heap usage by ~270kb. --- .../files/usr/lib/lua/gluon/announce.lua | 6 ++++ .../files/usr/lib/lua/gluon/announced.lua | 30 +++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua b/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua index 8a91e6f8..29a1f817 100644 --- a/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua +++ b/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua @@ -19,7 +19,9 @@ function collect_dir(dir) for entry in fs.dir(dir) do if entry:sub(1, 1) ~= '.' then + collectgarbage() local fn, err = collect_entry(dir .. '/' .. entry) + if fn then fns[entry] = fn else @@ -32,7 +34,9 @@ function collect_dir(dir) local ret = { [{}] = true } for k, v in pairs(fns) do + collectgarbage() local ok, val = pcall(setfenv(v, _M)) + if ok then ret[k] = val else @@ -40,6 +44,8 @@ function collect_dir(dir) end end + collectgarbage() + return ret end end diff --git a/package/gluon-announced/files/usr/lib/lua/gluon/announced.lua b/package/gluon-announced/files/usr/lib/lua/gluon/announced.lua index af2291fe..f6863277 100644 --- a/package/gluon-announced/files/usr/lib/lua/gluon/announced.lua +++ b/package/gluon-announced/files/usr/lib/lua/gluon/announced.lua @@ -1,26 +1,29 @@ local announce = require 'gluon.announce' local deflate = require 'deflate' local json = require 'luci.jsonc' +local nixio = require 'nixio' +local fs = require 'nixio.fs' local memoize = {} -local function collect(type) - if not memoize[type] then - memoize[type] = announce.collect_dir('/lib/gluon/announce/' .. type .. '.d') - end +nixio.chdir('/lib/gluon/announce/') - return memoize[type]() +for dir in fs.glob('*.d') do + local name = dir:sub(1, -3) + memoize[name] = announce.collect_dir(dir) end +local function collect(type) + return memoize[type] and memoize[type]() +end module('gluon.announced', package.seeall) function handle_request(query) - if query:match('^nodeinfo$') then - return json.stringify(collect('nodeinfo')) - end + collectgarbage() local m = query:match('^GET ([a-z ]+)$') + local ret if m then local data = {} @@ -32,7 +35,16 @@ function handle_request(query) end if next(data) then - return deflate.compress(json.stringify(data)) + ret = deflate.compress(json.stringify(data)) + end + elseif query:match('^[a-z]+$') then + local ok, data = pcall(collect, query) + if ok then + ret = json.stringify(data) end end + + collectgarbage() + + return ret end