Tie in the EGC with the SDK's heap knowledge. (#2319)
Added `node.egc.meminfo()` to expose LVM usage (to make the regular `node.egc.ON_MEM_LIMIT` option usable). Extended the `node.egc.ON_MEM_LIMIT` option to also take negative limits, in which case that's taken as a request to keep a certain amount of heap available for non-Lua use.
This commit is contained in:
parent
18f33f5ff1
commit
085f35da73
|
@ -14,6 +14,7 @@
|
||||||
#include C_HEADER_STRING
|
#include C_HEADER_STRING
|
||||||
#ifndef LUA_CROSS_COMPILER
|
#ifndef LUA_CROSS_COMPILER
|
||||||
#include "vfs.h"
|
#include "vfs.h"
|
||||||
|
#include "user_interface.h"
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -791,6 +792,11 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
|
||||||
}
|
}
|
||||||
if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */
|
if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */
|
||||||
luaC_fullgc(L);
|
luaC_fullgc(L);
|
||||||
|
#ifndef LUA_CROSS_COMPILER
|
||||||
|
if (L != NULL && (mode & EGC_ON_MEM_LIMIT) && G(L)->memlimit < 0 &&
|
||||||
|
(system_get_free_heap_size() < (-G(L)->memlimit)))
|
||||||
|
luaC_fullgc(L);
|
||||||
|
#endif
|
||||||
if(nsize > osize && L != NULL) {
|
if(nsize > osize && L != NULL) {
|
||||||
#if defined(LUA_STRESS_EMERGENCY_GC)
|
#if defined(LUA_STRESS_EMERGENCY_GC)
|
||||||
luaC_fullgc(L);
|
luaC_fullgc(L);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
|
|
||||||
void legc_set_mode(lua_State *L, int mode, unsigned limit) {
|
void legc_set_mode(lua_State *L, int mode, int limit) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
|
|
||||||
g->egcmode = mode;
|
g->egcmode = mode;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit
|
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit
|
||||||
#define EGC_ALWAYS 4 // always run EGC before an allocation
|
#define EGC_ALWAYS 4 // always run EGC before an allocation
|
||||||
|
|
||||||
void legc_set_mode(lua_State *L, int mode, unsigned limit);
|
void legc_set_mode(lua_State *L, int mode, int limit);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ typedef struct global_State {
|
||||||
Mbuffer buff; /* temporary buffer for string concatentation */
|
Mbuffer buff; /* temporary buffer for string concatentation */
|
||||||
lu_mem GCthreshold;
|
lu_mem GCthreshold;
|
||||||
lu_mem totalbytes; /* number of bytes currently allocated */
|
lu_mem totalbytes; /* number of bytes currently allocated */
|
||||||
lu_mem memlimit; /* maximum number of bytes that can be allocated, 0 = no limit. */
|
l_mem memlimit; /* maximum number of bytes that can be allocated, 0 = no limit. <0 used with EGC_ON_MEM_LIMIT when free heap falls below -memlimit */
|
||||||
lu_mem estimate; /* an estimate of number of bytes actually in use */
|
lu_mem estimate; /* an estimate of number of bytes actually in use */
|
||||||
lu_mem gcdept; /* how much GC is `behind schedule' */
|
lu_mem gcdept; /* how much GC is `behind schedule' */
|
||||||
int gcpause; /* size of pause between successive GCs */
|
int gcpause; /* size of pause between successive GCs */
|
||||||
|
|
|
@ -462,14 +462,23 @@ static int node_stripdebug (lua_State *L) {
|
||||||
// See legc.h and lecg.c.
|
// See legc.h and lecg.c.
|
||||||
static int node_egc_setmode(lua_State* L) {
|
static int node_egc_setmode(lua_State* L) {
|
||||||
unsigned mode = luaL_checkinteger(L, 1);
|
unsigned mode = luaL_checkinteger(L, 1);
|
||||||
unsigned limit = luaL_optinteger (L, 2, 0);
|
int limit = luaL_optinteger (L, 2, 0);
|
||||||
|
|
||||||
luaL_argcheck(L, mode <= (EGC_ON_ALLOC_FAILURE | EGC_ON_MEM_LIMIT | EGC_ALWAYS), 1, "invalid mode");
|
luaL_argcheck(L, mode <= (EGC_ON_ALLOC_FAILURE | EGC_ON_MEM_LIMIT | EGC_ALWAYS), 1, "invalid mode");
|
||||||
luaL_argcheck(L, !(mode & EGC_ON_MEM_LIMIT) || limit>0, 1, "limit must be non-zero");
|
luaL_argcheck(L, !(mode & EGC_ON_MEM_LIMIT) || limit!=0, 1, "limit must be non-zero");
|
||||||
|
|
||||||
legc_set_mode( L, mode, limit );
|
legc_set_mode( L, mode, limit );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// totalallocated, estimatedused = node.egc.meminfo()
|
||||||
|
static int node_egc_meminfo(lua_State *L) {
|
||||||
|
global_State *g = G(L);
|
||||||
|
lua_pushinteger(L, g->totalbytes);
|
||||||
|
lua_pushinteger(L, g->estimate);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Lua: osprint(true/false)
|
// Lua: osprint(true/false)
|
||||||
// Allows you to turn on the native Espressif SDK printing
|
// Allows you to turn on the native Espressif SDK printing
|
||||||
|
@ -560,6 +569,7 @@ static int node_random (lua_State *L) {
|
||||||
// Module function map
|
// Module function map
|
||||||
|
|
||||||
static const LUA_REG_TYPE node_egc_map[] = {
|
static const LUA_REG_TYPE node_egc_map[] = {
|
||||||
|
{ LSTRKEY( "meminfo" ), LFUNCVAL( node_egc_meminfo ) },
|
||||||
{ LSTRKEY( "setmode" ), LFUNCVAL( node_egc_setmode ) },
|
{ LSTRKEY( "setmode" ), LFUNCVAL( node_egc_setmode ) },
|
||||||
{ LSTRKEY( "NOT_ACTIVE" ), LNUMVAL( EGC_NOT_ACTIVE ) },
|
{ LSTRKEY( "NOT_ACTIVE" ), LNUMVAL( EGC_NOT_ACTIVE ) },
|
||||||
{ LSTRKEY( "ON_ALLOC_FAILURE" ), LNUMVAL( EGC_ON_ALLOC_FAILURE ) },
|
{ LSTRKEY( "ON_ALLOC_FAILURE" ), LNUMVAL( EGC_ON_ALLOC_FAILURE ) },
|
||||||
|
|
|
@ -484,7 +484,7 @@ provides more detailed information on the EGC.
|
||||||
- `mode`
|
- `mode`
|
||||||
- `node.egc.NOT_ACTIVE` EGC inactive, no collection cycle will be forced in low memory situations
|
- `node.egc.NOT_ACTIVE` EGC inactive, no collection cycle will be forced in low memory situations
|
||||||
- `node.egc.ON_ALLOC_FAILURE` Try to allocate a new block of memory, and run the garbage collector if the allocation fails. If the allocation fails even after running the garbage collector, the allocator will return with error.
|
- `node.egc.ON_ALLOC_FAILURE` Try to allocate a new block of memory, and run the garbage collector if the allocation fails. If the allocation fails even after running the garbage collector, the allocator will return with error.
|
||||||
- `node.egc.ON_MEM_LIMIT` Run the garbage collector when the memory used by the Lua script goes beyond an upper `limit`. If the upper limit can't be satisfied even after running the garbage collector, the allocator will return with error.
|
- `node.egc.ON_MEM_LIMIT` Run the garbage collector when the memory used by the Lua script goes beyond an upper `limit`. If the upper limit can't be satisfied even after running the garbage collector, the allocator will return with error. If the given limit is negative, it is interpreted as the desired amount of heap which should be left available. Whenever the free heap (as reported by `node.heap()` falls below the requested limit, the garbage collector will be run.
|
||||||
- `node.egc.ALWAYS` Run the garbage collector before each memory allocation. If the allocation fails even after running the garbage collector, the allocator will return with error. This mode is very efficient with regards to memory savings, but it's also the slowest.
|
- `node.egc.ALWAYS` Run the garbage collector before each memory allocation. If the allocation fails even after running the garbage collector, the allocator will return with error. This mode is very efficient with regards to memory savings, but it's also the slowest.
|
||||||
- `level` in the case of `node.egc.ON_MEM_LIMIT`, this specifies the memory limit.
|
- `level` in the case of `node.egc.ON_MEM_LIMIT`, this specifies the memory limit.
|
||||||
|
|
||||||
|
@ -495,6 +495,23 @@ provides more detailed information on the EGC.
|
||||||
|
|
||||||
`node.egc.setmode(node.egc.ALWAYS, 4096) -- This is the default setting at startup.`
|
`node.egc.setmode(node.egc.ALWAYS, 4096) -- This is the default setting at startup.`
|
||||||
`node.egc.setmode(node.egc.ON_ALLOC_FAILURE) -- This is the fastest activeEGC mode.`
|
`node.egc.setmode(node.egc.ON_ALLOC_FAILURE) -- This is the fastest activeEGC mode.`
|
||||||
|
`node.egc.setmode(node.egc.ON_MEM_LIMIT, 30720) -- Only allow the Lua runtime to allocate at most 30k, collect garbage if limit is about to be hit`
|
||||||
|
`node.egc.setmode(node.egc.ON_MEM_LIMIT, -6144) -- Try to keep at least 6k heap available for non-Lua use (e.g. network buffers)`
|
||||||
|
|
||||||
|
|
||||||
|
## node.egc.meminfo()
|
||||||
|
|
||||||
|
Returns memory usage information for the Lua runtime.
|
||||||
|
|
||||||
|
####Syntax
|
||||||
|
`total_allocated, estimated_used = node.egc.meminfo()`
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
None.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
- `total_allocated` The total number of bytes allocated by the Lua runtime. This is the number which is relevant when using the `node.egc.ON_MEM_LIMIT` option with positive limit values.
|
||||||
|
- `estimated_used` This value shows the estimated usage of the allocated memory.
|
||||||
|
|
||||||
# node.task module
|
# node.task module
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue