Skip to content

Commit 5f6775a

Browse files
Buristankyukhin
authored andcommitted
core: introduce various platform metrics
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
1 parent ad1d444 commit 5f6775a

17 files changed

+82
-11
lines changed

src/lj_asm_arm.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,9 +1257,16 @@ static void asm_cnew(ASMState *as, IRIns *ir)
12571257
{
12581258
uint32_t k = emit_isk12(ARMI_MOV, id);
12591259
Reg r = k ? RID_R1 : ra_allock(as, id, allow);
1260+
allow = rset_exclude(allow, r);
1261+
Reg gr = ra_allock(as, i32ptr(J2G(as->J)), allow);
12601262
emit_lso(as, ARMI_STRB, RID_TMP, RID_RET, offsetof(GCcdata, gct));
12611263
emit_lsox(as, ARMI_STRH, r, RID_RET, offsetof(GCcdata, ctypeid));
12621264
emit_d(as, ARMI_MOV|ARMI_K12|~LJ_TCDATA, RID_TMP);
1265+
emit_lso(as, ARMI_STR, RID_TMP, gr,
1266+
(int32_t)offsetof(global_State, gc.cdatanum));
1267+
emit_dn(as, ARMI_ADD|ARMI_K12|1, RID_TMP, RID_TMP);
1268+
emit_lso(as, ARMI_LDR, RID_TMP, gr,
1269+
(int32_t)offsetof(global_State, gc.cdatanum));
12631270
if (k) emit_d(as, ARMI_MOV^k, RID_R1);
12641271
}
12651272
args[0] = ASMREF_L; /* lua_State *L */

src/lj_asm_arm64.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,9 +1220,16 @@ static void asm_cnew(ASMState *as, IRIns *ir)
12201220
/* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
12211221
{
12221222
Reg r = (id < 65536) ? RID_X1 : ra_allock(as, id, allow);
1223+
allow = rset_exclude(allow, r);
1224+
Reg gr = ra_allock(as, i64ptr(J2G(as->J)), allow);
12231225
emit_lso(as, A64I_STRB, RID_TMP, RID_RET, offsetof(GCcdata, gct));
12241226
emit_lso(as, A64I_STRH, r, RID_RET, offsetof(GCcdata, ctypeid));
12251227
emit_d(as, A64I_MOVZw | A64F_U16(~LJ_TCDATA), RID_TMP);
1228+
emit_lso(as, A64I_STRx, RID_TMP, gr,
1229+
(int32_t)offsetof(global_State, gc.cdatanum));
1230+
emit_dn(as, (A64I_ADDx^A64I_K12) | A64F_U12(1), RID_TMP, RID_TMP);
1231+
emit_lso(as, A64I_LDRx, RID_TMP, gr,
1232+
(int32_t)offsetof(global_State, gc.cdatanum));
12261233
if (id < 65536) emit_d(as, A64I_MOVZw | A64F_U16(id), RID_X1);
12271234
}
12281235
args[0] = ASMREF_L; /* lua_State *L */

src/lj_asm_mips.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,9 @@ static void asm_cnew(ASMState *as, IRIns *ir)
14301430
CTInfo info = lj_ctype_info(cts, id, &sz);
14311431
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
14321432
IRRef args[4];
1433+
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
14331434
RegSet drop = RSET_SCRATCH;
1435+
Reg tmp;
14341436
lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL));
14351437

14361438
as->gcsteps++;
@@ -1442,7 +1444,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
14421444

14431445
/* Initialize immutable cdata object. */
14441446
if (ir->o == IR_CNEWI) {
1445-
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
14461447
#if LJ_32
14471448
int32_t ofs = sizeof(GCcdata);
14481449
if (sz == 8) {
@@ -1473,11 +1474,16 @@ static void asm_cnew(ASMState *as, IRIns *ir)
14731474
return;
14741475
}
14751476

1477+
tmp = ra_scratch(as, allow);
1478+
/* Code incrementing cdatanum is sparse to avoid mips data hazards. */
1479+
emit_setgl(as, tmp, gc.cdatanum);
14761480
/* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
14771481
emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
14781482
emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));
1483+
emit_tsi(as, MIPSI_AADDIU, tmp, tmp, 1);
14791484
emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA);
14801485
emit_ti(as, MIPSI_LI, RID_TMP, id); /* Lower 16 bit used. Sign-ext ok. */
1486+
emit_getgl(as, tmp, gc.cdatanum);
14811487
args[0] = ASMREF_L; /* lua_State *L */
14821488
args[1] = ASMREF_TMP1; /* MSize size */
14831489
asm_gencall(as, ci, args);

src/lj_asm_ppc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,9 @@ static void asm_cnew(ASMState *as, IRIns *ir)
10571057
return;
10581058
}
10591059

1060+
emit_setgl(as, RID_TMP, gc.cdatanum);
1061+
emit_tai(as, PPCI_ADDIC, RID_TMP, RID_TMP, 1);
1062+
emit_getgl(as, RID_TMP, gc.cdatanum);
10601063
/* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
10611064
emit_tai(as, PPCI_STB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
10621065
emit_tai(as, PPCI_STH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));

src/lj_asm_x86.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,10 @@ static void asm_cnew(ASMState *as, IRIns *ir)
18351835
return;
18361836
}
18371837

1838+
/* Increment cdatanum counter by address directly. */
1839+
emit_i8(as, 1);
1840+
emit_rmro(as, XO_ARITHi8, XOg_ADD, RID_NONE,
1841+
ptr2addr(&J2G(as->J)->gc.cdatanum));
18381842
/* Combine initialization of marked, gct and ctypeid. */
18391843
emit_movtomro(as, RID_ECX, RID_RET, offsetof(GCcdata, marked));
18401844
emit_gri(as, XG_ARITHi(XOg_OR), RID_ECX,

src/lj_cdata.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ GCcdata *lj_cdata_newv(lua_State *L, CTypeID id, CTSize sz, CTSize align)
4646
cd->marked |= 0x80;
4747
cd->gct = ~LJ_TCDATA;
4848
cd->ctypeid = id;
49+
g->gc.cdatanum++;
4950
return cd;
5051
}
5152

@@ -82,6 +83,7 @@ void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd)
8283
} else {
8384
lj_mem_free(g, memcdatav(cd), sizecdatav(cd));
8485
}
86+
g->gc.cdatanum--;
8587
}
8688

8789
void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj, uint32_t it)

src/lj_cdata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz)
4545
cd = (GCcdata *)lj_mem_newgco(cts->L, sizeof(GCcdata) + sz);
4646
cd->gct = ~LJ_TCDATA;
4747
cd->ctypeid = ctype_check(cts, id);
48+
G(cts->L)->gc.cdatanum++;
4849
return cd;
4950
}
5051

@@ -54,6 +55,7 @@ static LJ_AINLINE GCcdata *lj_cdata_new_(lua_State *L, CTypeID id, CTSize sz)
5455
GCcdata *cd = (GCcdata *)lj_mem_newgco(L, sizeof(GCcdata) + sz);
5556
cd->gct = ~LJ_TCDATA;
5657
cd->ctypeid = id;
58+
G(L)->gc.cdatanum++;
5759
return cd;
5860
}
5961

src/lj_gc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ static void atomic(global_State *g, lua_State *L)
634634
static size_t gc_onestep(lua_State *L)
635635
{
636636
global_State *g = G(L);
637+
g->gc.state_count[g->gc.state]++;
637638
switch (g->gc.state) {
638639
case GCSpause:
639640
gc_mark_start(g); /* Start a new GC cycle by marking all GC roots. */
@@ -857,6 +858,8 @@ void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz)
857858
lua_assert((nsz == 0) == (p == NULL));
858859
lua_assert(checkptrGC(p));
859860
g->gc.total = (g->gc.total - osz) + nsz;
861+
g->gc.allocated += nsz;
862+
g->gc.freed += osz;
860863
return p;
861864
}
862865

@@ -869,6 +872,7 @@ void * LJ_FASTCALL lj_mem_newgco(lua_State *L, GCSize size)
869872
lj_err_mem(L);
870873
lua_assert(checkptrGC(o));
871874
g->gc.total += size;
875+
g->gc.allocated += size;
872876
setgcrefr(o->gch.nextgc, g->gc.root);
873877
setgcref(g->gc.root, o);
874878
newwhite(g, o);

src/lj_gc.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88

99
#include "lj_obj.h"
1010

11-
/* Garbage collector states. Order matters. */
12-
enum {
13-
GCSpause, GCSpropagate, GCSatomic, GCSsweepstring, GCSsweep, GCSfinalize
14-
};
15-
1611
/* Bitmasks for marked field of GCobj. */
1712
#define LJ_GC_WHITE0 0x01
1813
#define LJ_GC_WHITE1 0x02
@@ -117,6 +112,7 @@ LJ_FUNC void *lj_mem_grow(lua_State *L, void *p,
117112
static LJ_AINLINE void lj_mem_free(global_State *g, void *p, size_t osize)
118113
{
119114
g->gc.total -= (GCSize)osize;
115+
g->gc.freed += osize;
120116
g->allocf(g->allocd, p, osize, 0);
121117
}
122118

src/lj_jit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,9 @@ typedef struct jit_State {
474474
MCode *mcbot; /* Bottom of current mcode area. */
475475
size_t szmcarea; /* Size of current mcode area. */
476476
size_t szallmcarea; /* Total size of all allocated mcode areas. */
477+
size_t tracenum; /* Overall number of traces. */
478+
size_t nsnaprestore; /* Overall number of snap restores. */
479+
size_t ntraceabort; /* Overall number of abort traces. */
477480

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

src/lj_obj.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,17 @@ typedef enum {
571571
#define basemt_obj(g, o) ((g)->gcroot[GCROOT_BASEMT+itypemap(o)])
572572
#define mmname_str(g, mm) (strref((g)->gcroot[GCROOT_MMNAME+(mm)]))
573573

574+
/* Garbage collector states. Order matters. */
575+
enum {
576+
GCSpause, /* Start a GC cycle and mark the root set.*/
577+
GCSpropagate, /* One gray object is processed. */
578+
GCSatomic, /* Atomic transition from mark to sweep phase. */
579+
GCSsweepstring, /* Sweep one chain of strings. */
580+
GCSsweep, /* Sweep few objects from root. */
581+
GCSfinalize, /* Finalize one userdata or cdata object. */
582+
GCSmax
583+
};
584+
574585
typedef struct GCState {
575586
GCSize total; /* Memory currently allocated. */
576587
GCSize threshold; /* Memory threshold. */
@@ -589,6 +600,15 @@ typedef struct GCState {
589600
GCSize estimate; /* Estimate of memory actually in use. */
590601
MSize stepmul; /* Incremental GC step granularity. */
591602
MSize pause; /* Pause between successive GC cycles. */
603+
604+
size_t freed; /* Total amount of freed memory. */
605+
size_t allocated; /* Total amount of allocated memory. */
606+
size_t state_count[GCSmax]; /* Count of incremental GC steps per state. */
607+
size_t tabnum; /* Amount of allocated table objects. */
608+
size_t udatanum; /* Amount of allocated udata objects. */
609+
#ifdef LJ_HASFFI
610+
size_t cdatanum; /* Amount of allocated cdata objects. */
611+
#endif
592612
} GCState;
593613

594614
/* Global state, shared by all threads of a Lua universe. */
@@ -602,22 +622,24 @@ typedef struct global_State {
602622
BloomFilter next[2];
603623
} strbloom;
604624
#endif
625+
size_t strhash_hit; /* Strings amount found in string hash. */
626+
size_t strhash_miss; /* Strings amount allocated and put into string hash. */
605627
lua_Alloc allocf; /* Memory allocator. */
606628
void *allocd; /* Memory allocator data. */
607629
GCState gc; /* Garbage collector. */
608-
volatile int32_t vmstate; /* VM state or current JIT code trace number. */
609630
SBuf tmpbuf; /* Temporary string buffer. */
610631
GCstr strempty; /* Empty string. */
611632
uint8_t stremptyz; /* Zero terminator of empty string. */
612633
uint8_t hookmask; /* Hook mask. */
613634
uint8_t dispatchmode; /* Dispatch mode. */
614635
uint8_t vmevmask; /* VM event mask. */
636+
int32_t hookcount; /* Instruction hook countdown. */
615637
GCRef mainthref; /* Link to main thread. */
616638
TValue registrytv; /* Anchor for registry. */
617-
TValue tmptv, tmptv2; /* Temporary TValues. */
639+
TValue tmptv2, tmptv; /* Temporary TValues. */
618640
Node nilnode; /* Fallback 1-element hash part (nil key and value). */
619641
GCupval uvhead; /* Head of double-linked list of all open upvalues. */
620-
int32_t hookcount; /* Instruction hook countdown. */
642+
volatile int32_t vmstate; /* VM state or current JIT code trace number. */
621643
int32_t hookcstart; /* Start count for instruction hook counter. */
622644
lua_Hook hookf; /* Hook function. */
623645
lua_CFunction wrapf; /* Wrapper for C function calls. */

src/lj_snap.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,7 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
904904
L->top = frame + snap->nslots;
905905
break;
906906
}
907+
J->nsnaprestore++;
907908
return pc;
908909
}
909910

src/lj_state.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
214214
g->gc.state = GCSpause;
215215
setgcref(g->gc.root, obj2gco(L));
216216
setmref(g->gc.sweep, &g->gc.root);
217-
g->gc.total = sizeof(GG_State);
217+
g->gc.allocated = g->gc.total = sizeof(GG_State);
218218
g->gc.pause = LUAI_GCPAUSE;
219219
g->gc.stepmul = LUAI_GCMUL;
220220
lj_dispatch_init((GG_State *)L);

src/lj_str.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
222222
str_fastcmp(str, strdata(sx), len) == 0) {
223223
/* Resurrect if dead. Can only happen with fixstring() (keywords). */
224224
if (isdead(g, o)) flipwhite(o);
225+
g->strhash_hit++;
225226
return sx; /* Return existing string. */
226227
}
227228
o = gcnext(o);
@@ -234,6 +235,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
234235
memcmp(str, strdata(sx), len) == 0) {
235236
/* Resurrect if dead. Can only happen with fixstring() (keywords). */
236237
if (isdead(g, o)) flipwhite(o);
238+
g->strhash_hit++;
237239
return sx; /* Return existing string. */
238240
}
239241
o = gcnext(o);
@@ -266,6 +268,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
266268
if (sx->hash == fh && sx->len == len && str_fastcmp(str, strdata(sx), len) == 0) {
267269
/* Resurrect if dead. Can only happen with fixstring() (keywords). */
268270
if (isdead(g, o)) flipwhite(o);
271+
g->strhash_hit++;
269272
return sx; /* Return existing string. */
270273
}
271274
o = gcnext(o);
@@ -276,6 +279,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
276279
if (sx->hash == fh && sx->len == len && memcmp(str, strdata(sx), len) == 0) {
277280
/* Resurrect if dead. Can only happen with fixstring() (keywords). */
278281
if (isdead(g, o)) flipwhite(o);
282+
g->strhash_hit++;
279283
return sx; /* Return existing string. */
280284
}
281285
o = gcnext(o);
@@ -293,6 +297,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
293297
}
294298
}
295299
#endif
300+
g->strhash_miss++;
296301
/* Nope, create a new string. */
297302
s = lj_mem_newt(L, sizeof(GCstr)+len+1, GCstr);
298303
newwhite(g, s);

src/lj_tab.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
141141
}
142142
if (hbits)
143143
newhpart(L, t, hbits);
144+
G(L)->gc.tabnum++;
144145
return t;
145146
}
146147

@@ -240,6 +241,7 @@ void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t)
240241
lj_mem_free(g, t, sizetabcolo((uint32_t)t->colo & 0x7f));
241242
else
242243
lj_mem_freet(g, t);
244+
g->gc.tabnum--;
243245
}
244246

245247
/* -- Table resizing ------------------------------------------------------ */

src/lj_trace.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ GCtrace * LJ_FASTCALL lj_trace_alloc(lua_State *L, GCtrace *T)
136136
T2->nsnap = T->nsnap;
137137
T2->nsnapmap = T->nsnapmap;
138138
memcpy(p, T->ir + T->nk, szins);
139+
L2J(L)->tracenum++;
139140
return T2;
140141
}
141142

@@ -176,6 +177,7 @@ void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T)
176177
lj_mem_free(g, T,
177178
((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
178179
T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry));
180+
J->tracenum--;
179181
}
180182

181183
/* Re-enable compiling a prototype by unpatching any modified bytecode. */
@@ -538,8 +540,10 @@ static int trace_downrec(jit_State *J)
538540
/* Restart recording at the return instruction. */
539541
lua_assert(J->pt != NULL);
540542
lua_assert(bc_isret(bc_op(*J->pc)));
541-
if (bc_op(*J->pc) == BC_RETM)
543+
if (bc_op(*J->pc) == BC_RETM) {
544+
J->ntraceabort++;
542545
return 0; /* NYI: down-recursion with RETM. */
546+
}
543547
J->parent = 0;
544548
J->exitno = 0;
545549
J->state = LJ_TRACE_RECORD;
@@ -616,6 +620,7 @@ static int trace_abort(jit_State *J)
616620
return trace_downrec(J);
617621
else if (e == LJ_TRERR_MCODEAL)
618622
lj_trace_flushall(L);
623+
J->ntraceabort++;
619624
return 0;
620625
}
621626

src/lj_udata.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ GCudata *lj_udata_new(lua_State *L, MSize sz, GCtab *env)
2424
/* Chain to userdata list (after main thread). */
2525
setgcrefr(ud->nextgc, mainthread(g)->nextgc);
2626
setgcref(mainthread(g)->nextgc, obj2gco(ud));
27+
g->gc.udatanum++;
2728
return ud;
2829
}
2930

3031
void LJ_FASTCALL lj_udata_free(global_State *g, GCudata *ud)
3132
{
33+
g->gc.udatanum--;
3234
lj_mem_free(g, ud, sizeudata(ud));
3335
}
3436

0 commit comments

Comments
 (0)