瀏覽代碼

update:优化了辅助内存回收功能,并提供接口
update:内存不足时不再简单的提示,而是把使用情况打印出来

alienwalker 2 年之前
父節點
當前提交
68ee36d669
共有 3 個文件被更改,包括 84 次插入18 次删除
  1. 8 2
      lua/src/lmem.c
  2. 1 0
      luat/include/luat_msgbus.h
  3. 75 16
      luat/modules/luat_lib_rtos.c

+ 8 - 2
lua/src/lmem.c

@@ -98,8 +98,14 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
       luaC_fullgc(L, 1);  /* try to free some memory... */
       newblock = (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
     }
-    if (newblock == NULL)
-      luaD_throw(L, LUA_ERRMEM);
+    if (newblock == NULL) {
+      size_t total = 0;
+      size_t used = 0;
+      size_t max_used = 0;
+      luat_meminfo_luavm(&total, &used, &max_used);
+      luaG_runerror(L, "memory allocation failed total %d, used %d, alloc %d", total, used, nsize);
+      luaD_throw(L, LUA_ERRMEM);  /* rethrow memory error */
+    }
   }
   lua_assert((nsize == 0) == (newblock == NULL));
   g->GCdebt = (g->GCdebt + nsize) - realosize;

+ 1 - 0
luat/include/luat_msgbus.h

@@ -25,6 +25,7 @@ void luat_msgbus_init(void);
 uint32_t luat_msgbus_put(rtos_msg_t* msg, size_t timeout);
 uint32_t luat_msgbus_get(rtos_msg_t* msg, size_t timeout);
 uint32_t luat_msgbus_freesize(void);
+uint8_t luat_msgbus_is_empty(void);
 
 #define luat_msgbug_put2(ABC1,ABC2,ABC3,ABC4,ABC5) {\
     rtos_msg_t _msg = {.handler=ABC1,.ptr=ABC2,.arg1=ABC3,.arg2=ABC4};\

+ 75 - 16
luat/modules/luat_lib_rtos.c

@@ -13,10 +13,16 @@
 
 #define LUAT_LOG_TAG "rtos"
 #include "luat_log.h"
-
+static uint32_t autogc_high_water = 90;
+static uint32_t autogc_mid_water = 80;
 static uint16_t autogc_config = 100; // TODO 通过API可配置
 static uint16_t autogc_counter = 0;
-
+#ifndef LUAT_COMPILER_NOWEAK
+LUAT_WEAK uint8_t luat_msgbus_is_empty(void)
+{
+	return 0;
+}
+#endif
 /*
 接受并处理底层消息队列.
 @api    rtos.receive(timeout)   
@@ -31,22 +37,42 @@ static int l_rtos_receive(lua_State *L) {
     size_t total = 0;
     size_t used = 0;
     size_t max_used = 0;
-    if (autogc_config > 0) {
-        if (autogc_counter >= autogc_config) {
-            autogc_counter = 0;
-            luat_meminfo_luavm(&total, &used, &max_used);
-            if ( (used * 100) >= (total * 90))
-            {
-                //LLOGD("luavm ram too high! used %d, total %d. Trigger Force-GC", used, total);
-                // 需要执行2次, 因为userdata在第二次才会被回收
-                lua_gc(L, LUA_GCCOLLECT, 0);
-                lua_gc(L, LUA_GCCOLLECT, 0);
-            }
+    //系统空闲且设置了自动收集功能
+    if (luat_msgbus_is_empty() && autogc_config)
+    {
+    	//LLOGD("auto collect check %d,%d", luat_msgbus_is_empty(), autogc_config);
+    	luat_meminfo_luavm(&total, &used, &max_used);
+    	//达到强制线就直接收集了
+        if ( (used * 100) >= (total * autogc_high_water))
+        {
+            //LLOGD("luavm ram too high! used %d, total %d. Trigger Force-GC", used, total);
+            // 需要执行2次, 因为userdata在第二次才会被回收
+            lua_gc(L, LUA_GCCOLLECT, 0);
+            lua_gc(L, LUA_GCCOLLECT, 0);
         }
-        else {
-            autogc_counter ++;
+        else
+        {
+
+            if (autogc_counter >= autogc_config) {
+                autogc_counter = 0;
+                if ( (used * 100) >= (total * autogc_mid_water))
+                {
+                    //LLOGD("luavm ram too high! used %d, total %d. Trigger Force-GC", used, total);
+                    // 需要执行2次, 因为userdata在第二次才会被回收
+                    lua_gc(L, LUA_GCCOLLECT, 0);
+                    lua_gc(L, LUA_GCCOLLECT, 0);
+                }
+            }
+            else {
+                autogc_counter ++;
+            }
         }
     }
+    else
+    {
+    	autogc_counter = 0;	//这里也许可以不清零
+    }
+
 
     re = luat_msgbus_get(&msg, luaL_checkinteger(L, 1));
     if (!re) {
@@ -325,6 +351,39 @@ static int l_rtos_nop(lua_State *L) {
     return 0;
 }
 
+/*
+内存自动收集配置,是lua本身收集机制的一种补充,不是必要的,而且只在luavm空闲时触发
+@api    rtos.autoCollectMem(period, warning_level, force_level)
+@int	自动收集的周期,等同于receive调用次数,0~60000。如果是0,则关闭自动收集功能,默认是100
+@int	内存使用警戒水位线,是总luavm内存量的百分比,50~95,内存达到(>=)警戒线时才会开始判断是否要收集。默认是80
+@int	内存使用强制收集水位线,是总luavm内存量的百分比,50~95,内存达到(>=)强制收集线时会强制收集。默认是90,必须比警戒水位线大
+@return nil 无返回值
+@usage
+rtos.autoCollectMem(100, 80, 90)
+*/
+static int l_rtos_auto_colloect_mem(lua_State *L) {
+    uint32_t period = luaL_optinteger(L, 1, 100);
+    uint32_t mid = luaL_optinteger(L, 2, 80);
+    uint32_t high = luaL_optinteger(L, 3, 90);
+    if (period > 60000) {
+    	return 0;
+    }
+    if (mid > 95 || high > 95) {
+    	return 0;
+    }
+    if (mid < 50 || high < 50) {
+    	return 0;
+    }
+    if (mid >= high) {
+    	return 0;
+    }
+    LLOGD("mem collect param %u,%u,%u -> %u,%u,%u", autogc_config, autogc_mid_water, autogc_high_water, period, mid, high);
+    autogc_config = period;
+	autogc_mid_water = mid;
+	autogc_high_water = high;
+    return 0;
+}
+
 // TODO 部分平台不支持LUAT_WEAK
 LUAT_WEAK int luat_poweron_reason(void) {
     return 0;
@@ -357,7 +416,7 @@ static const rotable_Reg_t reg_rtos[] =
     { "firmware",          ROREG_FUNC(l_rtos_firmware)},
     { "setPaths",          ROREG_FUNC(l_rtos_set_paths)},
     { "nop",               ROREG_FUNC(l_rtos_nop)},
-
+	{ "autoCollectMem",          ROREG_FUNC(l_rtos_auto_colloect_mem)},
     { "INF_TIMEOUT",       ROREG_INT(-1)},
 
     { "MSG_TIMER",         ROREG_INT(MSG_TIMER)},