diff options
author | Felix Fietkau <nbd@openwrt.org> | 2009-10-24 22:19:13 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2009-10-24 22:19:13 +0000 |
commit | 8f9821461723848e35487b70711e83bff1eb1dc4 (patch) | |
tree | 054e61c53d6bfe3136a2c031a2cb8080d7100eb4 /package/lua/patches/040-memory-limits.patch | |
parent | eff75d868bc1271e5f34d214012efff7674d1da0 (diff) | |
download | upstream-8f9821461723848e35487b70711e83bff1eb1dc4.tar.gz upstream-8f9821461723848e35487b70711e83bff1eb1dc4.tar.bz2 upstream-8f9821461723848e35487b70711e83bff1eb1dc4.zip |
lua: add reference counting for strings - this will need A LOT of testing, but it should finally fix the excessive memory usage problems triggered by luci
SVN-Revision: 18136
Diffstat (limited to 'package/lua/patches/040-memory-limits.patch')
-rw-r--r-- | package/lua/patches/040-memory-limits.patch | 289 |
1 files changed, 0 insertions, 289 deletions
diff --git a/package/lua/patches/040-memory-limits.patch b/package/lua/patches/040-memory-limits.patch deleted file mode 100644 index bc6526b3f7..0000000000 --- a/package/lua/patches/040-memory-limits.patch +++ /dev/null @@ -1,289 +0,0 @@ ---- a/src/lapi.c -+++ b/src/lapi.c -@@ -716,14 +716,14 @@ - - LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - StkId t; -- TValue key; - lua_lock(L); - api_checknelems(L, 1); - t = index2adr(L, idx); - api_checkvalidindex(L, t); -- setsvalue(L, &key, luaS_new(L, k)); -- luaV_settable(L, t, &key, L->top - 1); -- L->top--; /* pop value */ -+ setsvalue2s(L, L->top, luaS_new(L, k)); -+ api_incr_top(L); -+ luaV_settable(L, t, L->top - 1, L->top - 2); -+ L->top -= 2; /* pop key and value */ - lua_unlock(L); - } - -@@ -971,7 +971,12 @@ - break; - } - case LUA_GCCOLLECT: { -- luaC_fullgc(L); -+ lu_mem old_thres = g->GCthreshold; -+ if(g->GCthreshold != MAX_LUMEM) { -+ g->GCthreshold = MAX_LUMEM; -+ luaC_fullgc(L); -+ g->GCthreshold = old_thres; -+ } - break; - } - case LUA_GCCOUNT: { ---- a/src/ldo.c -+++ b/src/ldo.c -@@ -494,6 +494,7 @@ - struct SParser *p = cast(struct SParser *, ud); - int c = luaZ_lookahead(p->z); - luaC_checkGC(L); -+ lua_gc(L, LUA_GCSTOP, 0); /* stop collector during parsing */ - tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, - &p->buff, p->name); - cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); -@@ -502,6 +503,7 @@ - cl->l.upvals[i] = luaF_newupval(L); - setclvalue(L, L->top, cl); - incr_top(L); -+ lua_gc(L, LUA_GCRESTART, 0); - } - - ---- a/src/lgc.c -+++ b/src/lgc.c -@@ -437,7 +437,10 @@ - /* check size of buffer */ - if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ - size_t newsize = luaZ_sizebuffer(&g->buff) / 2; -- luaZ_resizebuffer(L, &g->buff, newsize); -+ /* make sure newsize is larger then the buffer's in use size. */ -+ newsize = (luaZ_bufflen(&g->buff) > newsize) ? luaZ_bufflen(&g->buff) : newsize; -+ if(newsize < luaZ_sizebuffer(&g->buff)) -+ luaZ_resizebuffer(L, &g->buff, newsize); - } - } - ---- a/src/lstate.c -+++ b/src/lstate.c -@@ -118,7 +118,6 @@ - - lua_State *luaE_newthread (lua_State *L) { - lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); -- luaC_link(L, obj2gco(L1), LUA_TTHREAD); - preinit_state(L1, G(L)); - stack_init(L1, L); /* init stack */ - setobj2n(L, gt(L1), gt(L)); /* share table of globals */ -@@ -126,6 +125,7 @@ - L1->basehookcount = L->basehookcount; - L1->hook = L->hook; - resethookcount(L1); -+ luaC_link(L, obj2gco(L1), LUA_TTHREAD); - lua_assert(iswhite(obj2gco(L1))); - return L1; - } ---- a/src/lstring.c -+++ b/src/lstring.c -@@ -53,6 +53,9 @@ - stringtable *tb; - if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) - luaM_toobig(L); -+ tb = &G(L)->strt; -+ if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) -+ luaS_resize(L, tb->size*2); /* too crowded */ - ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); - ts->tsv.len = l; - ts->tsv.hash = h; -@@ -61,13 +64,10 @@ - ts->tsv.reserved = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ -- tb = &G(L)->strt; - h = lmod(h, tb->size); - ts->tsv.next = tb->hash[h]; /* chain new entry */ - tb->hash[h] = obj2gco(ts); - tb->nuse++; -- if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) -- luaS_resize(L, tb->size*2); /* too crowded */ - return ts; - } - ---- a/src/ltable.c -+++ b/src/ltable.c -@@ -371,7 +371,6 @@ - - Table *luaH_new (lua_State *L, int narray, int nhash) { - Table *t = luaM_new(L, Table); -- luaC_link(L, obj2gco(t), LUA_TTABLE); - t->metatable = NULL; - t->flags = cast_byte(~0); - /* temporary values (kept only if some malloc fails) */ -@@ -381,6 +380,7 @@ - t->node = cast(Node *, dummynode); - setarrayvector(L, t, narray); - setnodevector(L, t, nhash); -+ luaC_link(L, obj2gco(t), LUA_TTABLE); - return t; - } - ---- a/src/lvm.c -+++ b/src/lvm.c -@@ -375,6 +375,7 @@ - if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); - tl += l; - } -+ G(L)->buff.n = tl; - buffer = luaZ_openspace(L, &G(L)->buff, tl); - tl = 0; - for (i=n; i>0; i--) { /* concat all strings */ -@@ -383,6 +384,7 @@ - tl += l; - } - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); -+ luaZ_resetbuffer(&G(L)->buff); - } - total -= n-1; /* got `n' strings to create 1 new */ - last -= n-1; ---- a/src/lua.c -+++ b/src/lua.c -@@ -19,6 +19,94 @@ - #include "llimits.h" - - -+typedef struct { -+ char *name; -+ lua_State *L; -+ size_t memused; -+ size_t peak_memused; -+ size_t gc_memused; -+ size_t max_memused; -+ int collecting; -+} script_info_t; -+ -+ -+static void *script_alloc(void *ud, void *ptr, size_t osize, size_t nsize) -+{ -+ script_info_t *info=(script_info_t *)ud; -+ size_t old_size = info->memused; -+ -+ info->memused -= osize; -+ if (nsize == 0) { -+ free(ptr); -+ return NULL; -+ } -+ info->memused += nsize; -+ if(info->max_memused > 0 && nsize > osize && -+ (info->memused >= info->max_memused || info->memused >= info->gc_memused)) { -+#ifdef LOW_MEM_DEBUG -+ printf("LOW MEM: 1 osize=%zd, nsize=%zd, used=%zu, peak=%zu, need=%zd\n", osize, nsize, -+ info->memused, info->peak_memused, (info->memused - info->max_memused)); -+#endif -+ info->memused = old_size; -+ /* don't allow a recursive garbage collection call. */ -+ if(info->collecting != 0) { -+ return NULL; -+ } -+ info->collecting = 1; -+ /* try to free memory by collecting garbage. */ -+ lua_gc(info->L, LUA_GCCOLLECT, 0); -+ info->collecting = 0; -+#ifdef LOW_MEM_DEBUG -+ printf("LOW MEM: 2 used=%zu, peak=%zu\n", info->memused, info->peak_memused); -+#endif -+ /* check memory usage again. */ -+ old_size = info->memused; -+ info->memused -= osize; -+ info->memused += nsize; -+ if(info->memused >= info->max_memused) { -+ info->memused = old_size; -+#ifdef LOW_MEM_DEBUG -+ printf("OUT OF MEMORY: memused=%zd, osize=%zd, nsize=%zd\n", info->memused, osize, nsize); -+#endif -+ return NULL; -+ } -+ } -+ if(info->memused > info->peak_memused) info->peak_memused = info->memused; -+ return realloc(ptr, nsize); -+} -+ -+static int set_memory_limit(lua_State *L) -+{ -+ int hardlimit = luaL_checknumber(L, 1); -+ int softlimit = luaL_optnumber(L, 2, 0); -+ -+ script_info_t *info; -+ lua_getallocf(L, (void *)(&info)); -+ -+ if( hardlimit >= 0 ) -+ { -+ if( softlimit <= 0 ) -+ softlimit = (int)((float)hardlimit * 0.75); -+ -+ info->max_memused = hardlimit; -+ info->gc_memused = softlimit; -+ } -+ -+ lua_pushnumber(L, hardlimit); -+ lua_pushnumber(L, softlimit); -+ return 2; -+} -+ -+static int get_memory_limit(lua_State *L) -+{ -+ script_info_t *info; -+ lua_getallocf(L, (void *)(&info)); -+ lua_pushnumber(L, info->max_memused); -+ lua_pushnumber(L, info->gc_memused); -+ return 2; -+} -+ -+ - static lua_State *globalL = NULL; - - static const char *progname = LUA_PROGNAME; -@@ -377,11 +465,28 @@ - int main (int argc, char **argv) { - int status; - struct Smain s; -- lua_State *L = lua_open(); /* create state */ -+ script_info_t *info; -+ -+ info = (script_info_t *)calloc(1, sizeof(script_info_t)); -+ info->max_memused = 0; -+ info->collecting = 0; -+ info->name = argv[0]; -+ info->memused = 0; -+ info->peak_memused = 0; -+ -+ lua_State *L = lua_newstate(script_alloc, info); -+ - if (L == NULL) { - l_message(argv[0], "cannot create state: not enough memory"); - return EXIT_FAILURE; - } -+ -+ info->L = L; -+ -+ luaL_openlibs(L); -+ lua_register(L, "set_memory_limit", set_memory_limit); -+ lua_register(L, "get_memory_limit", get_memory_limit); -+ - /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers. - */ - #ifdef LNUM_INT16 -@@ -396,6 +501,14 @@ - status = lua_cpcall(L, &pmain, &s); - report(L, status); - lua_close(L); -+ -+#ifdef LOW_MEM_DEBUG -+ printf("%s: memused=%zd, peak_memused=%zd\n", info->name, -+ info->memused, info->peak_memused); -+#endif -+ -+ free(info); -+ - return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; - } - |