From 5d26fb3f18487805b61ec65538241e32bf870950 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Tue, 18 Jun 2019 14:09:36 +0800 Subject: [PATCH] remove ssm and add string id --- 3rd/lua/lapi.c | 17 +- 3rd/lua/lauxlib.c | 2 +- 3rd/lua/lfunc.c | 11 +- 3rd/lua/lgc.c | 60 +- 3rd/lua/lgc.h | 7 +- 3rd/lua/lobject.h | 5 +- 3rd/lua/lstate.c | 7 +- 3rd/lua/lstate.h | 6 +- 3rd/lua/lstring.c | 1042 ++++------------------------------- 3rd/lua/lstring.h | 36 +- 3rd/lua/lua.c | 6 +- 3rd/lua/lua.h | 2 + 3rd/lua/luac.c | 3 - Makefile | 1 - lualib-src/lua-sharetable.c | 12 +- lualib-src/lua-ssm.c | 78 --- service/bootstrap.lua | 2 - service/garbagecollect.lua | 26 - skynet-src/luashrtbl.h | 29 - skynet-src/skynet_main.c | 3 - 20 files changed, 183 insertions(+), 1172 deletions(-) delete mode 100644 lualib-src/lua-ssm.c delete mode 100644 service/garbagecollect.lua delete mode 100644 skynet-src/luashrtbl.h diff --git a/3rd/lua/lapi.c b/3rd/lua/lapi.c index c319f612..a4282db6 100644 --- a/3rd/lua/lapi.c +++ b/3rd/lua/lapi.c @@ -1050,10 +1050,19 @@ LUA_API void lua_sharestring (lua_State *L, int index) { luaG_runerror(L, "need a string to share"); TString *ts = (TString *)(str - sizeof(UTString)); - if(ts->tt == LUA_TLNGSTR) - makeshared(ts); - else - luaS_fix(G(L), ts); + luaS_share(ts); +} + +LUA_API void lua_clonetable(lua_State *L, const void * tp) { + Table *t = cast(Table *, tp); + + if (!isshared(t)) + luaG_runerror(L, "Not a shared table"); + + lua_lock(L); + sethvalue(L, L->top, t); + api_incr_top(L); + lua_unlock(L); } LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { diff --git a/3rd/lua/lauxlib.c b/3rd/lua/lauxlib.c index 58c6d996..6b2f98f2 100644 --- a/3rd/lua/lauxlib.c +++ b/3rd/lua/lauxlib.c @@ -1103,7 +1103,7 @@ save(const char *key, const void * proto) { } else { lua_pop(L,2); } - + SPIN_UNLOCK(&CC) return result; } diff --git a/3rd/lua/lfunc.c b/3rd/lua/lfunc.c index 2cc9a6ce..260f64e9 100644 --- a/3rd/lua/lfunc.c +++ b/3rd/lua/lfunc.c @@ -19,6 +19,7 @@ #include "lmem.h" #include "lobject.h" #include "lstate.h" +#include "lstring.h" @@ -148,22 +149,20 @@ const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { return NULL; /* not found */ } -#define MAKESHARED(x) if ((x) && (x)->tt == LUA_TLNGSTR) makeshared(x) - void luaF_shareproto (Proto *f) { int i; if (f == NULL) return; makeshared(f); - MAKESHARED(f->source); + luaS_share(f->source); for (i = 0; i < f->sizek; i++) { if (ttnov(&f->k[i]) == LUA_TSTRING) - MAKESHARED(tsvalue(&f->k[i])); + luaS_share(tsvalue(&f->k[i])); } for (i = 0; i < f->sizeupvalues; i++) - MAKESHARED(f->upvalues[i].name); + luaS_share(f->upvalues[i].name); for (i = 0; i < f->sizelocvars; i++) - MAKESHARED(f->locvars[i].varname); + luaS_share(f->locvars[i].varname); for (i = 0; i < f->sizep; i++) luaF_shareproto(f->p[i]); } diff --git a/3rd/lua/lgc.c b/3rd/lua/lgc.c index 757dbd53..08395dec 100644 --- a/3rd/lua/lgc.c +++ b/3rd/lua/lgc.c @@ -193,12 +193,7 @@ void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { void luaC_fix (lua_State *L, GCObject *o) { global_State *g = G(L); - if (o->tt == LUA_TSHRSTR) { - luaS_fix(g, gco2ts(o)); - return; - } - if (g->allgc != o) - return; /* if object is not 1st in 'allgc' list, it is in global short string table */ + lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ white2gray(o); /* they will be gray forever */ g->allgc = o->next; /* remove object from 'allgc' list */ o->next = g->fixedgc; /* link it to 'fixedgc' list */ @@ -239,22 +234,22 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { */ static void reallymarkobject (global_State *g, GCObject *o) { reentry: + if (isshared(o)) + return; + white2gray(o); switch (o->tt) { case LUA_TSHRSTR: { - luaS_mark(g, gco2ts(o)); + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); break; } case LUA_TLNGSTR: { - if (!isshared(o)) { - white2gray(o); - gray2black(o); - g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); - } + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); break; } case LUA_TUSERDATA: { TValue uvalue; - white2gray(o); markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ gray2black(o); g->GCmemtrav += sizeudata(gco2u(o)); @@ -266,34 +261,23 @@ static void reallymarkobject (global_State *g, GCObject *o) { break; } case LUA_TLCL: { - if (!isshared(o)) { - white2gray(o); - linkgclist(gco2lcl(o), g->gray); - } + linkgclist(gco2lcl(o), g->gray); break; } case LUA_TCCL: { - white2gray(o); linkgclist(gco2ccl(o), g->gray); break; } case LUA_TTABLE: { - if (!isshared(o)) { - white2gray(o); - linkgclist(gco2t(o), g->gray); - } + linkgclist(gco2t(o), g->gray); break; } case LUA_TTHREAD: { - white2gray(o); linkgclist(gco2th(o), g->gray); break; } case LUA_TPROTO: { - if (!isshared(o)) { - white2gray(o); - linkgclist(gco2p(o), g->gray); - } + linkgclist(gco2p(o), g->gray); break; } default: lua_assert(0); break; @@ -724,6 +708,10 @@ static void freeobj (lua_State *L, GCObject *o) { case LUA_TTABLE: luaH_free(L, gco2t(o)); break; case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; + case LUA_TSHRSTR: + luaS_remove(L, gco2ts(o)); /* remove it from hash table */ + luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); + break; case LUA_TLNGSTR: { luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); break; @@ -789,6 +777,19 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) { ** ======================================================= */ +/* +** If possible, shrink string table +*/ +static void checkSizes (lua_State *L, global_State *g) { + if (g->gckind != KGC_EMERGENCY) { + l_mem olddebt = g->GCdebt; + if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ + luaS_resize(L, g->strt.size / 2); /* shrink it a little */ + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ + } +} + + static GCObject *udata2finalize (global_State *g) { GCObject *o = g->tobefnz; /* get first element */ lua_assert(tofinalize(o)); @@ -979,6 +980,7 @@ void luaC_freeallobjects (lua_State *L) { sweepwholelist(L, &g->finobj); sweepwholelist(L, &g->allgc); sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ + lua_assert(g->strt.nuse == 0); } @@ -1024,7 +1026,6 @@ static l_mem atomic (lua_State *L) { clearvalues(g, g->allweak, origall); luaS_clearcache(g); g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ - luaS_collect(g, 0); /* send short strings set to gc thread */ work += g->GCmemtrav; /* complete counting */ return work; /* estimate of memory marked by 'atomic' */ } @@ -1050,7 +1051,7 @@ static lu_mem singlestep (lua_State *L) { global_State *g = G(L); switch (g->gcstate) { case GCSpause: { - g->GCmemtrav = 0; + g->GCmemtrav = g->strt.size * sizeof(GCObject*); restartcollection(g); g->gcstate = GCSpropagate; return g->GCmemtrav; @@ -1082,6 +1083,7 @@ static lu_mem singlestep (lua_State *L) { } case GCSswpend: { /* finish sweeps */ makewhite(g, g->mainthread); /* sweep main thread */ + checkSizes(L, g); g->gcstate = GCScallfin; return 0; } diff --git a/3rd/lua/lgc.h b/3rd/lua/lgc.h index 6977ff22..55467ef3 100644 --- a/3rd/lua/lgc.h +++ b/3rd/lua/lgc.h @@ -85,7 +85,6 @@ #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) -/* short string is always white */ #define iswhite(x) testbits((x)->marked, WHITEBITS) #define isblack(x) testbit((x)->marked, BLACKBIT) #define isgray(x) /* neither white nor black */ \ @@ -120,15 +119,15 @@ #define luaC_barrier(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v)) && !isshared(gcvalue(v))) ? \ luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) #define luaC_barrierback(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v)) && !isshared(gcvalue(v))) ? \ luaC_barrierback_(L,p) : cast_void(0)) #define luaC_objbarrier(L,p,o) ( \ - (isblack(p) && iswhite(o)) ? \ + (isblack(p) && iswhite(o) && !isshared(o)) ? \ luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) #define luaC_upvalbarrier(L,uv) ( \ diff --git a/3rd/lua/lobject.h b/3rd/lua/lobject.h index 71f55b26..948e9704 100644 --- a/3rd/lua/lobject.h +++ b/3rd/lua/lobject.h @@ -189,7 +189,7 @@ typedef struct lua_TValue { #define checkliveness(L,obj) \ lua_longassert(!iscollectable(obj) || \ - (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))) + (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)) || isshared(gcvalue(obj))))) /* Macros to set values */ @@ -305,9 +305,10 @@ typedef struct TString { lu_byte extra; /* reserved words for short strings; "has hash" for longs */ lu_byte shrlen; /* length for short strings */ unsigned int hash; + size_t id; /* id for short strings */ union { size_t lnglen; /* length for long strings */ - size_t ref; /* reference count for short strings */ + struct TString *hnext; /* linked list for hash table */ } u; } TString; diff --git a/3rd/lua/lstate.c b/3rd/lua/lstate.c index d0cd5e75..4e3029b3 100644 --- a/3rd/lua/lstate.c +++ b/3rd/lua/lstate.c @@ -224,7 +224,7 @@ static void close_state (lua_State *L) { luaC_freeallobjects(L); /* collect all objects */ if (g->version) /* closing a fully built state? */ luai_userstateclose(L); - luaS_collect(g, 1); /* clear short strings */ + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); freestack(L); lua_assert(gettotalbytes(g) == sizeof(LG)); (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ @@ -289,6 +289,8 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->mainthread = L; g->gcrunning = 0; /* no GC while building state */ g->GCestimate = 0; + g->strt.size = g->strt.nuse = 0; + g->strt.hash = NULL; setnilvalue(&g->l_registry); g->panic = NULL; g->version = NULL; @@ -304,9 +306,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->gcfinnum = 0; g->gcpause = LUAI_GCPAUSE; g->gcstepmul = LUAI_GCMUL; - g->strsave = NULL; - g->strmark = NULL; - g->strfix = NULL; for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { /* memory allocation error: free partial state */ diff --git a/3rd/lua/lstate.h b/3rd/lua/lstate.h index 5ccf7bac..3f029fe3 100644 --- a/3rd/lua/lstate.h +++ b/3rd/lua/lstate.h @@ -130,8 +130,6 @@ typedef struct CallInfo { #define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) #define getoah(st) ((st) & CIST_OAH) -/* SSM (short string map) See lstring.c */ -struct ssm_ref; /* ** 'global state', shared by all threads of this state @@ -143,6 +141,7 @@ typedef struct global_State { l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ lu_mem GCmemtrav; /* memory traversed by the GC */ lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ + stringtable strt; /* hash table for strings */ TValue l_registry; lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ @@ -169,9 +168,6 @@ typedef struct global_State { TString *tmname[TM_N]; /* array with tag-method names */ struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ - struct ssm_ref *strsave; - struct ssm_ref *strmark; - struct ssm_ref *strfix; } global_State; diff --git a/3rd/lua/lstring.c b/3rd/lua/lstring.c index 4bec4a7c..a9ff3e15 100644 --- a/3rd/lua/lstring.c +++ b/3rd/lua/lstring.c @@ -9,8 +9,10 @@ #include "lprefix.h" + #include #include + #include "lua.h" #include "ldebug.h" @@ -19,10 +21,10 @@ #include "lobject.h" #include "lstate.h" #include "lstring.h" +#include "atomic.h" static unsigned int STRSEED; - -#define STRFIXSIZE 64 +static size_t STRID = 0; #define MEMERRMSG "not enough memory" @@ -47,6 +49,24 @@ int luaS_eqlngstr (TString *a, TString *b) { (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ } +int luaS_eqshrstr (TString *a, TString *b) { + lu_byte len = a->shrlen; + lua_assert(b->tt == LUA_TSHRSTR); + int r = len == b->shrlen && (memcmp(getstr(a), getstr(b), len) == 0); + if (r) { + if (a->id < b->id) { + a->id = b->id; + } else { + b->id = a->id; + } + } + return r; +} + +void luaS_share (TString *ts) { + makeshared(ts); + ts->id = ATOM_INC(&STRID); +} unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { unsigned int h = seed ^ cast(unsigned int, l); @@ -67,6 +87,37 @@ unsigned int luaS_hashlongstr (TString *ts) { } +/* +** resizes the string table +*/ +void luaS_resize (lua_State *L, int newsize) { + int i; + stringtable *tb = &G(L)->strt; + if (newsize > tb->size) { /* grow table if needed */ + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); + for (i = tb->size; i < newsize; i++) + tb->hash[i] = NULL; + } + for (i = 0; i < tb->size; i++) { /* rehash */ + TString *p = tb->hash[i]; + tb->hash[i] = NULL; + while (p) { /* for each node in the list */ + TString *hnext = p->u.hnext; /* save next */ + unsigned int h = lmod(p->hash, newsize); /* new position */ + p->u.hnext = tb->hash[h]; /* chain it */ + tb->hash[h] = p; + p = hnext; + } + } + if (newsize < tb->size) { /* shrink table if needed */ + /* vanishing slice should be empty */ + lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); + } + tb->size = newsize; +} + + /* ** Clear API string cache. (Entries cannot be empty, so fill them with ** a non-collectable string.) @@ -75,11 +126,20 @@ void luaS_clearcache (global_State *g) { int i, j; for (i = 0; i < STRCACHE_N; i++) for (j = 0; j < STRCACHE_M; j++) { + if (iswhite(g->strcache[i][j])) /* will entry be collected? */ g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ } } -static struct ssm_ref * newref(int size); +static unsigned int make_str_seed(lua_State *L) { + size_t buff[4]; + unsigned int h = time(NULL); + buff[0] = cast(size_t, h); + buff[1] = cast(size_t, &STRSEED); + buff[2] = cast(size_t, &make_str_seed); + buff[3] = cast(size_t, L); + return luaS_hash((const char*)buff, sizeof(buff), h); +} /* ** Initialize the string table and the string cache @@ -87,8 +147,10 @@ static struct ssm_ref * newref(int size); void luaS_init (lua_State *L) { global_State *g = G(L); int i, j; - g->strsave = newref(MINSTRTABSIZE); - g->strmark = newref(MINSTRTABSIZE); + if (STRSEED == 0) { + STRSEED = make_str_seed(L); + } + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ /* pre-create memory-error message */ g->memerrmsg = luaS_newliteral(L, MEMERRMSG); luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ @@ -111,17 +173,60 @@ static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { ts = gco2ts(o); ts->hash = h; ts->extra = 0; + ts->id = 0; getstr(ts)[l] = '\0'; /* ending 0 */ return ts; } + TString *luaS_createlngstrobj (lua_State *L, size_t l) { TString *ts = createstrobj(L, l, LUA_TLNGSTR, STRSEED); ts->u.lnglen = l; return ts; } -static TString *internshrstr (lua_State *L, const char *str, size_t l); + +void luaS_remove (lua_State *L, TString *ts) { + stringtable *tb = &G(L)->strt; + TString **p = &tb->hash[lmod(ts->hash, tb->size)]; + while (*p != ts) /* find previous element */ + p = &(*p)->u.hnext; + *p = (*p)->u.hnext; /* remove element from its list */ + tb->nuse--; +} + + +/* +** checks whether short string exists and reuses it or creates a new one +*/ +static TString *internshrstr (lua_State *L, const char *str, size_t l) { + TString *ts; + global_State *g = G(L); + unsigned int h = luaS_hash(str, l, STRSEED); + TString **list = &g->strt.hash[lmod(h, g->strt.size)]; + lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ + for (ts = *list; ts != NULL; ts = ts->u.hnext) { + if (l == ts->shrlen && + (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { + /* found! */ + if (isdead(g, ts)) /* dead (but not collected yet)? */ + changewhite(ts); /* resurrect it */ + return ts; + } + } + if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { + luaS_resize(L, g->strt.size * 2); + list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ + } + ts = createstrobj(L, l, LUA_TSHRSTR, h); + memcpy(getstr(ts), str, l * sizeof(char)); + ts->shrlen = cast_byte(l); + ts->u.hnext = *list; + *list = ts; + g->strt.nuse++; + return ts; +} + /* ** new string (with explicit length) @@ -176,928 +281,3 @@ Udata *luaS_newudata (lua_State *L, size_t s) { return u; } -/* - * global shared table - */ - -#include "rwlock.h" -#include "spinlock.h" -#include "atomic.h" -#include -#include - -#define SHRSTR_INITSIZE 0x10000 - -/* prime is better for hash */ -#define VMHASHSLOTS 4093 - -struct shrmap_slot { - struct rwlock lock; - TString *str; -}; - -struct ssm_ref { - TString **hash; - TString **array; - int nuse; /* number of elements */ - int hsize; - int asize; - int acap; -}; - -struct collect_queue { - struct collect_queue *next; - void * key; - struct ssm_ref *strsave; - struct ssm_ref *strmark; - struct ssm_ref *strfix; -}; - -struct shrmap { - struct rwlock lock; - int rwslots; - int total; - int garbage; - int roslots; - struct shrmap_slot * readwrite; - struct shrmap_slot * readonly; - struct spinlock qlock; - struct collect_queue * head; - struct collect_queue * tail; - struct collect_queue * vm[VMHASHSLOTS]; -}; - -static struct shrmap SSM; - -#define ADD_SREF(ts) do {if(ATOM_INC(&((ts)->u.ref))==1) ATOM_DEC(&SSM.garbage);}while(0) -#define DEC_SREF(ts) do {if(ATOM_DEC(&((ts)->u.ref))==0) ATOM_INC(&SSM.garbage);}while(0) -#define ZERO_SREF(ts) ((ts)->u.ref == 0) -#define FREE_SREF(ts) do {free(ts);ATOM_DEC(&SSM.total);ATOM_DEC(&SSM.garbage);}while(0) - -static struct ssm_ref * -newref(int size) { - /* size must be must be power of 2 */ - lua_assert( (size&(size-1))==0 ); - struct ssm_ref *r = (struct ssm_ref *)malloc(sizeof(*r)); - if (r == NULL) - return NULL; - TString **hash = (TString **)malloc(sizeof(TString *) * size); - if (hash == NULL) { - free(r); - return NULL; - } - memset(r, 0, sizeof(*r)); - memset(hash, 0, sizeof(TString *) * size); - r->hsize = size; - r->hash = hash; - return r; -} - -static void -expand_ref(struct ssm_ref *r, int changeref) { - int hsize = r->hsize * 2; - TString ** hash = (TString **)malloc(sizeof(TString *) * hsize); - if (hash == NULL) - return; - memset(hash, 0, sizeof(TString *) * hsize); - int i; - for (i=0;ihsize;i++) { - TString *s = r->hash[i]; - if (s) { - hash[lmod(s->hash, hsize)] = s; - } - } - free(r->hash); - r->hash = hash; - r->hsize = hsize; - - for (i=0;iasize;) { - TString *s = r->array[i]; - int slot = lmod(s->hash, hsize); - TString *hs = hash[slot]; - if (hs == s || hs == NULL) { - if (hs == NULL) - hash[slot] = s; - else { - --r->nuse; - if (changeref) - DEC_SREF(s); - } - --r->asize; - r->array[i] = r->array[r->asize]; - } else { - ++i; - } - } -} - -static void -insert_ref(struct ssm_ref *r, TString *s) { - if (r->asize >= r->acap) { - r->acap = r->asize * 2; - if (r->acap == 0) { - r->acap = r->hsize / 2; - } - TString ** array = (TString **)realloc(r->array, r->acap * sizeof(TString *)); - lua_assert(array != NULL); - r->array = array; - } - r->array[r->asize++] = s; -} - -static void -shrink_ref(struct ssm_ref *r) { - int hsize = r->hsize / 2; - if (hsize < MINSTRTABSIZE) - return; - TString ** hash = (TString **)malloc(sizeof(TString *) * hsize); - if (hash == NULL) - return; - memset(hash, 0, sizeof(TString *) * hsize); - int i; - for (i=0;ihsize;i++) { - TString *s = r->hash[i]; - if (s) { - int h = lmod(s->hash, hsize); - if (hash[h] == NULL) - hash[h] = s; - else - insert_ref(r, s); - } - } - free(r->hash); - r->hash = hash; - r->hsize = hsize; -} - -static void -markref(struct ssm_ref *r, TString *s, int changeref) { - unsigned int h = s->hash; - int slot = lmod(h, r->hsize); - TString * hs = r->hash[slot]; - if (hs == s){ - if (changeref) - DEC_SREF(s); - return; - } - ++r->nuse; - if (r->nuse >= r->hsize && r->hsize <= MAX_INT/2) { - expand_ref(r, changeref); - slot = lmod(h, r->hsize); - hs = r->hash[slot]; - } - if (hs != NULL) { - if (hs == s) { - --r->nuse; - if (changeref) - DEC_SREF(s); - return; - } - insert_ref(r, hs); - } - r->hash[slot] = s; -} - -void -luaS_mark(global_State *g, TString *s) { - markref(g->strmark, s, 0); -} - -void -luaS_fix(global_State *g, TString *s) { - if (g->strfix == NULL) - g->strfix = newref(STRFIXSIZE); - markref(g->strfix, s, 0); -} - -static void -delete_ref(struct ssm_ref *r) { - if (r == NULL) - return; - free(r->hash); - free(r->array); - free(r); -} - -static void -delete_cqueue(struct collect_queue *cqueue) { - delete_ref(cqueue->strsave); - delete_ref(cqueue->strmark); - delete_ref(cqueue->strfix); - free(cqueue); -} - -static void -free_cqueue(struct collect_queue *cqueue) { - while (cqueue) { - struct collect_queue * next = cqueue->next; - delete_cqueue(cqueue); - cqueue = next; - } -} - -static void -remove_duplicate(struct ssm_ref *r, int decref) { - int i = 0; - while (i < r->asize) { - TString *s = r->array[i]; - if (r->hash[lmod(s->hash, r->hsize)] == s) { - --r->nuse; - --r->asize; - r->array[i] = r->array[r->asize]; - if (decref) { - DEC_SREF(s); - } - } else { - ++i; - } - } -} - -static struct ssm_ref * -mergeset(struct ssm_ref *set, struct ssm_ref * rset, int changeref) { - if (set == NULL) - return rset; - else if (rset == NULL) - return set; - int total = set->nuse + rset->nuse; - if (total * 2 <= set->hsize) { - shrink_ref(set); - } else if (total > set->hsize) { - expand_ref(set, changeref); - } - int i; - for (i=0;ihsize;i++) { - TString * s = rset->hash[i]; - if (s) { - markref(set, s, changeref); - } - } - for (i=0;iasize;i++) { - TString * s = rset->array[i]; - markref(set, s, changeref); - } - delete_ref(rset); - remove_duplicate(set, changeref); - return set; -} - -static void -merge_last(struct collect_queue * c) { - void *key = c->key; - int hash = (int)((size_t)key % VMHASHSLOTS); - struct shrmap * s = &SSM; - struct collect_queue * slot = s->vm[hash]; - if (slot == NULL) { - s->vm[hash] = c; - c->next = NULL; - return; - } - - if (slot->key == key) { - // remove head - s->vm[hash] = slot->next; - } else { - for (;;) { - struct collect_queue * next = slot->next; - if (next == NULL) { - // not found, insert head - c->next = s->vm[hash]; - s->vm[hash] = c; - return; - } else if (next->key == key) { - // remove next - slot->next = next->next; - slot = next; - break; - } - slot = next; - } - } - // merge slot (last) into c - c->strsave = mergeset(slot->strsave, c->strsave, 1); - c->strfix = mergeset(slot->strfix, c->strfix, 0); - c->next = s->vm[hash]; - s->vm[hash] = c; - free(slot); -} - -static void -clear_vm(struct collect_queue * c) { - void *key = c->key; - int hash = (int)((size_t)key % VMHASHSLOTS); - struct shrmap * s = &SSM; - struct collect_queue * slot = s->vm[hash]; - lua_assert(slot == c); - s->vm[hash] = slot->next; - delete_cqueue(slot); -} - -static int -compar_tstring(const void *a, const void *b) { - return memcmp(a,b, sizeof(TString *)); -} - -static void -sortset(struct ssm_ref *set) { - qsort(set->array, set->asize,sizeof(TString *),compar_tstring); -} - -static int -exist(struct ssm_ref *r, TString *s) { - int slot = lmod(s->hash, r->hsize); - TString *hs = r->hash[slot]; - if (hs == s) - return 1; - int begin = 0, end = r->asize-1; - while (begin <= end) { - int mid = (begin + end) / 2; - TString *t = r->array[mid]; - if (t == s) - return 1; - if (memcmp(&s,&t,sizeof(TString *)) > 0) - begin = mid + 1; - else - end = mid - 1; - } - return 0; -} - -static int -collectref(struct collect_queue * c) { - int i; - int total = 0; - merge_last(c); - struct ssm_ref *mark = c->strmark; - struct ssm_ref * save = c->strsave; - c->strmark = NULL; - if (mark) { - struct ssm_ref * fix = c->strfix; - sortset(mark); - sortset(fix); - - for (i=0;ihsize;i++) { - TString * s = save->hash[i]; - if (s) { - if (!exist(mark, s) && !exist(fix, s)) { - save->hash[i] = NULL; - --save->nuse; - DEC_SREF(s); - ++total; - } - } - } - - for (i=0;iasize;) { - TString * s = save->array[i]; - if (!exist(mark, s) && !exist(fix, s)) { - --save->asize; - --save->nuse; - save->array[i] = save->array[save->asize]; - DEC_SREF(s); - ++total; - } else { - ++i; - } - } - delete_ref(mark); - } else { - for (i=0;ihsize;i++) { - TString * s = save->hash[i]; - if (s) { - DEC_SREF(s); - ++total; - } - } - for (i=0;iasize;i++) { - TString * s = save->array[i]; - DEC_SREF(s); - ++total; - } - clear_vm(c); - } - return total; -} - -static int -pow2size(struct ssm_ref *r) { - if (r->nuse <= MINSTRTABSIZE) - return MINSTRTABSIZE; - int hsize = r->hsize; - while (hsize / 2 > r->nuse) { - hsize /= 2; - } - return hsize; -} - -void -luaS_collect(global_State *g, int closed) { - if (closed) { - delete_ref(g->strmark); - g->strmark = NULL; - } - struct shrmap * s = &SSM; - struct collect_queue *cqueue = (struct collect_queue *)malloc(sizeof(*cqueue)); - if (cqueue == NULL) { - /* OOM, give up */ - return; - } - cqueue->key = g; - cqueue->strsave = g->strsave; - cqueue->strmark = g->strmark; - cqueue->strfix = g->strfix; - cqueue->next = NULL; - - g->strfix = NULL; - if (closed) { - g->strsave = NULL; - g->strmark = NULL; - } else { - g->strsave = newref(pow2size(g->strsave)); - g->strmark = newref(pow2size(g->strmark)); - } - - spinlock_lock(&s->qlock); - if (s->head) { - s->tail->next = cqueue; - s->tail = cqueue; - } else { - s->head = s->tail = cqueue; - } - spinlock_unlock(&s->qlock); -} - -static unsigned int make_str_seed() { - size_t buff[4]; - unsigned int h = time(NULL); - buff[0] = cast(size_t, h); - buff[1] = cast(size_t, &STRSEED); - buff[2] = cast(size_t, &make_str_seed); - buff[3] = cast(size_t, SHRSTR_INITSIZE); - return luaS_hash((const char*)buff, sizeof(buff), h); -} - -static struct shrmap_slot * -shrstr_newpage(int sz) { - int i; - struct shrmap_slot * s = (struct shrmap_slot *)malloc(sz * sizeof(*s)); - if (s == NULL) - return NULL; - for (i=0;inext; - FREE_SREF(str); - str = next; - } - } - free(s); - } -} - -static int -shrstr_allocpage(struct shrmap * s, int osz, int sz, struct shrmap_slot * newpage) { - if (s->readonly != NULL) - return 0; - if (s->rwslots != osz) - return 0; - s->readonly = s->readwrite; - s->readwrite = newpage; - s->roslots = s->rwslots; - s->rwslots = sz; - - return 1; -} - -static void -shrstr_rehash(struct shrmap *s, int slotid) { - struct shrmap_slot *slot = &s->readonly[slotid]; - rwlock_wlock(&slot->lock); - TString *str = slot->str; - while (str) { - TString * next = (TString *)str->next; - if (ZERO_SREF(str)) { - FREE_SREF(str); - } else { - int newslotid = lmod(str->hash, s->rwslots); - struct shrmap_slot *newslot = &s->readwrite[newslotid]; - rwlock_wlock(&newslot->lock); - str->next = (GCObject *)newslot->str; - newslot->str = str; - rwlock_wunlock(&newslot->lock); - } - str = next; - } - - slot->str = NULL; - rwlock_wunlock(&slot->lock); -} - -/* - 1. writelock SSM if readonly == NULL, (Only one thread can expand) - 2. move old page (readwrite) to readonly - 3. new (empty) page with double size to readwrite - 4. unlock SSM - 5. rehash every slots - 6. remove temporary readonly (writelock SSM) - */ -static void -expandssm() { - struct shrmap * s = &SSM; - if (s->readonly) - return; - int osz = s->rwslots; - int sz = osz * 2; - if (sz < osz) { - // overflow check - return; - } - struct shrmap_slot * newpage = shrstr_newpage(sz); - if (newpage == NULL) - return; - rwlock_wlock(&s->lock); - int succ = shrstr_allocpage(s, osz, sz, newpage); - rwlock_wunlock(&s->lock); - if (!succ) { - shrstr_deletepage(newpage, sz); - return; - } - int i; - for (i=0;ilock); - struct shrmap_slot * oldpage = s->readonly; - s->readonly = NULL; - rwlock_wunlock(&s->lock); - shrstr_deletepage(oldpage, osz); -} - -static int -sweep_slot(struct shrmap *s, int i) { - struct shrmap_slot *slot = &s->readwrite[i]; - int n = 0; - TString *ts; - rwlock_rlock(&slot->lock); - ts = slot->str; - while (ts) { - if (ZERO_SREF(ts)) { - n = 1; - break; - } - ts = (TString *)ts->next; - } - rwlock_runlock(&slot->lock); - if (n == 0) - return 0; - - n = 0; - rwlock_wlock(&slot->lock); - TString **ref = &slot->str; - ts = *ref; - while (ts) { - if (ZERO_SREF(ts)) { - *ref = (TString *)ts->next; - FREE_SREF(ts); - ts = *ref; - ++n; - } else { - ref = (TString **)&(ts->next); - ts = *ref; - } - } - rwlock_wunlock(&slot->lock); - return n; -} - -static int -sweepssm() { - struct shrmap * s = &SSM; - rwlock_rlock(&s->lock); - if (s->readonly) { - rwlock_runlock(&s->lock); - return 0; - } - int sz = s->rwslots; - int i; - int n = 0; - for (i=0;ilock); - return n; -} - -/* call it in a separate thread */ -LUA_API int -luaS_collectssm(struct ssm_collect *info) { - struct shrmap * s = &SSM; - if (s->total * 5 / 4 > s->rwslots) { - expandssm(); - } - if (s->garbage > s->total / 8) { - info->sweep = sweepssm(); - } else { - info->sweep = 0; - } - if (s->head) { - struct collect_queue * cqueue; - spinlock_lock(&s->qlock); - cqueue = s->head; - s->head = cqueue->next; - spinlock_unlock(&s->qlock); - if (cqueue) { - if (info) { - info->key = cqueue->key; - } - int n = collectref(cqueue); - if (info) { - info->n = n; - } - } - return 1; - } - return 0; -} - -LUA_API void -luaS_initssm() { - struct shrmap * s = &SSM; - rwlock_init(&s->lock); - s->rwslots = SHRSTR_INITSIZE; - s->readwrite = shrstr_newpage(SHRSTR_INITSIZE); - s->readonly = NULL; - s->head = NULL; - s->tail = NULL; - spinlock_init(&s->qlock); - STRSEED = make_str_seed(); -} - -LUA_API void -luaS_exitssm() { - struct shrmap * s = &SSM; - rwlock_wlock(&s->lock); - int sz = s->rwslots; - shrstr_deletepage(s->readwrite, sz); - shrstr_deletepage(s->readonly, s->roslots); - s->readwrite = NULL; - s->readonly = NULL; - free_cqueue(s->head); - s->head = NULL; - s->tail = NULL; - int i; - for (i=0;ivm[i]); - s->vm[i] = NULL; - } -} - -static TString * -find_string(struct shrmap_slot * slot, unsigned int h, const char *str, lu_byte l) { - TString *ts = slot->str; - while (ts) { - if (ts->hash == h && - ts->shrlen == l && - memcmp(str, ts+1, l) == 0) { - ADD_SREF(ts); - break; - } - ts = (TString *)ts->next; - } - return ts; -} - -static TString * -find_and_collect(struct shrmap_slot * slot, unsigned int h, const char *str, lu_byte l) { - TString **ref = &slot->str; - TString *ts = *ref; - while (ts) { - if (ts->hash == h && - ts->shrlen == l && - memcmp(str, ts+1, l) == 0) { - ADD_SREF(ts); - break; - } - if (ZERO_SREF(ts)) { - *ref = (TString *)ts->next; - FREE_SREF(ts); - ts = *ref; - } else { - ref = (TString **)&(ts->next); - ts = *ref; - } - } - return ts; -} - - -/* - 1. readlock SSM - 2. find string in readwrite page - 3. find string in readonly (if exist, during exapnding) - 4. unlock SSM - */ -static TString * -query_string(unsigned int h, const char *str, lu_byte l) { - struct shrmap * s = &SSM; - TString *ts = NULL; - rwlock_rlock(&s->lock); - struct shrmap_slot *slot = &s->readwrite[lmod(h, s->rwslots)]; - rwlock_rlock(&slot->lock); - ts = find_string(slot, h, str, l); - rwlock_runlock(&slot->lock); - if (ts == NULL && s->readonly != NULL) { - int mask = s->roslots - 1; - slot = &s->readonly[h & mask]; - rwlock_rlock(&slot->lock); - ts = find_string(slot, h, str, l); - rwlock_runlock(&slot->lock); - } - rwlock_runlock(&s->lock); - return ts; -} - -static TString * -new_string(unsigned int h, const char *str, lu_byte l) { - size_t sz = sizelstring(l); - TString *ts = malloc(sz); - memset(ts, 0, sz); - setbits(ts->marked, WHITEBITS); - gray2black(ts); - makeshared(ts); - ts->tt = LUA_TSHRSTR; - ts->hash = h; - ts->shrlen = l; - ts->u.ref = 1; - memcpy(ts+1, str, l); - return ts; -} - -static TString * -shrstr_exist(struct shrmap * s, unsigned int h, const char *str, lu_byte l) { - TString *found; - if (s->readonly) { - unsigned int mask = s->roslots - 1; - struct shrmap_slot *slot = &s->readonly[h & mask]; - rwlock_rlock(&slot->lock); - found = find_string(slot, h, str, l); - rwlock_runlock(&slot->lock); - if (found) - return found; - } - struct shrmap_slot *slot = &s->readwrite[lmod(h, s->rwslots)]; - rwlock_wlock(&slot->lock); - if (s->readonly) { - // Don't collect during expanding - found = find_string(slot, h, str, l); - } else { - found = find_and_collect(slot, h, str, l); - } - if (found) { - rwlock_wunlock(&slot->lock); - return found; - } - // not found, lock slot and return. - return NULL; -} - -static TString * -add_string(unsigned int h, const char *str, lu_byte l) { - struct shrmap * s = &SSM; - TString * tmp = new_string(h, str, l); - rwlock_rlock(&s->lock); - struct TString *ts = shrstr_exist(s, h, str, l); - if (ts) { - // string is create by other thread, so free tmp - free(tmp); - } else { - struct shrmap_slot *slot = &s->readwrite[lmod(h, s->rwslots)]; - ts = tmp; - ts->next = (GCObject *)slot->str; - slot->str = ts; - rwlock_wunlock(&slot->lock); - ATOM_INC(&SSM.total); - } - rwlock_runlock(&s->lock); - return ts; -} - -static TString * -internshrstr(lua_State *L, const char *str, size_t l) { - TString *ts; - unsigned int h = luaS_hash(str, l, STRSEED); - ts = query_string(h, str, l); - if (ts == NULL) { - ts = add_string(h, str, l); - } - markref(G(L)->strsave, ts, 1); - return ts; -} - -struct slotinfo { - int len; - int garbage; - size_t size; - size_t garbage_size; -}; - -static void -getslot(struct shrmap_slot *s, struct slotinfo *info) { - memset(info, 0, sizeof(*info)); - rwlock_rlock(&s->lock); - TString *ts = s->str; - while (ts) { - ++info->len; - size_t sz = sizelstring(ts->shrlen); - if (ZERO_SREF(ts)) { - ++info->garbage; - info->garbage_size += sz; - } - info->size += sz; - ts = (TString *)ts->next; - } - rwlock_runlock(&s->lock); -} - -struct variance { - int count; - double mean; - double m2; -}; - -static void -variance_update(struct variance *v, int newValue_) { - double newValue = (double)newValue_; - ++v->count; - double delta = newValue - v->mean; - v->mean += delta / v->count; - double delta2 = newValue - v->mean; - v->m2 += delta * delta2; -} - -LUA_API void -luaS_infossm(struct ssm_info *info) { - struct slotinfo total; - struct slotinfo tmp; - memset(&total, 0, sizeof(total)); - struct shrmap * s = &SSM; - struct variance v = { 0,0,0 }; - int slots = 0; - rwlock_rlock(&s->lock); - int i; - int sz = s->rwslots; - for (i=0;ireadwrite[i]; - getslot(slot, &tmp); - if (tmp.len > 0) { - if (tmp.len > total.len) { - total.len = tmp.len; - } - total.size += tmp.size; - total.garbage_size += tmp.garbage_size; - total.garbage += tmp.garbage; - variance_update(&v, tmp.len); - ++slots; - } - } - if (s->readonly) { - sz = s->roslots; - for (i=0;ireadonly[i]; - getslot(slot, &tmp); - if (tmp.len > 0) { - if (tmp.len > total.len) { - total.len = tmp.len; - } - // may double counting, but it's only an info - total.size += tmp.size; - total.garbage_size += tmp.garbage_size; - total.garbage += tmp.garbage; - variance_update(&v, tmp.len); - } - } - } - rwlock_runlock(&s->lock); - info->total = SSM.total; - info->size = total.size; - info->longest = total.len; - info->slots = slots; - info->garbage = total.garbage; - info->garbage_size = total.garbage_size; - if (v.count > 1) { - info->variance = v.m2 / v.count; - } else { - info->variance = 0; - } -} diff --git a/3rd/lua/lstring.h b/3rd/lua/lstring.h index 72ee14a0..4cb59297 100644 --- a/3rd/lua/lstring.h +++ b/3rd/lua/lstring.h @@ -28,46 +28,24 @@ /* -** equality for short strings, which are always internalized +** equality for short strings, compare id first */ -#define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b)) - +#define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b) || \ + ( ((a)->id == (b)->id) ? ((a)->id != 0) : ((a)->hash == (b)->hash && luaS_eqshrstr(a,b)) ) ) LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); +LUAI_FUNC int luaS_eqshrstr (TString *a, TString *b); +LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC void luaS_clearcache (global_State *g); LUAI_FUNC void luaS_init (lua_State *L); +LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); +LUAI_FUNC void luaS_share(TString *ts); -#define ENABLE_SHORT_STRING_TABLE - -struct ssm_info { - int total; - int longest; - int slots; - int garbage; - size_t size; - size_t garbage_size; - double variance; -}; - -struct ssm_collect { - void *key; - int n; - int sweep; -}; - -LUA_API void luaS_initssm(); -LUA_API void luaS_exitssm(); -LUA_API void luaS_infossm(struct ssm_info *info); -LUA_API int luaS_collectssm(struct ssm_collect *info); - -LUAI_FUNC void luaS_mark(global_State *g, TString *s); -LUAI_FUNC void luaS_fix(global_State *g, TString *s); -LUAI_FUNC void luaS_collect(global_State *g, int closed); #endif diff --git a/3rd/lua/lua.c b/3rd/lua/lua.c index cad0d9f4..ca5b2985 100644 --- a/3rd/lua/lua.c +++ b/3rd/lua/lua.c @@ -18,7 +18,6 @@ #include "lauxlib.h" #include "lualib.h" -#include "lstring.h" @@ -596,9 +595,7 @@ static int pmain (lua_State *L) { int main (int argc, char **argv) { int status, result; - lua_State *L; - luaS_initssm(); - L = luaL_newstate(); /* create state */ + lua_State *L = luaL_newstate(); /* create state */ if (L == NULL) { l_message(argv[0], "cannot create state: not enough memory"); return EXIT_FAILURE; @@ -610,7 +607,6 @@ int main (int argc, char **argv) { result = lua_toboolean(L, -1); /* get result */ report(L, status); lua_close(L); - luaS_exitssm(); return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/3rd/lua/lua.h b/3rd/lua/lua.h index 0595e75e..8a59176a 100644 --- a/3rd/lua/lua.h +++ b/3rd/lua/lua.h @@ -233,9 +233,11 @@ LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); LUA_API void (lua_pushboolean) (lua_State *L, int b); LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); LUA_API int (lua_pushthread) (lua_State *L); + LUA_API void (lua_clonefunction) (lua_State *L, const void * fp); LUA_API void (lua_sharefunction) (lua_State *L, int index); LUA_API void (lua_sharestring) (lua_State *L, int index); +LUA_API void (lua_clonetable) (lua_State *L, const void * t); /* ** get functions (Lua -> stack) diff --git a/3rd/lua/luac.c b/3rd/lua/luac.c index 62a0509b..549ad395 100644 --- a/3rd/lua/luac.c +++ b/3rd/lua/luac.c @@ -21,7 +21,6 @@ #include "lobject.h" #include "lstate.h" #include "lundump.h" -#include "lstring.h" static void PrintFunction(const Proto* f, int full); #define luaU_print PrintFunction @@ -193,7 +192,6 @@ static int pmain(lua_State* L) int main(int argc, char* argv[]) { lua_State* L; - luaS_initssm(); int i=doargs(argc,argv); argc-=i; argv+=i; if (argc<=0) usage("no input files given"); @@ -204,7 +202,6 @@ int main(int argc, char* argv[]) lua_pushlightuserdata(L,argv); if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); lua_close(L); - luaS_exitssm(); return EXIT_SUCCESS; } diff --git a/Makefile b/Makefile index 10076bab..36cb83bc 100644 --- a/Makefile +++ b/Makefile @@ -69,7 +69,6 @@ LUA_CLIB_SKYNET = \ lua-stm.c \ lua-debugchannel.c \ lua-datasheet.c \ - lua-ssm.c \ lua-sharetable.c \ \ diff --git a/lualib-src/lua-sharetable.c b/lualib-src/lua-sharetable.c index dce345c4..660d27ec 100644 --- a/lualib-src/lua-sharetable.c +++ b/lualib-src/lua-sharetable.c @@ -4,12 +4,9 @@ #include #include -#include "lstring.h" -#include "lobject.h" -#include "lapi.h" #include "lgc.h" -#ifdef ENABLE_SHORT_STRING_TABLE +#ifdef makeshared static void mark_shared(lua_State *L) { @@ -81,12 +78,7 @@ make_matrix(lua_State *L) { static int clone_table(lua_State *L) { - Table * t = (Table *)lua_touserdata(L, 1); - if (!isshared(t)) - return luaL_error(L, "Not a shared table"); - - sethvalue(L, L->top, t); - api_incr_top(L); + lua_clonetable(L, lua_touserdata(L, 1)); return 1; } diff --git a/lualib-src/lua-ssm.c b/lualib-src/lua-ssm.c deleted file mode 100644 index fac37850..00000000 --- a/lualib-src/lua-ssm.c +++ /dev/null @@ -1,78 +0,0 @@ -#define LUA_LIB - -#include -#include -#include - -#include "lstring.h" - -static int -linfo(lua_State *L) { - struct ssm_info info; - memset(&info, 0, sizeof(info)); - luaS_infossm(&info); - lua_createtable(L, 0, 5); - lua_pushinteger(L, info.total); - lua_setfield(L, -2, "n"); - lua_pushinteger(L, info.longest); - lua_setfield(L, -2, "longest"); - lua_pushinteger(L, info.slots); - lua_setfield(L, -2, "slots"); - lua_pushinteger(L, info.size); - lua_setfield(L, -2, "size"); - lua_pushinteger(L, info.garbage); - lua_setfield(L, -2, "garbage"); - lua_pushinteger(L, info.garbage_size); - lua_setfield(L, -2, "garbage_size"); - lua_pushnumber(L, info.variance); - lua_setfield(L, -2, "variance"); - - return 1; -} - -static int -lcollect(lua_State *L) { - int loop = lua_toboolean(L, 1); - if (loop) { - int n = 0; - struct ssm_collect info; - while (luaS_collectssm(&info)) { - n+=info.n; - } - lua_pushinteger(L, n); - return 1; - } else { - struct ssm_collect info; - int again = luaS_collectssm(&info); - if (again && lua_istable(L, 2)) { - lua_pushinteger(L, info.n); - lua_setfield(L, 2, "n"); - lua_pushinteger(L, info.sweep); - lua_setfield(L, 2, "sweep"); - lua_pushlightuserdata(L, info.key); - lua_setfield(L, 2, "key"); - } - lua_pushboolean(L, again); - return 1; - } -} - -LUAMOD_API int -luaopen_skynet_ssm(lua_State *L) { - luaL_checkversion(L); - - luaL_Reg l[] = { - { "info", linfo }, - { "collect", lcollect }, - { NULL, NULL }, - }; - - luaL_newlib(L,l); - -#ifndef ENABLE_SHORT_STRING_TABLE - lua_pushboolean(L, 1); - lua_setfield(L, -2, "disable"); -#endif - return 1; -} - diff --git a/service/bootstrap.lua b/service/bootstrap.lua index 195544b7..39f0c49c 100644 --- a/service/bootstrap.lua +++ b/service/bootstrap.lua @@ -8,8 +8,6 @@ skynet.start(function() local launcher = assert(skynet.launch("snlua","launcher")) skynet.name(".launcher", launcher) - skynet.newservice "garbagecollect" - local harbor_id = tonumber(skynet.getenv "harbor" or 0) if harbor_id == 0 then assert(standalone == nil) diff --git a/service/garbagecollect.lua b/service/garbagecollect.lua deleted file mode 100644 index f2a00f06..00000000 --- a/service/garbagecollect.lua +++ /dev/null @@ -1,26 +0,0 @@ -local skynet = require "skynet" -local ssm = require "skynet.ssm" - -local function ssm_info() - return ssm.info() -end - -local function collect() - local info = {} - while true do --- while ssm.collect(false, info) do --- skynet.error(string.format("Collect %d strings from %s, sweep %d", info.n, info.key, info.sweep)) --- end - ssm.collect(true) - skynet.sleep(50) - end -end - -skynet.start(function() - if ssm.disable then - skynet.error "Short String Map (SSM) Disabled" - skynet.exit() - end - skynet.info_func(ssm_info) - skynet.fork(collect) -end) diff --git a/skynet-src/luashrtbl.h b/skynet-src/luashrtbl.h deleted file mode 100644 index 0dcb2799..00000000 --- a/skynet-src/luashrtbl.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef LUA_SHORT_STRING_TABLE_H -#define LUA_SHORT_STRING_TABLE_H - -#include "lstring.h" - -// If you use modified lua, this macro would be defined in lstring.h -#ifndef ENABLE_SHORT_STRING_TABLE - -struct ssm_info { - int total; - int longest; - int slots; - size_t size; - double variance; -}; - -struct ssm_collect { - void *key; - int n; -}; - -static inline void luaS_initssm(); -static inline void luaS_exitssm(); -static inline void luaS_infossm(struct ssm_info *info) {} -static inline int luaS_collectssm(struct ssm_collect *info) { return 0; } - -#endif - -#endif diff --git a/skynet-src/skynet_main.c b/skynet-src/skynet_main.c index d9aef78a..ba7bb847 100644 --- a/skynet-src/skynet_main.c +++ b/skynet-src/skynet_main.c @@ -3,7 +3,6 @@ #include "skynet_imp.h" #include "skynet_env.h" #include "skynet_server.h" -#include "luashrtbl.h" #include #include @@ -126,7 +125,6 @@ main(int argc, char *argv[]) { return 1; } - luaS_initssm(); skynet_globalinit(); skynet_env_init(); @@ -162,7 +160,6 @@ main(int argc, char *argv[]) { skynet_start(&config); skynet_globalexit(); - luaS_exitssm(); return 0; }