Skip to content

Commit

Permalink
core: introduce various platform metrics
Browse files Browse the repository at this point in the history
This patch introduces the following counters:
  - overall amount of allocated tables, cdata and udata objects
  - number of incremental GC steps grouped by GC state
  - number of string hashes hits and misses
  - amount of allocated and freed memory
  - number of trace aborts, number of traces and restored snapshots

Also this patch fixes alignment for 64-bit architectures.

NB: MSize and BCIns are the only fixed types that equal 32 bits. GCRef,
MRef and GCSize sizes depend on LJ_GC64 define.

struct GCState is terminated by three fields: GCSize estimate, MSize
stepmul and MSize pause, which are aligned. The introduced size_t
fields do not violate the alignment too.

vmstate 32-bit field goes right after GCState field within global_State
structure. The next field tmpbuf consists of several MRef fields that
have 64-bit size each. This issue can be solved by moving vmstate field
below. However DynASM doesn't work well with unaligned memory access on
64-bit bigendian MIPS, so vmstate should be aligned to a 64-bit
boundary.

Furthermore field order has been changed to be able to compile code by
DynASM for 32-bit ARM too (see also
openresty/luajit2#37 (comment)).

Interfaces to obtain these metrics via both Lua and C API are
introduced in the next patch.

Part of tarantool/tarantool#5187
  • Loading branch information
Buristan authored and igormunkin committed Jun 16, 2022
1 parent f20a71d commit 0ddbf67
Show file tree
Hide file tree
Showing 17 changed files with 76 additions and 8 deletions.
7 changes: 7 additions & 0 deletions src/lj_asm_arm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1328,9 +1328,16 @@ static void asm_cnew(ASMState *as, IRIns *ir)
{
uint32_t k = emit_isk12(ARMI_MOV, id);
Reg r = k ? RID_R1 : ra_allock(as, id, allow);
allow = rset_exclude(allow, r);
Reg gr = ra_allock(as, i32ptr(J2G(as->J)), allow);
emit_lso(as, ARMI_STRB, RID_TMP, RID_RET, offsetof(GCcdata, gct));
emit_lsox(as, ARMI_STRH, r, RID_RET, offsetof(GCcdata, ctypeid));
emit_d(as, ARMI_MOV|ARMI_K12|~LJ_TCDATA, RID_TMP);
emit_lso(as, ARMI_STR, RID_TMP, gr,
(int32_t)offsetof(global_State, gc.cdatanum));
emit_dn(as, ARMI_ADD|ARMI_K12|1, RID_TMP, RID_TMP);
emit_lso(as, ARMI_LDR, RID_TMP, gr,
(int32_t)offsetof(global_State, gc.cdatanum));
if (k) emit_d(as, ARMI_MOV^k, RID_R1);
}
args[0] = ASMREF_L; /* lua_State *L */
Expand Down
7 changes: 7 additions & 0 deletions src/lj_asm_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1267,9 +1267,16 @@ static void asm_cnew(ASMState *as, IRIns *ir)
/* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
{
Reg r = (id < 65536) ? RID_X1 : ra_allock(as, id, allow);
allow = rset_exclude(allow, r);
Reg gr = ra_allock(as, i64ptr(J2G(as->J)), allow);
emit_lso(as, A64I_STRB, RID_TMP, RID_RET, offsetof(GCcdata, gct));
emit_lso(as, A64I_STRH, r, RID_RET, offsetof(GCcdata, ctypeid));
emit_d(as, A64I_MOVZw | A64F_U16(~LJ_TCDATA), RID_TMP);
emit_lso(as, A64I_STRx, RID_TMP, gr,
(int32_t)offsetof(global_State, gc.cdatanum));
emit_dn(as, (A64I_ADDx^A64I_K12) | A64F_U12(1), RID_TMP, RID_TMP);
emit_lso(as, A64I_LDRx, RID_TMP, gr,
(int32_t)offsetof(global_State, gc.cdatanum));
if (id < 65536) emit_d(as, A64I_MOVZw | A64F_U16(id), RID_X1);
}
args[0] = ASMREF_L; /* lua_State *L */
Expand Down
8 changes: 7 additions & 1 deletion src/lj_asm_mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -1633,7 +1633,9 @@ static void asm_cnew(ASMState *as, IRIns *ir)
CTInfo info = lj_ctype_info(cts, id, &sz);
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
IRRef args[4];
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
RegSet drop = RSET_SCRATCH;
Reg tmp;
lj_assertA(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL),
"bad CNEW/CNEWI operands");

Expand All @@ -1646,7 +1648,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)

/* Initialize immutable cdata object. */
if (ir->o == IR_CNEWI) {
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
#if LJ_32
int32_t ofs = sizeof(GCcdata);
if (sz == 8) {
Expand Down Expand Up @@ -1677,11 +1678,16 @@ static void asm_cnew(ASMState *as, IRIns *ir)
return;
}

tmp = ra_scratch(as, allow);
/* Code incrementing cdatanum is sparse to avoid mips data hazards. */
emit_setgl(as, tmp, gc.cdatanum);
/* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));
emit_tsi(as, MIPSI_AADDIU, tmp, tmp, 1);
emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA);
emit_ti(as, MIPSI_LI, RID_TMP, id); /* Lower 16 bit used. Sign-ext ok. */
emit_getgl(as, tmp, gc.cdatanum);
args[0] = ASMREF_L; /* lua_State *L */
args[1] = ASMREF_TMP1; /* MSize size */
asm_gencall(as, ci, args);
Expand Down
3 changes: 3 additions & 0 deletions src/lj_asm_ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,9 @@ static void asm_cnew(ASMState *as, IRIns *ir)
return;
}

emit_setgl(as, RID_TMP, gc.cdatanum);
emit_tai(as, PPCI_ADDIC, RID_TMP, RID_TMP, 1);
emit_getgl(as, RID_TMP, gc.cdatanum);
/* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
emit_tai(as, PPCI_STB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
emit_tai(as, PPCI_STH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));
Expand Down
4 changes: 4 additions & 0 deletions src/lj_asm_x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,10 @@ static void asm_cnew(ASMState *as, IRIns *ir)
return;
}

/* Increment cdatanum counter by address directly. */
emit_i8(as, 1);
emit_rmro(as, XO_ARITHi8, XOg_ADD, RID_NONE,
ptr2addr(&J2G(as->J)->gc.cdatanum));
/* Combine initialization of marked, gct and ctypeid. */
emit_movtomro(as, RID_ECX, RID_RET, offsetof(GCcdata, marked));
emit_gri(as, XG_ARITHi(XOg_OR), RID_ECX,
Expand Down
2 changes: 2 additions & 0 deletions src/lj_cdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ GCcdata *lj_cdata_newv(lua_State *L, CTypeID id, CTSize sz, CTSize align)
cd->marked |= 0x80;
cd->gct = ~LJ_TCDATA;
cd->ctypeid = id;
g->gc.cdatanum++;
return cd;
}

Expand Down Expand Up @@ -82,6 +83,7 @@ void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd)
} else {
lj_mem_free(g, memcdatav(cd), sizecdatav(cd));
}
g->gc.cdatanum--;
}

void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj, uint32_t it)
Expand Down
2 changes: 2 additions & 0 deletions src/lj_cdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz)
cd = (GCcdata *)lj_mem_newgco(cts->L, sizeof(GCcdata) + sz);
cd->gct = ~LJ_TCDATA;
cd->ctypeid = ctype_check(cts, id);
G(cts->L)->gc.cdatanum++;
return cd;
}

Expand All @@ -55,6 +56,7 @@ static LJ_AINLINE GCcdata *lj_cdata_new_(lua_State *L, CTypeID id, CTSize sz)
GCcdata *cd = (GCcdata *)lj_mem_newgco(L, sizeof(GCcdata) + sz);
cd->gct = ~LJ_TCDATA;
cd->ctypeid = id;
G(L)->gc.cdatanum++;
return cd;
}

Expand Down
4 changes: 4 additions & 0 deletions src/lj_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ static void atomic(global_State *g, lua_State *L)
static size_t gc_onestep(lua_State *L)
{
global_State *g = G(L);
g->gc.state_count[g->gc.state]++;
switch (g->gc.state) {
case GCSpause:
gc_mark_start(g); /* Start a new GC cycle by marking all GC roots. */
Expand Down Expand Up @@ -872,6 +873,8 @@ void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz)
lj_assertG(checkptrGC(p),
"allocated memory address %p outside required range", p);
g->gc.total = (g->gc.total - osz) + nsz;
g->gc.allocated += nsz;
g->gc.freed += osz;
return p;
}

Expand All @@ -885,6 +888,7 @@ void * LJ_FASTCALL lj_mem_newgco(lua_State *L, GCSize size)
lj_assertG(checkptrGC(o),
"allocated memory address %p outside required range", o);
g->gc.total += size;
g->gc.allocated += size;
setgcrefr(o->gch.nextgc, g->gc.root);
setgcref(g->gc.root, o);
newwhite(g, o);
Expand Down
6 changes: 1 addition & 5 deletions src/lj_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@

#include "lj_obj.h"

/* Garbage collector states. Order matters. */
enum {
GCSpause, GCSpropagate, GCSatomic, GCSsweepstring, GCSsweep, GCSfinalize
};

/* Bitmasks for marked field of GCobj. */
#define LJ_GC_WHITE0 0x01
#define LJ_GC_WHITE1 0x02
Expand Down Expand Up @@ -119,6 +114,7 @@ LJ_FUNC void *lj_mem_grow(lua_State *L, void *p,
static LJ_AINLINE void lj_mem_free(global_State *g, void *p, size_t osize)
{
g->gc.total -= (GCSize)osize;
g->gc.freed += osize;
g->allocf(g->allocd, p, osize, 0);
}

Expand Down
3 changes: 3 additions & 0 deletions src/lj_jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,9 @@ typedef struct jit_State {
MCode *mcbot; /* Bottom of current mcode area. */
size_t szmcarea; /* Size of current mcode area. */
size_t szallmcarea; /* Total size of all allocated mcode areas. */
size_t tracenum; /* Overall number of traces. */
size_t nsnaprestore; /* Overall number of snap restores. */
size_t ntraceabort; /* Overall number of abort traces. */

TValue errinfo; /* Additional info element for trace errors. */

Expand Down
22 changes: 22 additions & 0 deletions src/lj_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,17 @@ typedef enum {
#define basemt_obj(g, o) ((g)->gcroot[GCROOT_BASEMT+itypemap(o)])
#define mmname_str(g, mm) (strref((g)->gcroot[GCROOT_MMNAME+(mm)]))

/* Garbage collector states. Order matters. */
enum {
GCSpause, /* Start a GC cycle and mark the root set.*/
GCSpropagate, /* One gray object is processed. */
GCSatomic, /* Atomic transition from mark to sweep phase. */
GCSsweepstring, /* Sweep one chain of strings. */
GCSsweep, /* Sweep few objects from root. */
GCSfinalize, /* Finalize one userdata or cdata object. */
GCSmax
};

/* Garbage collector state. */
typedef struct GCState {
GCSize total; /* Memory currently allocated. */
Expand All @@ -612,6 +623,15 @@ typedef struct GCState {
#if LJ_64
MRef lightudseg; /* Upper bits of lightuserdata segments. */
#endif

size_t freed; /* Total amount of freed memory. */
size_t allocated; /* Total amount of allocated memory. */
size_t state_count[GCSmax]; /* Count of incremental GC steps per state. */
size_t tabnum; /* Amount of allocated table objects. */
size_t udatanum; /* Amount of allocated udata objects. */
#ifdef LJ_HASFFI
size_t cdatanum; /* Amount of allocated cdata objects. */
#endif
} GCState;

/* String interning state. */
Expand All @@ -632,6 +652,8 @@ typedef struct global_State {
lua_Alloc allocf; /* Memory allocator. */
void *allocd; /* Memory allocator data. */
GCState gc; /* Garbage collector. */
size_t strhash_hit; /* Strings amount found in string hash. */
size_t strhash_miss; /* Strings amount allocated and put into string hash. */
GCstr strempty; /* Empty string. */
uint8_t stremptyz; /* Zero terminator of empty string. */
uint8_t hookmask; /* Hook mask. */
Expand Down
1 change: 1 addition & 0 deletions src/lj_snap.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,7 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
L->top = frame + snap->nslots;
break;
}
J->nsnaprestore++;
return pc;
}

Expand Down
2 changes: 1 addition & 1 deletion src/lj_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ LUA_API lua_State *lua_newstate(lua_Alloc allocf, void *allocd)
g->gc.state = GCSpause;
setgcref(g->gc.root, obj2gco(L));
setmref(g->gc.sweep, &g->gc.root);
g->gc.total = sizeof(GG_State);
g->gc.allocated = g->gc.total = sizeof(GG_State);
g->gc.pause = LUAI_GCPAUSE;
g->gc.stepmul = LUAI_GCMUL;
lj_dispatch_init((GG_State *)L);
Expand Down
2 changes: 2 additions & 0 deletions src/lj_str.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
if (sx->hash == hash && sx->len == len) {
if (memcmp(str, strdata(sx), len) == 0) {
if (isdead(g, o)) flipwhite(o); /* Resurrect if dead. */
g->strhash_hit++;
return sx; /* Return existing string. */
}
coll++;
Expand All @@ -358,6 +359,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
return lj_str_rehash_chain(L, hash, str, len);
}
#endif
g->strhash_miss++;
/* Otherwise allocate a new string. */
return lj_str_alloc(L, str, len, hash, hashalg);
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/lj_tab.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
}
if (hbits)
newhpart(L, t, hbits);
G(L)->gc.tabnum++;
return t;
}

Expand Down Expand Up @@ -222,6 +223,7 @@ void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t)
lj_mem_free(g, t, sizetabcolo((uint32_t)t->colo & 0x7f));
else
lj_mem_freet(g, t);
g->gc.tabnum--;
}

/* -- Table resizing ------------------------------------------------------ */
Expand Down
7 changes: 6 additions & 1 deletion src/lj_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ GCtrace * LJ_FASTCALL lj_trace_alloc(lua_State *L, GCtrace *T)
T2->nsnap = T->nsnap;
T2->nsnapmap = T->nsnapmap;
memcpy(p, T->ir + T->nk, szins);
L2J(L)->tracenum++;
return T2;
}

Expand Down Expand Up @@ -178,6 +179,7 @@ void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T)
lj_mem_free(g, T,
((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry));
J->tracenum--;
}

/* Re-enable compiling a prototype by unpatching any modified bytecode. */
Expand Down Expand Up @@ -555,8 +557,10 @@ static int trace_downrec(jit_State *J)
/* Restart recording at the return instruction. */
lj_assertJ(J->pt != NULL, "no active prototype");
lj_assertJ(bc_isret(bc_op(*J->pc)), "not at a return bytecode");
if (bc_op(*J->pc) == BC_RETM)
if (bc_op(*J->pc) == BC_RETM) {
J->ntraceabort++;
return 0; /* NYI: down-recursion with RETM. */
}
J->parent = 0;
J->exitno = 0;
J->state = LJ_TRACE_RECORD;
Expand Down Expand Up @@ -633,6 +637,7 @@ static int trace_abort(jit_State *J)
return trace_downrec(J);
else if (e == LJ_TRERR_MCODEAL)
lj_trace_flushall(L);
J->ntraceabort++;
return 0;
}

Expand Down
2 changes: 2 additions & 0 deletions src/lj_udata.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ GCudata *lj_udata_new(lua_State *L, MSize sz, GCtab *env)
/* Chain to userdata list (after main thread). */
setgcrefr(ud->nextgc, mainthread(g)->nextgc);
setgcref(mainthread(g)->nextgc, obj2gco(ud));
g->gc.udatanum++;
return ud;
}

void LJ_FASTCALL lj_udata_free(global_State *g, GCudata *ud)
{
g->gc.udatanum--;
lj_mem_free(g, ud, sizeudata(ud));
}

Expand Down

0 comments on commit 0ddbf67

Please sign in to comment.