mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
add global share string table
This commit is contained in:
@@ -19,7 +19,7 @@ SYSCFLAGS=
|
||||
SYSLDFLAGS=
|
||||
SYSLIBS=
|
||||
|
||||
MYCFLAGS=
|
||||
MYCFLAGS=-I../../skynet-src
|
||||
MYLDFLAGS=
|
||||
MYLIBS=
|
||||
MYOBJS=
|
||||
|
||||
@@ -1000,7 +1000,7 @@ static Proto * cloneproto (lua_State *L, const Proto *src) {
|
||||
const TValue *s=&src->k[i];
|
||||
TValue *o=&f->k[i];
|
||||
if (ttisstring(s)) {
|
||||
TString * str = luaS_newlstr(L,svalue(s),vslen(s));
|
||||
TString * str = luaS_clonestring(L,tsvalue(s));
|
||||
setsvalue2n(L,o,str);
|
||||
} else {
|
||||
setobj(L,o,s);
|
||||
@@ -1288,7 +1288,7 @@ static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
|
||||
StkId fi = index2addr(L, fidx);
|
||||
api_check(L, ttisLclosure(fi), "Lua function expected");
|
||||
f = clLvalue(fi);
|
||||
api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
|
||||
api_check(L, (1 <= n && n <= f->p->sp->sizeupvalues), "invalid upvalue index");
|
||||
if (pf) *pf = f;
|
||||
return &f->upvals[n - 1]; /* get its upvalue pointer */
|
||||
}
|
||||
|
||||
@@ -188,7 +188,8 @@ void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
|
||||
|
||||
void luaC_fix (lua_State *L, GCObject *o) {
|
||||
global_State *g = G(L);
|
||||
lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
|
||||
if (g->allgc != o)
|
||||
return; /* if object is not 1st in 'allgc' list, it is in global short string table */
|
||||
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 */
|
||||
|
||||
@@ -148,10 +148,9 @@ void luaS_remove (lua_State *L, TString *ts) {
|
||||
/*
|
||||
** 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) {
|
||||
static TString *queryshrstr (lua_State *L, const char *str, size_t l, unsigned int h) {
|
||||
TString *ts;
|
||||
global_State *g = G(L);
|
||||
unsigned int h = luaS_hash(str, l, g->seed);
|
||||
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
|
||||
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
|
||||
if (l == ts->shrlen &&
|
||||
@@ -162,6 +161,13 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static TString *addshrstr (lua_State *L, const char *str, size_t l, unsigned int h) {
|
||||
TString *ts;
|
||||
global_State *g = G(L);
|
||||
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
|
||||
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 */
|
||||
@@ -174,6 +180,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
||||
return ts;
|
||||
}
|
||||
|
||||
static TString *internshrstr (lua_State *L, const char *str, size_t l);
|
||||
|
||||
/*
|
||||
** new string (with explicit length)
|
||||
@@ -224,3 +231,216 @@ Udata *luaS_newudata (lua_State *L, size_t s) {
|
||||
return u;
|
||||
}
|
||||
|
||||
/*
|
||||
* global shared table
|
||||
*/
|
||||
|
||||
#include "rwlock.h"
|
||||
#include "atomic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SHRSTR_SLOT 0x10000
|
||||
#define HASH_NODE(h) ((h) % SHRSTR_SLOT)
|
||||
|
||||
struct shrmap_slot {
|
||||
struct rwlock lock;
|
||||
TString *str;
|
||||
};
|
||||
|
||||
struct shrmap {
|
||||
struct shrmap_slot h[SHRSTR_SLOT];
|
||||
int n;
|
||||
};
|
||||
|
||||
static struct shrmap *SSM = NULL;
|
||||
|
||||
LUA_API void
|
||||
luaS_initshr() {
|
||||
struct shrmap * s = malloc(sizeof(*s));
|
||||
memset(s, 0, sizeof(*s));
|
||||
int i;
|
||||
for (i=0;i<SHRSTR_SLOT;i++) {
|
||||
rwlock_init(&s->h[i].lock);
|
||||
}
|
||||
SSM = s;
|
||||
}
|
||||
|
||||
LUA_API void
|
||||
luaS_exitshr() {
|
||||
int i;
|
||||
for (i=0;i<SHRSTR_SLOT;i++) {
|
||||
TString *str = SSM->h[i].str;
|
||||
while (str) {
|
||||
TString * next = str->u.hnext;
|
||||
free(str);
|
||||
str = next;
|
||||
}
|
||||
}
|
||||
free(SSM);
|
||||
}
|
||||
|
||||
static TString *
|
||||
query_string(unsigned int h, const char *str, lu_byte l) {
|
||||
struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
|
||||
rwlock_rlock(&s->lock);
|
||||
TString *ts = s->str;
|
||||
while (ts) {
|
||||
if (ts->hash == h &&
|
||||
ts->shrlen == l &&
|
||||
memcmp(str, ts+1, l) == 0) {
|
||||
break;
|
||||
}
|
||||
ts = ts->u.hnext;
|
||||
}
|
||||
rwlock_runlock(&s->lock);
|
||||
return ts;
|
||||
}
|
||||
|
||||
static TString *
|
||||
query_ptr(TString *t) {
|
||||
unsigned int h = t->hash;
|
||||
struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
|
||||
rwlock_rlock(&s->lock);
|
||||
TString *ts = s->str;
|
||||
while (ts) {
|
||||
if (ts == t)
|
||||
break;
|
||||
ts = ts->u.hnext;
|
||||
}
|
||||
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);
|
||||
ts->tt = LUA_TSHRSTR;
|
||||
ts->hash = h;
|
||||
ts->shrlen = l;
|
||||
memcpy(ts+1, str, l);
|
||||
return ts;
|
||||
}
|
||||
|
||||
static TString *
|
||||
add_string(unsigned int h, const char *str, lu_byte l) {
|
||||
TString * tmp = new_string(h, str, l);
|
||||
struct shrmap_slot *s = &SSM->h[HASH_NODE(h)];
|
||||
rwlock_wlock(&s->lock);
|
||||
TString *ts = s->str;
|
||||
while (ts) {
|
||||
if (ts->hash == h &&
|
||||
ts->shrlen == l &&
|
||||
memcmp(str, ts+1, l) == 0) {
|
||||
break;
|
||||
}
|
||||
ts = ts->u.hnext;
|
||||
}
|
||||
if (ts == NULL) {
|
||||
ts = tmp;
|
||||
ts->u.hnext = s->str;
|
||||
s->str = ts;
|
||||
tmp = NULL;
|
||||
}
|
||||
rwlock_wunlock(&s->lock);
|
||||
if (tmp) {
|
||||
// string is create by other thread, so free tmp
|
||||
free(tmp);
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
|
||||
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, g->seed);
|
||||
unsigned int h0;
|
||||
// lookup global state of this L first
|
||||
ts = queryshrstr (L, str, l, h);
|
||||
if (ts)
|
||||
return ts;
|
||||
// lookup SSM again
|
||||
h0 = luaS_hash(str, l, 0);
|
||||
ts = query_string(h0, str, l);
|
||||
if (ts)
|
||||
return ts;
|
||||
// If SSM->n greate than 0, add it to SSM
|
||||
if (SSM->n > 0) {
|
||||
ATOM_DEC(&SSM->n);
|
||||
return add_string(h0, str, l);
|
||||
}
|
||||
// Else add it to global state (local)
|
||||
return addshrstr (L, str, l, h);
|
||||
}
|
||||
|
||||
LUA_API void
|
||||
luaS_expandshr(int n) {
|
||||
ATOM_ADD(&SSM->n, n);
|
||||
}
|
||||
|
||||
LUAI_FUNC TString *
|
||||
luaS_clonestring(lua_State *L, TString *ts) {
|
||||
unsigned int h;
|
||||
int l;
|
||||
const char * str = getaddrstr(ts);
|
||||
global_State *g = G(L);
|
||||
TString *result;
|
||||
if (ts->tt == LUA_TLNGSTR)
|
||||
return luaS_newlstr(L, str, ts->u.lnglen);
|
||||
// look up global state of this L first
|
||||
l = ts->shrlen;
|
||||
h = luaS_hash(str, l, g->seed);
|
||||
result = queryshrstr (L, str, l, h);
|
||||
if (result)
|
||||
return result;
|
||||
// look up SSM by ptr
|
||||
result = query_ptr(ts);
|
||||
if (result)
|
||||
return result;
|
||||
// ts is not in SSM, so recalc hash, and add it to SSM
|
||||
h = luaS_hash(str, l, 0);
|
||||
return add_string(h, str, l);
|
||||
}
|
||||
|
||||
struct slotinfo {
|
||||
int len;
|
||||
int 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;
|
||||
info->size += ts->shrlen;
|
||||
ts = ts->u.hnext;
|
||||
}
|
||||
rwlock_runlock(&s->lock);
|
||||
}
|
||||
|
||||
LUA_API int
|
||||
luaS_shrinfo(lua_State *L) {
|
||||
struct slotinfo total;
|
||||
struct slotinfo tmp;
|
||||
memset(&total, 0, sizeof(total));
|
||||
int i;
|
||||
int len = 0;
|
||||
for (i=0;i<SHRSTR_SLOT;i++) {
|
||||
struct shrmap_slot *s = &SSM->h[i];
|
||||
getslot(s, &tmp);
|
||||
len += tmp.len;
|
||||
if (tmp.len > total.len) {
|
||||
total.len = tmp.len;
|
||||
}
|
||||
total.size += tmp.size;
|
||||
}
|
||||
lua_pushinteger(L, len);
|
||||
lua_pushinteger(L, total.size);
|
||||
lua_pushinteger(L, total.len);
|
||||
lua_pushinteger(L, SSM->n);
|
||||
return 4;
|
||||
}
|
||||
|
||||
@@ -43,5 +43,10 @@ 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);
|
||||
|
||||
LUA_API void luaS_initshr();
|
||||
LUA_API void luaS_exitshr();
|
||||
LUA_API void luaS_expandshr(int n);
|
||||
LUAI_FUNC TString *luaS_clonestring(lua_State *L, TString *);
|
||||
LUA_API int luaS_shrinfo(lua_State *L);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define LUA_USE_APICHECK
|
||||
|
||||
/*
|
||||
** ===================================================================
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "malloc_hook.h"
|
||||
#include "luashrtbl.h"
|
||||
|
||||
static int
|
||||
ltotal(lua_State *L) {
|
||||
@@ -33,6 +34,13 @@ ldump(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lexpandshrtbl(lua_State *L) {
|
||||
int n = luaL_checkinteger(L, 1);
|
||||
luaS_expandshr(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
luaopen_memory(lua_State *L) {
|
||||
luaL_checkversion(L);
|
||||
@@ -43,6 +51,8 @@ luaopen_memory(lua_State *L) {
|
||||
{ "dumpinfo", ldumpinfo },
|
||||
{ "dump", ldump },
|
||||
{ "info", dump_mem_lua },
|
||||
{ "ssinfo", luaS_shrinfo },
|
||||
{ "ssexpand", lexpandshrtbl },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
local skynet = require "skynet"
|
||||
local harbor = require "skynet.harbor"
|
||||
require "skynet.manager" -- import skynet.launch, ...
|
||||
local memory = require "memory"
|
||||
|
||||
skynet.start(function()
|
||||
local sharestring = tonumber(skynet.getenv "sharestring")
|
||||
memory.ssexpand(sharestring or 4096)
|
||||
|
||||
local standalone = skynet.getenv "standalone"
|
||||
|
||||
local launcher = assert(skynet.launch("snlua","launcher"))
|
||||
|
||||
@@ -3,6 +3,7 @@ local codecache = require "skynet.codecache"
|
||||
local core = require "skynet.core"
|
||||
local socket = require "socket"
|
||||
local snax = require "snax"
|
||||
local memory = require "memory"
|
||||
|
||||
local port = tonumber(...)
|
||||
local COMMAND = {}
|
||||
@@ -130,6 +131,8 @@ function COMMAND.help()
|
||||
log = "launch a new lua service with log",
|
||||
debug = "debug address : debug a lua service",
|
||||
signal = "signal address sig",
|
||||
cmem = "Show C memory info",
|
||||
shrtbl = "Show shared short string table info",
|
||||
}
|
||||
end
|
||||
|
||||
@@ -258,3 +261,19 @@ function COMMAND.signal(address, sig)
|
||||
core.command("SIGNAL", address)
|
||||
end
|
||||
end
|
||||
|
||||
function COMMAND.cmem()
|
||||
local info = memory.info()
|
||||
local tmp = {}
|
||||
for k,v in pairs(info) do
|
||||
tmp[skynet.address(k)] = v
|
||||
end
|
||||
return tmp
|
||||
end
|
||||
|
||||
function COMMAND.shrtbl()
|
||||
local n, total, longest, space = memory.ssinfo()
|
||||
return { n = n, total = total, longest = longest, space = space }
|
||||
end
|
||||
|
||||
|
||||
|
||||
17
skynet-src/luashrtbl.h
Normal file
17
skynet-src/luashrtbl.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef LUA_SHORT_STRING_TABLE_H
|
||||
#define LUA_SHORT_STRING_TABLE_H
|
||||
|
||||
#ifndef DISABLE_SHORT_STRING
|
||||
|
||||
#include "lstring.h"
|
||||
|
||||
#else
|
||||
|
||||
static inline int luaS_shrinfo(lua_State *L) { return 0; }
|
||||
static inline void luaS_initshr() {}
|
||||
static inline void luaS_exitshr() {}
|
||||
static inline void luaS_expandshr(int n);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "skynet_imp.h"
|
||||
#include "skynet_env.h"
|
||||
#include "skynet_server.h"
|
||||
#include "luashrtbl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -105,6 +106,8 @@ main(int argc, char *argv[]) {
|
||||
"usage: skynet configfilename\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
luaS_initshr();
|
||||
skynet_globalinit();
|
||||
skynet_env_init();
|
||||
|
||||
@@ -139,6 +142,7 @@ main(int argc, char *argv[]) {
|
||||
|
||||
skynet_start(&config);
|
||||
skynet_globalexit();
|
||||
luaS_exitshr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user