stage2 提供近乎完整的功能但出现严重性能问题 添加stage0的原生性能记录 stage1添加更多内置函数 nob重构代码使其更加健壮
This commit is contained in:
1 parent
b5a7a811b3
commit
e02b0c633a
35 files changed
+14018
-216
No files matched your search
+141
@@ -5,12 +5,15 @@
|
||||
*/
|
||||
|
||||
#include "spl_vm.h"
|
||||
#include "include/core_map.h"
|
||||
#include "spl_mcode.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void spl_vm_profile_free(spl_vm_t *vm);
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
@@ -566,6 +569,9 @@ void spl_vm_init_ex(spl_vm_t *vm, int stack_size, int call_depth) {
|
||||
vec_init(vm->fn_breakpoints);
|
||||
|
||||
vm->sp = vm->fp = vm->ip = vm->cp = vm->gp = 0;
|
||||
vm->steps = 0;
|
||||
vm->profile = NULL;
|
||||
vm->profile_interval = 0;
|
||||
vm->prog = NULL;
|
||||
vm->trace = 0;
|
||||
vm->debug = 1;
|
||||
@@ -585,6 +591,7 @@ void spl_vm_drop(spl_vm_t *vm) {
|
||||
free(vm->fn_breakpoints.data[i]);
|
||||
vec_free(vm->fn_breakpoints);
|
||||
vec_free(vm->breakpoints);
|
||||
spl_vm_profile_free(vm);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
@@ -643,6 +650,7 @@ void spl_vm_skip_breakpoint(spl_vm_t *vm) {
|
||||
|
||||
/* 前向声明(定义在文件尾部 dump 区域) */
|
||||
static const char *func_name_by_ip(spl_prog_t *prog, spl_vm_val_t ip);
|
||||
static void spl_vm_profile_free(spl_vm_t *vm);
|
||||
|
||||
/* 函数名断点命中:addr 所在函数名是否在断点表 */
|
||||
static int fn_breakpoint_hit(spl_vm_t *vm, spl_vm_val_t addr) {
|
||||
@@ -766,6 +774,136 @@ int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv,
|
||||
* Returns: 0 = still running, 1 = halted, 2 = breakpoint (SPL_DBG), -1 = error
|
||||
* ================================================================ */
|
||||
|
||||
/* ================= native 采样 profiler =================
|
||||
* 每隔 interval 条指令采样一次当前调用栈(root;...;leaf),累积计数。
|
||||
* 输出折叠格式(folded)供火焰图工具使用,以及每函数 self 采样表。 */
|
||||
|
||||
static int func_index_by_ip(spl_prog_t *prog, spl_vm_val_t ip) {
|
||||
if (!prog)
|
||||
return -1;
|
||||
isize lo = 0, hi = (isize)vec_size(prog->funcs) - 1;
|
||||
while (lo <= hi) {
|
||||
isize mid = (lo + hi) / 2;
|
||||
spl_vm_func_t *f = &vec_at(prog->funcs, (usize)mid);
|
||||
if (ip < f->address)
|
||||
hi = mid - 1;
|
||||
else if (ip >= f->address + f->ninsns)
|
||||
lo = mid + 1;
|
||||
else
|
||||
return (int)mid;
|
||||
}
|
||||
for (usize i = 0; i < vec_size(prog->funcs); i++) {
|
||||
spl_vm_func_t *f = &vec_at(prog->funcs, i);
|
||||
if (ip >= f->address && ip < f->address + f->ninsns)
|
||||
return (int)i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void spl_vm_sample(spl_vm_t *vm) {
|
||||
spl_prof_t *p = (spl_prof_t *)vm->profile;
|
||||
spl_prog_t *prog = vm->prog;
|
||||
if (!p || !prog)
|
||||
return;
|
||||
|
||||
char buf[8192];
|
||||
usize len = 0;
|
||||
for (isize i = 0; i < vm->cp; i++) {
|
||||
intptr_t s = (intptr_t)vm->frames.data[i].saved_ip;
|
||||
if (s <= 0)
|
||||
continue;
|
||||
int fi = func_index_by_ip(prog, (spl_vm_val_t)(s - 1));
|
||||
const char *n = fi >= 0 ? vec_at(prog->funcs, (usize)fi).name : "?";
|
||||
size_t l = strlen(n);
|
||||
if (len + l + 2 < sizeof(buf)) {
|
||||
if (len)
|
||||
buf[len++] = ';';
|
||||
memcpy(buf + len, n, l);
|
||||
len += l;
|
||||
}
|
||||
}
|
||||
int leaf = func_index_by_ip(prog, vm->ip > 0 ? vm->ip - 1 : 0);
|
||||
const char *ln = leaf >= 0 ? vec_at(prog->funcs, (usize)leaf).name : "?";
|
||||
size_t ll = strlen(ln);
|
||||
if (len + ll + 1 < sizeof(buf)) {
|
||||
if (len)
|
||||
buf[len++] = ';';
|
||||
memcpy(buf + len, ln, ll);
|
||||
len += ll;
|
||||
}
|
||||
buf[len] = 0;
|
||||
|
||||
usize old = 0;
|
||||
if (map_get(p->stacks, buf, &old)) {
|
||||
map_put(p->stacks, buf, old + 1);
|
||||
} else {
|
||||
map_put(p->stacks, strdup(buf), (usize)1);
|
||||
}
|
||||
if (leaf >= 0 && (usize)leaf < vec_size(p->self_samples))
|
||||
p->self_samples.data[leaf]++;
|
||||
p->samples++;
|
||||
}
|
||||
|
||||
void spl_vm_profile_enable(spl_vm_t *vm, usize interval) {
|
||||
if (!vm)
|
||||
return;
|
||||
spl_prof_t *p = (spl_prof_t *)malloc(sizeof(*p));
|
||||
if (!p)
|
||||
return;
|
||||
memset(p, 0, sizeof(*p));
|
||||
map_init(p->stacks, MAP_HASH_STR, MAP_CMP_STR);
|
||||
vec_init(p->self_samples);
|
||||
if (vm->prog) {
|
||||
usize n = vec_size(vm->prog->funcs);
|
||||
for (usize i = 0; i < n; i++)
|
||||
vec_push(p->self_samples, (usize)0);
|
||||
}
|
||||
vm->profile = p;
|
||||
vm->profile_interval = interval ? interval : 100000;
|
||||
}
|
||||
|
||||
static void spl_vm_profile_free(spl_vm_t *vm) {
|
||||
spl_prof_t *p = (spl_prof_t *)vm->profile;
|
||||
if (!p)
|
||||
return;
|
||||
map_for(p->stacks, i) { free((void *)p->stacks.data[i].key); }
|
||||
map_free(p->stacks);
|
||||
vec_free(p->self_samples);
|
||||
free(p);
|
||||
vm->profile = NULL;
|
||||
}
|
||||
|
||||
void spl_vm_profile_dump_folded(spl_vm_t *vm, const char *path) {
|
||||
spl_prof_t *p = vm ? (spl_prof_t *)vm->profile : NULL;
|
||||
if (!p || !path)
|
||||
return;
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f)
|
||||
return;
|
||||
map_for(p->stacks, i) { fprintf(f, "%s %zu\n", p->stacks.data[i].key, p->stacks.data[i].val); }
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void spl_vm_profile_dump_table(spl_vm_t *vm, const char *path) {
|
||||
spl_prof_t *p = vm ? (spl_prof_t *)vm->profile : NULL;
|
||||
if (!p || !path || !vm->prog)
|
||||
return;
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f)
|
||||
return;
|
||||
fprintf(f, "samples=%zu interval=%zu\n", p->samples, vm->profile_interval);
|
||||
fprintf(f, "func\tself_samples\tpercent\n");
|
||||
for (usize i = 0; i < vec_size(vm->prog->funcs); i++) {
|
||||
usize c = i < vec_size(p->self_samples) ? p->self_samples.data[i] : 0;
|
||||
if (c == 0)
|
||||
continue;
|
||||
spl_vm_func_t *fn = &vec_at(vm->prog->funcs, i);
|
||||
fprintf(f, "%s\t%zu\t%.2f\n", fn->name, c,
|
||||
p->samples ? (100.0 * (double)c / (double)p->samples) : 0.0);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int spl_vm_run_once(spl_vm_t *vm) {
|
||||
const spl_vm_ins_t *ins;
|
||||
spl_prog_t *prog;
|
||||
@@ -792,6 +930,9 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
|
||||
ins = &vec_at(prog->insns, vm->ip);
|
||||
vm->ip++;
|
||||
vm->steps++;
|
||||
if (vm->profile && vm->profile_interval && (vm->steps % vm->profile_interval) == 0)
|
||||
spl_vm_sample(vm);
|
||||
|
||||
if (vm->trace) {
|
||||
fprintf(stderr, "vm: ip=%zd op=%s type=%s imm=%zu sp=%zd fp=%zd\n", vm->ip - 1,
|
||||
|
||||
Reference in new issue
Block a user