mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
add profiler
This commit is contained in:
parent
4633ca7242
commit
03ee6563c8
1
.gitignore
vendored
1
.gitignore
vendored
@ -41,3 +41,4 @@ docs/C-API/functions.md
|
|||||||
|
|
||||||
cmake-build-*
|
cmake-build-*
|
||||||
tmp/
|
tmp/
|
||||||
|
profiler_report.json
|
||||||
|
@ -25,3 +25,5 @@ void LineProfiler__tracefunc_line(LineProfiler* self, py_Frame* frame);
|
|||||||
void LineProfiler__end(LineProfiler* self);
|
void LineProfiler__end(LineProfiler* self);
|
||||||
void LineProfiler__reset(LineProfiler* self);
|
void LineProfiler__reset(LineProfiler* self);
|
||||||
c11_string* LineProfiler__get_report(LineProfiler* self);
|
c11_string* LineProfiler__get_report(LineProfiler* self);
|
||||||
|
|
||||||
|
void LineProfiler_tracefunc(py_Frame* frame, enum py_TraceEvent event);
|
@ -163,9 +163,6 @@ PK_API void py_Frame_newlocals(py_Frame* frame, py_OutRef out);
|
|||||||
/// Returns `NULL` if not available.
|
/// Returns `NULL` if not available.
|
||||||
PK_API py_StackRef py_Frame_function(py_Frame* frame);
|
PK_API py_StackRef py_Frame_function(py_Frame* frame);
|
||||||
|
|
||||||
/// Trace function for the line profiler.
|
|
||||||
PK_API void py_LineProfiler_tracefunc(py_Frame* frame, enum py_TraceEvent event);
|
|
||||||
|
|
||||||
/// Run a source string.
|
/// Run a source string.
|
||||||
/// @param source source string.
|
/// @param source source string.
|
||||||
/// @param filename filename (for error messages).
|
/// @param filename filename (for error messages).
|
||||||
@ -704,6 +701,14 @@ PK_API bool py_json_loads(const char* source) PY_RAISE PY_RETURN;
|
|||||||
PK_API bool py_pickle_dumps(py_Ref val) PY_RAISE PY_RETURN;
|
PK_API bool py_pickle_dumps(py_Ref val) PY_RAISE PY_RETURN;
|
||||||
/// Python equivalent to `pickle.loads(val)`.
|
/// Python equivalent to `pickle.loads(val)`.
|
||||||
PK_API bool py_pickle_loads(const unsigned char* data, int size) PY_RAISE PY_RETURN;
|
PK_API bool py_pickle_loads(const unsigned char* data, int size) PY_RAISE PY_RETURN;
|
||||||
|
|
||||||
|
/************* Profiler *************/
|
||||||
|
|
||||||
|
PK_API void py_profiler_begin();
|
||||||
|
PK_API void py_profiler_end();
|
||||||
|
PK_API void py_profiler_reset();
|
||||||
|
PK_API char* py_profiler_report();
|
||||||
|
|
||||||
/************* Unchecked Functions *************/
|
/************* Unchecked Functions *************/
|
||||||
|
|
||||||
PK_API py_ObjectRef py_tuple_data(py_Ref self);
|
PK_API py_ObjectRef py_tuple_data(py_Ref self);
|
||||||
|
@ -66,6 +66,12 @@ void LineProfiler__reset(LineProfiler* self) {
|
|||||||
c11_string* LineProfiler__get_report(LineProfiler* self) {
|
c11_string* LineProfiler__get_report(LineProfiler* self) {
|
||||||
c11_sbuf sbuf;
|
c11_sbuf sbuf;
|
||||||
c11_sbuf__ctor(&sbuf);
|
c11_sbuf__ctor(&sbuf);
|
||||||
|
c11_sbuf__write_char(&sbuf, '{');
|
||||||
|
c11_sbuf__write_cstr(&sbuf, "\"version\": 1, ");
|
||||||
|
c11_sbuf__write_cstr(&sbuf, "\"CLOCKS_PER_SEC\": ");
|
||||||
|
c11_sbuf__write_i64(&sbuf, CLOCKS_PER_SEC);
|
||||||
|
c11_sbuf__write_cstr(&sbuf, ", \"records\": ");
|
||||||
|
|
||||||
c11_sbuf__write_char(&sbuf, '{');
|
c11_sbuf__write_char(&sbuf, '{');
|
||||||
for(int i = 0; i < self->records.length; i++) {
|
for(int i = 0; i < self->records.length; i++) {
|
||||||
c11_smallmap_p2i_KV kv = c11__getitem(c11_smallmap_p2i_KV, &self->records, i);
|
c11_smallmap_p2i_KV kv = c11__getitem(c11_smallmap_p2i_KV, &self->records, i);
|
||||||
@ -90,5 +96,6 @@ c11_string* LineProfiler__get_report(LineProfiler* self) {
|
|||||||
if(i < self->records.length - 1) c11_sbuf__write_cstr(&sbuf, ", ");
|
if(i < self->records.length - 1) c11_sbuf__write_cstr(&sbuf, ", ");
|
||||||
}
|
}
|
||||||
c11_sbuf__write_char(&sbuf, '}');
|
c11_sbuf__write_char(&sbuf, '}');
|
||||||
|
c11_sbuf__write_char(&sbuf, '}');
|
||||||
return c11_sbuf__submit(&sbuf);
|
return c11_sbuf__submit(&sbuf);
|
||||||
}
|
}
|
@ -34,9 +34,36 @@ static void pk_default_flush() { fflush(stdout); }
|
|||||||
|
|
||||||
static int pk_default_getchr() { return getchar(); }
|
static int pk_default_getchr() { return getchar(); }
|
||||||
|
|
||||||
void py_LineProfiler_tracefunc(py_Frame* frame, enum py_TraceEvent event) {
|
void py_profiler_begin() {
|
||||||
LineProfiler* self = &pk_current_vm->line_profiler;
|
LineProfiler* lp = &pk_current_vm->line_profiler;
|
||||||
if(self->enabled && event == TRACE_EVENT_LINE) LineProfiler__tracefunc_line(self, frame);
|
TraceInfo* trace_info = &pk_current_vm->trace_info;
|
||||||
|
if(trace_info->func == NULL) py_sys_settrace(LineProfiler_tracefunc, true);
|
||||||
|
c11__rtassert(trace_info->func == LineProfiler_tracefunc);
|
||||||
|
LineProfiler__begin(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void py_profiler_end() {
|
||||||
|
LineProfiler* lp = &pk_current_vm->line_profiler;
|
||||||
|
LineProfiler__end(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void py_profiler_reset() {
|
||||||
|
LineProfiler* lp = &pk_current_vm->line_profiler;
|
||||||
|
LineProfiler__reset(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* py_profiler_report() {
|
||||||
|
LineProfiler* lp = &pk_current_vm->line_profiler;
|
||||||
|
if(lp->enabled) LineProfiler__end(lp);
|
||||||
|
c11_string* s = LineProfiler__get_report(lp);
|
||||||
|
char* s_dup = c11_strdup(s->data);
|
||||||
|
c11_string__delete(s);
|
||||||
|
return s_dup;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineProfiler_tracefunc(py_Frame* frame, enum py_TraceEvent event) {
|
||||||
|
LineProfiler* lp = &pk_current_vm->line_profiler;
|
||||||
|
if(lp->enabled && event == TRACE_EVENT_LINE) LineProfiler__tracefunc_line(lp, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int BinTree__cmp_cstr(void* lhs, void* rhs) {
|
static int BinTree__cmp_cstr(void* lhs, void* rhs) {
|
||||||
|
@ -469,8 +469,10 @@ static void pkpy_configmacros_add(py_Ref dict, const char* key, int val) {
|
|||||||
|
|
||||||
static bool pkpy_profiler_begin(int argc, py_Ref argv) {
|
static bool pkpy_profiler_begin(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(0);
|
PY_CHECK_ARGC(0);
|
||||||
if(pk_current_vm->trace_info.func != py_LineProfiler_tracefunc) {
|
TraceInfo* trace_info = &pk_current_vm->trace_info;
|
||||||
return RuntimeError("py_LineProfiler_tracefunc() should be set as the trace function");
|
if(trace_info->func == NULL) py_sys_settrace(LineProfiler_tracefunc, true);
|
||||||
|
if(trace_info->func != LineProfiler_tracefunc) {
|
||||||
|
return RuntimeError("LineProfiler_tracefunc() should be set as the trace function");
|
||||||
}
|
}
|
||||||
LineProfiler__begin(&pk_current_vm->line_profiler);
|
LineProfiler__begin(&pk_current_vm->line_profiler);
|
||||||
py_newnone(py_retval());
|
py_newnone(py_retval());
|
||||||
|
17
src2/main.c
17
src2/main.c
@ -78,10 +78,23 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(profile) py_sys_settrace(py_LineProfiler_tracefunc, true);
|
if(profile) py_profiler_begin();
|
||||||
char* source = read_file(filename);
|
char* source = read_file(filename);
|
||||||
if(source) {
|
if(source) {
|
||||||
if(!py_exec(source, filename, EXEC_MODE, NULL)) py_printexc();
|
if(!py_exec(source, filename, EXEC_MODE, NULL))
|
||||||
|
py_printexc();
|
||||||
|
else {
|
||||||
|
if(profile) {
|
||||||
|
char* json_report = py_profiler_report();
|
||||||
|
FILE* report_file = fopen("profiler_report.json", "w");
|
||||||
|
if(report_file) {
|
||||||
|
fprintf(report_file, "%s", json_report);
|
||||||
|
fclose(report_file);
|
||||||
|
}
|
||||||
|
PK_FREE(json_report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PK_FREE(source);
|
PK_FREE(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user