profiler
This commit is contained in:
parent
5b2d221d0b
commit
e2fda60745
@ -10,6 +10,10 @@ Execute the contents of the file as if it were REPL input (but allowing multilin
|
|||||||
|
|
||||||
Execute the expression, but don't print its result.
|
Execute the expression, but don't print its result.
|
||||||
|
|
||||||
|
## `)profile expr` / `)profile@frequency expr`
|
||||||
|
|
||||||
|
Profile the expression at the given sampling frequency, or 5000 samples/second by default
|
||||||
|
|
||||||
## `)t expr` / `)time expr` / `)t:n expr` / `)time:n expr`
|
## `)t expr` / `)time expr` / `)t:n expr` / `)time:n expr`
|
||||||
|
|
||||||
Time the argument expression. `n` specifies the number of times to repeat. Exists to allow not escaping quotes and less overhead for timing very fast & small expressions.
|
Time the argument expression. `n` specifies the number of times to repeat. Exists to allow not escaping quotes and less overhead for timing very fast & small expressions.
|
||||||
|
|||||||
@ -339,6 +339,22 @@ B gid2str(i32 n) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* profiler_makeMap() {
|
||||||
|
return m_b2i(64);
|
||||||
|
}
|
||||||
|
i32 profiler_index(void** mapRaw, B comp) {
|
||||||
|
H_b2i* map = *(H_b2i**)mapRaw;
|
||||||
|
i32 r;
|
||||||
|
bool had; u64 p = mk_b2i(&map, comp, &had);
|
||||||
|
if (had) r = map->a[p].val;
|
||||||
|
else r = map->a[p].val = map->pop-1;
|
||||||
|
*(H_b2i**)mapRaw = map;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
void profiler_freeMap(void* mapRaw) {
|
||||||
|
free_b2i((H_b2i*)mapRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void fun_gcFn() {
|
void fun_gcFn() {
|
||||||
|
|||||||
@ -150,7 +150,7 @@ void fprint(FILE* f, B x) {
|
|||||||
}
|
}
|
||||||
else if (isVar(x)) fprintf(f, "(var d=%d i=%d)", (u16)(x.u>>32), (i32)x.u);
|
else if (isVar(x)) fprintf(f, "(var d=%d i=%d)", (u16)(x.u>>32), (i32)x.u);
|
||||||
else if (isExt(x)) fprintf(f, "(extvar d=%d i=%d)", (u16)(x.u>>32), (i32)x.u);
|
else if (isExt(x)) fprintf(f, "(extvar d=%d i=%d)", (u16)(x.u>>32), (i32)x.u);
|
||||||
else if (x.u==bi_N.u) fprintf(f, "·");
|
else if (x.u==bi_N.u) fprintf(f, "(native ·)");
|
||||||
else if (x.u==bi_optOut.u) fprintf(f, "(value optimized out)");
|
else if (x.u==bi_optOut.u) fprintf(f, "(value optimized out)");
|
||||||
else if (x.u==bi_noVar.u) fprintf(f, "(unset variable placeholder)");
|
else if (x.u==bi_noVar.u) fprintf(f, "(unset variable placeholder)");
|
||||||
else if (x.u==bi_okHdr.u) fprintf(f, "(accepted SETH placeholder)");
|
else if (x.u==bi_okHdr.u) fprintf(f, "(accepted SETH placeholder)");
|
||||||
|
|||||||
@ -36,7 +36,7 @@ __attribute__((optnone))
|
|||||||
static void* mmap_nvm(u64 sz) {
|
static void* mmap_nvm(u64 sz) {
|
||||||
u64 near = (u64)&bqn_exec;
|
u64 near = (u64)&bqn_exec;
|
||||||
u64 MAX_DIST = 1ULL<<30;
|
u64 MAX_DIST = 1ULL<<30;
|
||||||
if (near < MAX_DIST) return mmap(NULL, sz, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_NORESERVE|MAP_PRIVATE|MAP_ANON|MAP_32BIT, -1, 0);
|
if (near < MAX_DIST) return mmap(NULL, sz, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0);
|
||||||
u64 ps = getPageSize();
|
u64 ps = getPageSize();
|
||||||
|
|
||||||
i32 attempt = 0;
|
i32 attempt = 0;
|
||||||
@ -50,7 +50,7 @@ static void* mmap_nvm(u64 sz) {
|
|||||||
#ifdef MAP_FIXED_NOREPLACE
|
#ifdef MAP_FIXED_NOREPLACE
|
||||||
noreplace|= MAP_FIXED_NOREPLACE;
|
noreplace|= MAP_FIXED_NOREPLACE;
|
||||||
#endif
|
#endif
|
||||||
void* c = mmap((void*)loc, sz, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_NORESERVE|MAP_PRIVATE|MAP_ANON|noreplace, -1, 0);
|
void* c = mmap((void*)loc, sz, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS|noreplace, -1, 0);
|
||||||
if (c==NULL) continue;
|
if (c==NULL) continue;
|
||||||
|
|
||||||
i64 dist = (i64)near - (i64)c;
|
i64 dist = (i64)near - (i64)c;
|
||||||
@ -241,7 +241,7 @@ u32 perfid = 0;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void* nvm_alloc(u64 sz) {
|
static void* nvm_alloc(u64 sz) {
|
||||||
// void* r = mmap(NULL, sz, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON|MAP_32BIT, -1, 0);
|
// void* r = mmap(NULL, sz, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0);
|
||||||
// if (r==MAP_FAILED) thrM("JIT: Failed to allocate executable memory");
|
// if (r==MAP_FAILED) thrM("JIT: Failed to allocate executable memory");
|
||||||
// return r;
|
// return r;
|
||||||
I8Arr* src = mmX_allocN(fsizeof(I8Arr,a,u8,sz), t_i8arr);
|
I8Arr* src = mmX_allocN(fsizeof(I8Arr,a,u8,sz), t_i8arr);
|
||||||
|
|||||||
14
src/load.c
14
src/load.c
@ -116,11 +116,11 @@ Block* load_compObj(B x, B src, B path, Scope* sc) { // consumes x,src
|
|||||||
}
|
}
|
||||||
#include "gen/src"
|
#include "gen/src"
|
||||||
#if RT_SRC
|
#if RT_SRC
|
||||||
Block* load_compImport(B bc, B objs, B blocks, B bodies, B inds, B src) { // consumes all
|
Block* load_compImport(char* name, B bc, B objs, B blocks, B bodies, B inds, B src) { // consumes all
|
||||||
return compile(bc, objs, blocks, bodies, inds, bi_N, src, m_str8l("(precompiled)"), NULL);
|
return compile(bc, objs, blocks, bodies, inds, bi_N, src, m_str8l(name), NULL);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Block* load_compImport(B bc, B objs, B blocks, B bodies) { // consumes all
|
Block* load_compImport(char* name, B bc, B objs, B blocks, B bodies) { // consumes all
|
||||||
return compile(bc, objs, blocks, bodies, bi_N, bi_N, bi_N, bi_N, NULL);
|
return compile(bc, objs, blocks, bodies, bi_N, bi_N, bi_N, bi_N, NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -350,14 +350,14 @@ void load_init() { // very last init function
|
|||||||
#ifndef ALL_R0
|
#ifndef ALL_R0
|
||||||
B runtime_0[] = {bi_floor,bi_ceil,bi_stile,bi_lt,bi_gt,bi_ne,bi_ge,bi_rtack,bi_ltack,bi_join,bi_pair,bi_take,bi_drop,bi_select,bi_const,bi_swap,bi_each,bi_fold,bi_atop,bi_over,bi_before,bi_after,bi_cond,bi_repeat};
|
B runtime_0[] = {bi_floor,bi_ceil,bi_stile,bi_lt,bi_gt,bi_ne,bi_ge,bi_rtack,bi_ltack,bi_join,bi_pair,bi_take,bi_drop,bi_select,bi_const,bi_swap,bi_each,bi_fold,bi_atop,bi_over,bi_before,bi_after,bi_cond,bi_repeat};
|
||||||
#else
|
#else
|
||||||
Block* runtime0_b = load_compImport(
|
Block* runtime0_b = load_compImport("r0.bqn",
|
||||||
#include "gen/runtime0"
|
#include "gen/runtime0"
|
||||||
);
|
);
|
||||||
B r0r = evalFunBlock(runtime0_b, 0); ptr_dec(runtime0_b);
|
B r0r = evalFunBlock(runtime0_b, 0); ptr_dec(runtime0_b);
|
||||||
B* runtime_0 = toHArr(r0r)->a;
|
B* runtime_0 = toHArr(r0r)->a;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Block* runtime_b = load_compImport(
|
Block* runtime_b = load_compImport("r1.bqn",
|
||||||
#include "gen/runtime1"
|
#include "gen/runtime1"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -458,7 +458,7 @@ void load_init() { // very last init function
|
|||||||
#else // use compiler
|
#else // use compiler
|
||||||
B prevAsrt = runtime[n_asrt];
|
B prevAsrt = runtime[n_asrt];
|
||||||
runtime[n_asrt] = bi_casrt; // horrible but GC is off so it's fiiiiiine
|
runtime[n_asrt] = bi_casrt; // horrible but GC is off so it's fiiiiiine
|
||||||
Block* comp_b = load_compImport(
|
Block* comp_b = load_compImport("c.bqn",
|
||||||
#include "gen/compiles"
|
#include "gen/compiles"
|
||||||
);
|
);
|
||||||
runtime[n_asrt] = prevAsrt;
|
runtime[n_asrt] = prevAsrt;
|
||||||
@ -469,7 +469,7 @@ void load_init() { // very last init function
|
|||||||
|
|
||||||
|
|
||||||
#if FORMATTER
|
#if FORMATTER
|
||||||
Block* fmt_b = load_compImport(
|
Block* fmt_b = load_compImport("f.bqn",
|
||||||
#include "gen/formatter"
|
#include "gen/formatter"
|
||||||
);
|
);
|
||||||
B fmtM = evalFunBlock(fmt_b, 0); ptr_dec(fmt_b);
|
B fmtM = evalFunBlock(fmt_b, 0); ptr_dec(fmt_b);
|
||||||
|
|||||||
42
src/main.c
42
src/main.c
@ -38,7 +38,22 @@ static bool isCmd(char* s, char** e, const char* cmd) {
|
|||||||
*e = s;
|
*e = s;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool profiler_alloc(void);
|
||||||
|
bool profiler_start(i64 hz);
|
||||||
|
bool profiler_stop(void);
|
||||||
|
void profiler_free(void);
|
||||||
|
void profiler_displayResults(void);
|
||||||
|
|
||||||
|
i64 readInt(char** p) {
|
||||||
|
char* c = *p;
|
||||||
|
i64 am = 0;
|
||||||
|
while (*c>='0' & *c<='9') {
|
||||||
|
am = am*10 + (*c - '0');
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
*p = c;
|
||||||
|
return am;
|
||||||
|
}
|
||||||
void cbqn_runLine0(char* ln, i64 read) {
|
void cbqn_runLine0(char* ln, i64 read) {
|
||||||
if (ln[0]==10) return;
|
if (ln[0]==10) return;
|
||||||
if (ln[read-1]==10) ln[--read] = 0;
|
if (ln[read-1]==10) ln[--read] = 0;
|
||||||
@ -46,6 +61,7 @@ void cbqn_runLine0(char* ln, i64 read) {
|
|||||||
B code;
|
B code;
|
||||||
int output; // 0-no; 1-formatter; 2-internal
|
int output; // 0-no; 1-formatter; 2-internal
|
||||||
i32 time = 0;
|
i32 time = 0;
|
||||||
|
i64 profile = -1;
|
||||||
if (ln[0] == ')') {
|
if (ln[0] == ')') {
|
||||||
char* cmdS = ln+1;
|
char* cmdS = ln+1;
|
||||||
char* cmdE;
|
char* cmdE;
|
||||||
@ -60,13 +76,16 @@ void cbqn_runLine0(char* ln, i64 read) {
|
|||||||
code = fromUTF8l(cmdE);
|
code = fromUTF8l(cmdE);
|
||||||
time = -1;
|
time = -1;
|
||||||
output = 0;
|
output = 0;
|
||||||
|
} else if (isCmd(cmdS, &cmdE, "profile ") || isCmd(cmdS, &cmdE, "profile@")) {
|
||||||
|
char* cpos = cmdE;
|
||||||
|
profile = '@'==*(cpos-1)? readInt(&cpos) : 5000;
|
||||||
|
if (profile==0) { printf("Cannot profile with 0hz sampling frequency\n"); return; }
|
||||||
|
if (profile>999999) { printf("Cannot profile with >999999hz frequency\n"); return; }
|
||||||
|
code = fromUTF8l(cmdE);
|
||||||
|
output = 0;
|
||||||
} else if (isCmd(cmdS, &cmdE, "t:") || isCmd(cmdS, &cmdE, "time:")) {
|
} else if (isCmd(cmdS, &cmdE, "t:") || isCmd(cmdS, &cmdE, "time:")) {
|
||||||
char* repE = cmdE;
|
char* repE = cmdE;
|
||||||
i64 am = 0;
|
i64 am = readInt(&repE);
|
||||||
while (*repE>='0' & *repE<='9') {
|
|
||||||
am = am*10 + (*repE - '0');
|
|
||||||
repE++;
|
|
||||||
}
|
|
||||||
if (repE==cmdE) { printf("time command not given repetition count\n"); return; }
|
if (repE==cmdE) { printf("time command not given repetition count\n"); return; }
|
||||||
if (am==0) { printf("repetition count was zero\n"); return; }
|
if (am==0) { printf("repetition count was zero\n"); return; }
|
||||||
code = fromUTF8l(repE);
|
code = fromUTF8l(repE);
|
||||||
@ -187,9 +206,16 @@ void cbqn_runLine0(char* ln, i64 read) {
|
|||||||
else if (t<1e6) printf("%.4gus\n", t/1e3);
|
else if (t<1e6) printf("%.4gus\n", t/1e3);
|
||||||
else if (t<1e9) printf("%.4gms\n", t/1e6);
|
else if (t<1e9) printf("%.4gms\n", t/1e6);
|
||||||
else printf("%.5gs\n", t/1e9);
|
else printf("%.5gs\n", t/1e9);
|
||||||
} else {
|
} else if (profile>0) {
|
||||||
res = execBlockInline(block, gsc);
|
if (CATCH) { profiler_stop(); profiler_free(); rethrow(); }
|
||||||
}
|
if (profiler_alloc() && profiler_start(profile)) {
|
||||||
|
res = execBlockInline(block, gsc);
|
||||||
|
profiler_stop();
|
||||||
|
profiler_displayResults();
|
||||||
|
profiler_free();
|
||||||
|
}
|
||||||
|
popCatch();
|
||||||
|
} else res = execBlockInline(block, gsc);
|
||||||
ptr_dec(block);
|
ptr_dec(block);
|
||||||
|
|
||||||
if (output) {
|
if (output) {
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
#define alSize BN(alSize)
|
#define alSize BN(alSize)
|
||||||
#ifndef MMAP
|
#ifndef MMAP
|
||||||
usz getPageSize();
|
usz getPageSize();
|
||||||
#define MMAP(SZ) mmap(NULL, (SZ)+getPageSize(), PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANON, -1, 0)
|
#define MMAP(SZ) mmap(NULL, (SZ)+getPageSize(), PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct AllocInfo {
|
typedef struct AllocInfo {
|
||||||
|
|||||||
176
src/vm.c
176
src/vm.c
@ -996,7 +996,7 @@ static void allocStack(void** curr, void** start, void** end, i32 elSize, i32 co
|
|||||||
#if NO_MMAP
|
#if NO_MMAP
|
||||||
void* mem = calloc(sz+ps, 1);
|
void* mem = calloc(sz+ps, 1);
|
||||||
#else
|
#else
|
||||||
void* mem = mmap(NULL, sz+ps, PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANON, -1, 0);
|
void* mem = mmap(NULL, sz+ps, PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||||
if (*curr == MAP_FAILED) err("Failed to allocate stack");
|
if (*curr == MAP_FAILED) err("Failed to allocate stack");
|
||||||
#endif
|
#endif
|
||||||
*curr = *start = mem;
|
*curr = *start = mem;
|
||||||
@ -1231,6 +1231,180 @@ NOINLINE void vm_pstLive() {
|
|||||||
vm_pst(envStart, envCurr+1);
|
vm_pst(envStart, envCurr+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if __has_include(<sys/time.h>) && __has_include(<signal.h>) && !NO_MMAP
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#define PROFILE_BUFFER (1ULL<<29)
|
||||||
|
|
||||||
|
typedef struct Profiler_ent {
|
||||||
|
Comp* comp;
|
||||||
|
usz bcPos;
|
||||||
|
} Profiler_ent;
|
||||||
|
Profiler_ent* profiler_buf_s;
|
||||||
|
Profiler_ent* profiler_buf_c;
|
||||||
|
Profiler_ent* profiler_buf_e;
|
||||||
|
bool profile_buf_full;
|
||||||
|
void profiler_sigHandler(int x) {
|
||||||
|
Profiler_ent* bn = profiler_buf_c+1;
|
||||||
|
if (RARE(bn>=profiler_buf_e)) {
|
||||||
|
profile_buf_full = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (envCurr<envStart) return;
|
||||||
|
Env e = *envCurr;
|
||||||
|
Comp* comp = e.sc->body->bl->comp;
|
||||||
|
i32 bcPos = e.pos&1? ((u32)e.pos)>>1 : BCPOS(e.sc->body, (u32*)e.pos);
|
||||||
|
|
||||||
|
*profiler_buf_c = (Profiler_ent){.comp = ptr_inc(comp), .bcPos = bcPos};
|
||||||
|
profiler_buf_c = bn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static bool setHandler(bool b) {
|
||||||
|
struct sigaction act = {};
|
||||||
|
act.sa_handler = b? profiler_sigHandler : SIG_DFL;
|
||||||
|
if (sigaction(SIGALRM/*SIGPROF*/, &act, NULL)) {
|
||||||
|
printf("Failed to set profiling signal handler\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static bool setTimer(i64 us) {
|
||||||
|
struct itimerval timer;
|
||||||
|
timer.it_value.tv_sec=0;
|
||||||
|
timer.it_value.tv_usec=us;
|
||||||
|
timer.it_interval.tv_sec=0;
|
||||||
|
timer.it_interval.tv_usec=us;
|
||||||
|
if (setitimer(ITIMER_REAL/*ITIMER_PROF*/, &timer, NULL)) {
|
||||||
|
printf("Failed to start sampling timer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* profiler_makeMap();
|
||||||
|
i32 profiler_index(void* mapRaw, B comp);
|
||||||
|
void profiler_freeMap(void* mapRaw);
|
||||||
|
|
||||||
|
bool profiler_alloc() {
|
||||||
|
profiler_buf_s = profiler_buf_c = mmap(NULL, PROFILE_BUFFER, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||||
|
if (profiler_buf_s == MAP_FAILED) {
|
||||||
|
fprintf(stderr, "Failed to allocate profiler buffer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
profiler_buf_e = profiler_buf_s+PROFILE_BUFFER;
|
||||||
|
profile_buf_full = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void profiler_free() {
|
||||||
|
munmap(profiler_buf_s, PROFILE_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool profiler_active;
|
||||||
|
bool profiler_start(i64 hz) {
|
||||||
|
i64 us = 999999/hz;
|
||||||
|
profiler_active = true;
|
||||||
|
return setHandler(true) && setTimer(us);
|
||||||
|
}
|
||||||
|
bool profiler_stop() {
|
||||||
|
if (!profiler_active) return false;
|
||||||
|
profiler_active = false;
|
||||||
|
if (profile_buf_full) fprintf(stderr, "Profiler buffer ran out in the middle of execution. Only timings of the start of profiling will be shown.\n");
|
||||||
|
return setTimer(0) && setHandler(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
usz profiler_getResults(B* compListRes, B* mapListRes, bool keyPath) {
|
||||||
|
Profiler_ent* c = profiler_buf_s;
|
||||||
|
|
||||||
|
B compList = emptyHVec();
|
||||||
|
B mapList = emptyHVec();
|
||||||
|
usz compCount = 0;
|
||||||
|
void* map = profiler_makeMap();
|
||||||
|
|
||||||
|
while (c!=profiler_buf_c) {
|
||||||
|
usz bcPos = c->bcPos;
|
||||||
|
Comp* comp = c->comp;
|
||||||
|
B path = comp->path;
|
||||||
|
if (!q_N(path) && !q_N(comp->src)) {
|
||||||
|
i32 idx = profiler_index(&map, q_N(path)? tag(comp, OBJ_TAG) : path);
|
||||||
|
if (idx == compCount) {
|
||||||
|
compList = vec_addN(compList, tag(comp, OBJ_TAG));
|
||||||
|
i32* rp;
|
||||||
|
usz ia = a(comp->src)->ia;
|
||||||
|
mapList = vec_addN(mapList, m_i32arrv(&rp, ia));
|
||||||
|
for (i32 i = 0; i < ia; i++) rp[i] = 0;
|
||||||
|
compCount++;
|
||||||
|
}
|
||||||
|
B inds = IGetU(comp->indices, 0); usz cs = o2s(IGetU(inds,bcPos));
|
||||||
|
// B inde = IGetU(comp->indices, 1); usz ce = o2s(IGetU(inde,bcPos));
|
||||||
|
i32* cMap = i32arr_ptr(IGetU(mapList, idx));
|
||||||
|
// for (usz i = cs; i <= ce; i++) cMap[i]++;
|
||||||
|
cMap[cs]++;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
profiler_freeMap(map);
|
||||||
|
|
||||||
|
*compListRes = compList;
|
||||||
|
*mapListRes = mapList;
|
||||||
|
return compCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiler_displayResults() {
|
||||||
|
printf("Got "N64u" samples\n", (u64)(profiler_buf_c-profiler_buf_s));
|
||||||
|
|
||||||
|
B compList, mapList;
|
||||||
|
usz compCount = profiler_getResults(&compList, &mapList, true);
|
||||||
|
|
||||||
|
SGetU(compList) SGetU(mapList)
|
||||||
|
for (usz i = 0; i < compCount; i++) {
|
||||||
|
Comp* c = c(Comp, GetU(compList, i));
|
||||||
|
i32* m = i32arr_ptr(GetU(mapList, i));
|
||||||
|
if (!q_N(c->src)) {
|
||||||
|
if (q_N(c->path)) printf("unknown:");
|
||||||
|
else printRaw(c->path);
|
||||||
|
printf(":\n");
|
||||||
|
B src = c->src;
|
||||||
|
SGetU(src)
|
||||||
|
usz sia = a(src)->ia;
|
||||||
|
usz pi = 0;
|
||||||
|
i32 curr = 0;
|
||||||
|
for (usz i = 0; i < sia; i++) {
|
||||||
|
u32 c = o2cu(GetU(src, i));
|
||||||
|
curr+= m[i];
|
||||||
|
if (c=='\n' || i==sia-1) {
|
||||||
|
Arr* sl = TI(src,slice)(inc(src), pi, i-pi); arr_shVec(sl);
|
||||||
|
if (curr==0) printf(" │");
|
||||||
|
else printf("%6d│", curr);
|
||||||
|
printRaw(taga(sl));
|
||||||
|
printf("\n");
|
||||||
|
ptr_dec(sl);
|
||||||
|
curr = 0;
|
||||||
|
pi = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dec(compList);
|
||||||
|
dec(mapList);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool profiler_alloc() {
|
||||||
|
printf("Profiler not supported\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool profiler_start(i64 hz) { return false; }
|
||||||
|
bool profiler_stop() { return false; }
|
||||||
|
void profiler_free() { thrM("Profiler not supported"); }
|
||||||
|
usz profiler_getResults(B* compListRes, B* mapListRes, bool keyPath) { thrM("Profiler not supported"); }
|
||||||
|
void profiler_displayResults() { thrM("Profiler not supported"); }
|
||||||
|
#endif
|
||||||
|
|
||||||
void unwindEnv(Env* envNew) {
|
void unwindEnv(Env* envNew) {
|
||||||
assert(envNew<=envCurr);
|
assert(envNew<=envCurr);
|
||||||
while (envCurr!=envNew) {
|
while (envCurr!=envNew) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user