Skip to content

Commit c0862d8

Browse files
committed
add global share string table
1 parent 1b53e6e commit c0862d8

File tree

11 files changed

+287
-6
lines changed

11 files changed

+287
-6
lines changed

3rd/lua/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ SYSCFLAGS=
1919
SYSLDFLAGS=
2020
SYSLIBS=
2121

22-
MYCFLAGS=
22+
MYCFLAGS=-I../../skynet-src
2323
MYLDFLAGS=
2424
MYLIBS=
2525
MYOBJS=

3rd/lua/lapi.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ static Proto * cloneproto (lua_State *L, const Proto *src) {
10001000
const TValue *s=&src->k[i];
10011001
TValue *o=&f->k[i];
10021002
if (ttisstring(s)) {
1003-
TString * str = luaS_newlstr(L,svalue(s),vslen(s));
1003+
TString * str = luaS_clonestring(L,tsvalue(s));
10041004
setsvalue2n(L,o,str);
10051005
} else {
10061006
setobj(L,o,s);
@@ -1288,7 +1288,7 @@ static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
12881288
StkId fi = index2addr(L, fidx);
12891289
api_check(L, ttisLclosure(fi), "Lua function expected");
12901290
f = clLvalue(fi);
1291-
api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
1291+
api_check(L, (1 <= n && n <= f->p->sp->sizeupvalues), "invalid upvalue index");
12921292
if (pf) *pf = f;
12931293
return &f->upvals[n - 1]; /* get its upvalue pointer */
12941294
}

3rd/lua/lgc.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
188188

189189
void luaC_fix (lua_State *L, GCObject *o) {
190190
global_State *g = G(L);
191-
lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
191+
if (g->allgc != o)
192+
return; /* if object is not 1st in 'allgc' list, it is in global short string table */
192193
white2gray(o); /* they will be gray forever */
193194
g->allgc = o->next; /* remove object from 'allgc' list */
194195
o->next = g->fixedgc; /* link it to 'fixedgc' list */

3rd/lua/lstring.c

+222-2
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,9 @@ void luaS_remove (lua_State *L, TString *ts) {
148148
/*
149149
** checks whether short string exists and reuses it or creates a new one
150150
*/
151-
static TString *internshrstr (lua_State *L, const char *str, size_t l) {
151+
static TString *queryshrstr (lua_State *L, const char *str, size_t l, unsigned int h) {
152152
TString *ts;
153153
global_State *g = G(L);
154-
unsigned int h = luaS_hash(str, l, g->seed);
155154
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
156155
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
157156
if (l == ts->shrlen &&
@@ -162,6 +161,13 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
162161
return ts;
163162
}
164163
}
164+
return NULL;
165+
}
166+
167+
static TString *addshrstr (lua_State *L, const char *str, size_t l, unsigned int h) {
168+
TString *ts;
169+
global_State *g = G(L);
170+
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
165171
if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) {
166172
luaS_resize(L, g->strt.size * 2);
167173
list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
@@ -174,6 +180,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
174180
return ts;
175181
}
176182

183+
static TString *internshrstr (lua_State *L, const char *str, size_t l);
177184

178185
/*
179186
** new string (with explicit length)
@@ -224,3 +231,216 @@ Udata *luaS_newudata (lua_State *L, size_t s) {
224231
return u;
225232
}
226233

234+
/*
235+
* global shared table
236+
*/
237+
238+
#include "rwlock.h"
239+
#include "atomic.h"
240+
#include <stdlib.h>
241+
242+
#define SHRSTR_SLOT 0x10000
243+
#define HASH_NODE(h) ((h) % SHRSTR_SLOT)
244+
245+
struct shrmap_slot {
246+
struct rwlock lock;
247+
TString *str;
248+
};
249+
250+
struct shrmap {
251+
struct shrmap_slot h[SHRSTR_SLOT];
252+
int n;
253+
};
254+
255+
static struct shrmap *SSM = NULL;
256+
257+
LUA_API void
258+
luaS_initshr() {
259+
struct shrmap * s = malloc(sizeof(*s));
260+
memset(s, 0, sizeof(*s));
261+
int i;
262+
for (i=0;i<SHRSTR_SLOT;i++) {
263+
rwlock_init(&s->h[i].lock);
264+
}
265+
SSM = s;
266+
}
267+
268+
LUA_API void
269+
luaS_exitshr() {
270+
int i;
271+
for (i=0;i<SHRSTR_SLOT;i++) {
272+
TString *str = SSM->h[i].str;
273+
while (str) {
274+
TString * next = str->u.hnext;
275+
free(str);
276+
str = next;
277+
}
278+
}
279+
free(SSM);
280+
}
281+
282+
static TString *
283+
query_string(unsigned int h, const char *str, lu_byte l) {
284+
struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
285+
rwlock_rlock(&s->lock);
286+
TString *ts = s->str;
287+
while (ts) {
288+
if (ts->hash == h &&
289+
ts->shrlen == l &&
290+
memcmp(str, ts+1, l) == 0) {
291+
break;
292+
}
293+
ts = ts->u.hnext;
294+
}
295+
rwlock_runlock(&s->lock);
296+
return ts;
297+
}
298+
299+
static TString *
300+
query_ptr(TString *t) {
301+
unsigned int h = t->hash;
302+
struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
303+
rwlock_rlock(&s->lock);
304+
TString *ts = s->str;
305+
while (ts) {
306+
if (ts == t)
307+
break;
308+
ts = ts->u.hnext;
309+
}
310+
rwlock_runlock(&s->lock);
311+
return ts;
312+
}
313+
314+
static TString *
315+
new_string(unsigned int h, const char *str, lu_byte l) {
316+
size_t sz = sizelstring(l);
317+
TString *ts = malloc(sz);
318+
memset(ts, 0, sz);
319+
ts->tt = LUA_TSHRSTR;
320+
ts->hash = h;
321+
ts->shrlen = l;
322+
memcpy(ts+1, str, l);
323+
return ts;
324+
}
325+
326+
static TString *
327+
add_string(unsigned int h, const char *str, lu_byte l) {
328+
TString * tmp = new_string(h, str, l);
329+
struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
330+
rwlock_wlock(&s->lock);
331+
TString *ts = s->str;
332+
while (ts) {
333+
if (ts->hash == h &&
334+
ts->shrlen == l &&
335+
memcmp(str, ts+1, l) == 0) {
336+
break;
337+
}
338+
ts = ts->u.hnext;
339+
}
340+
if (ts == NULL) {
341+
ts = tmp;
342+
ts->u.hnext = s->str;
343+
s->str = ts;
344+
tmp = NULL;
345+
}
346+
rwlock_wunlock(&s->lock);
347+
if (tmp) {
348+
// string is create by other thread, so free tmp
349+
free(tmp);
350+
}
351+
return ts;
352+
}
353+
354+
static TString *
355+
internshrstr (lua_State *L, const char *str, size_t l) {
356+
TString *ts;
357+
global_State *g = G(L);
358+
unsigned int h = luaS_hash(str, l, g->seed);
359+
unsigned int h0;
360+
// lookup global state of this L first
361+
ts = queryshrstr (L, str, l, h);
362+
if (ts)
363+
return ts;
364+
// lookup SSM again
365+
h0 = luaS_hash(str, l, 0);
366+
ts = query_string(h0, str, l);
367+
if (ts)
368+
return ts;
369+
// If SSM->n greate than 0, add it to SSM
370+
if (SSM->n > 0) {
371+
ATOM_DEC(&SSM->n);
372+
return add_string(h0, str, l);
373+
}
374+
// Else add it to global state (local)
375+
return addshrstr (L, str, l, h);
376+
}
377+
378+
LUA_API void
379+
luaS_expandshr(int n) {
380+
ATOM_ADD(&SSM->n, n);
381+
}
382+
383+
LUAI_FUNC TString *
384+
luaS_clonestring(lua_State *L, TString *ts) {
385+
unsigned int h;
386+
int l;
387+
const char * str = getaddrstr(ts);
388+
global_State *g = G(L);
389+
TString *result;
390+
if (ts->tt == LUA_TLNGSTR)
391+
return luaS_newlstr(L, str, ts->u.lnglen);
392+
// look up global state of this L first
393+
l = ts->shrlen;
394+
h = luaS_hash(str, l, g->seed);
395+
result = queryshrstr (L, str, l, h);
396+
if (result)
397+
return result;
398+
// look up SSM by ptr
399+
result = query_ptr(ts);
400+
if (result)
401+
return result;
402+
// ts is not in SSM, so recalc hash, and add it to SSM
403+
h = luaS_hash(str, l, 0);
404+
return add_string(h, str, l);
405+
}
406+
407+
struct slotinfo {
408+
int len;
409+
int size;
410+
};
411+
412+
static void
413+
getslot(struct shrmap_slot *s, struct slotinfo *info) {
414+
memset(info, 0, sizeof(*info));
415+
rwlock_rlock(&s->lock);
416+
TString *ts = s->str;
417+
while (ts) {
418+
++info->len;
419+
info->size += ts->shrlen;
420+
ts = ts->u.hnext;
421+
}
422+
rwlock_runlock(&s->lock);
423+
}
424+
425+
LUA_API int
426+
luaS_shrinfo(lua_State *L) {
427+
struct slotinfo total;
428+
struct slotinfo tmp;
429+
memset(&total, 0, sizeof(total));
430+
int i;
431+
int len = 0;
432+
for (i=0;i<SHRSTR_SLOT;i++) {
433+
struct shrmap_slot *s = &SSM->h[i];
434+
getslot(s, &tmp);
435+
len += tmp.len;
436+
if (tmp.len > total.len) {
437+
total.len = tmp.len;
438+
}
439+
total.size += tmp.size;
440+
}
441+
lua_pushinteger(L, len);
442+
lua_pushinteger(L, total.size);
443+
lua_pushinteger(L, total.len);
444+
lua_pushinteger(L, SSM->n);
445+
return 4;
446+
}

3rd/lua/lstring.h

+5
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,10 @@ LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
4343
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
4444
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
4545

46+
LUA_API void luaS_initshr();
47+
LUA_API void luaS_exitshr();
48+
LUA_API void luaS_expandshr(int n);
49+
LUAI_FUNC TString *luaS_clonestring(lua_State *L, TString *);
50+
LUA_API int luaS_shrinfo(lua_State *L);
4651

4752
#endif

3rd/lua/luaconf.h

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <limits.h>
1212
#include <stddef.h>
1313

14+
#define LUA_USE_APICHECK
1415

1516
/*
1617
** ===================================================================

lualib-src/lua-memory.c

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <lauxlib.h>
33

44
#include "malloc_hook.h"
5+
#include "luashrtbl.h"
56

67
static int
78
ltotal(lua_State *L) {
@@ -33,6 +34,13 @@ ldump(lua_State *L) {
3334
return 0;
3435
}
3536

37+
static int
38+
lexpandshrtbl(lua_State *L) {
39+
int n = luaL_checkinteger(L, 1);
40+
luaS_expandshr(n);
41+
return 0;
42+
}
43+
3644
int
3745
luaopen_memory(lua_State *L) {
3846
luaL_checkversion(L);
@@ -43,6 +51,8 @@ luaopen_memory(lua_State *L) {
4351
{ "dumpinfo", ldumpinfo },
4452
{ "dump", ldump },
4553
{ "info", dump_mem_lua },
54+
{ "ssinfo", luaS_shrinfo },
55+
{ "ssexpand", lexpandshrtbl },
4656
{ NULL, NULL },
4757
};
4858

service/bootstrap.lua

+4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
local skynet = require "skynet"
22
local harbor = require "skynet.harbor"
33
require "skynet.manager" -- import skynet.launch, ...
4+
local memory = require "memory"
45

56
skynet.start(function()
7+
local sharestring = tonumber(skynet.getenv "sharestring")
8+
memory.ssexpand(sharestring or 4096)
9+
610
local standalone = skynet.getenv "standalone"
711

812
local launcher = assert(skynet.launch("snlua","launcher"))

service/debug_console.lua

+19
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ local codecache = require "skynet.codecache"
33
local core = require "skynet.core"
44
local socket = require "socket"
55
local snax = require "snax"
6+
local memory = require "memory"
67

78
local port = tonumber(...)
89
local COMMAND = {}
@@ -130,6 +131,8 @@ function COMMAND.help()
130131
log = "launch a new lua service with log",
131132
debug = "debug address : debug a lua service",
132133
signal = "signal address sig",
134+
cmem = "Show C memory info",
135+
shrtbl = "Show shared short string table info",
133136
}
134137
end
135138

@@ -258,3 +261,19 @@ function COMMAND.signal(address, sig)
258261
core.command("SIGNAL", address)
259262
end
260263
end
264+
265+
function COMMAND.cmem()
266+
local info = memory.info()
267+
local tmp = {}
268+
for k,v in pairs(info) do
269+
tmp[skynet.address(k)] = v
270+
end
271+
return tmp
272+
end
273+
274+
function COMMAND.shrtbl()
275+
local n, total, longest, space = memory.ssinfo()
276+
return { n = n, total = total, longest = longest, space = space }
277+
end
278+
279+

0 commit comments

Comments
 (0)