diff --git a/include/pocketpy/interpreter/line_profiler.h b/include/pocketpy/interpreter/line_profiler.h index 1382a6ee..9e108ee6 100644 --- a/include/pocketpy/interpreter/line_profiler.h +++ b/include/pocketpy/interpreter/line_profiler.h @@ -24,5 +24,4 @@ void LineProfiler__begin(LineProfiler* self); void LineProfiler__tracefunc_line(LineProfiler* self, py_Frame* frame); void LineProfiler__end(LineProfiler* self); void LineProfiler__reset(LineProfiler* self); - -void LineProfiler__tracefunc(py_Frame* frame, enum py_TraceEvent event); \ No newline at end of file +c11_string* LineProfiler__get_report(LineProfiler* self); \ No newline at end of file diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index cb1c7858..7c8ea276 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -163,6 +163,9 @@ PK_API void py_Frame_newlocals(py_Frame* frame, py_OutRef out); /// Returns `NULL` if not available. 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. /// @param source source string. /// @param filename filename (for error messages). diff --git a/include/typings/pkpy.pyi b/include/typings/pkpy.pyi index 33683370..4714d03e 100644 --- a/include/typings/pkpy.pyi +++ b/include/typings/pkpy.pyi @@ -28,15 +28,19 @@ def currentvm() -> int: def watchdog_begin(timeout: int): - """ - Begin the watchdog with `timeout` in milliseconds. + """Begin the watchdog with `timeout` in milliseconds. + `PK_ENABLE_WATCHDOG` must be defined to `1` to use this feature. You need to call `watchdog_end()` later. If `timeout` is reached, `TimeoutError` will be raised. """ -def watchdog_end(): - """Reset the watchdog.""" +def watchdog_end() -> None: + """End the watchdog after a call to `watchdog_begin()`.""" +def profiler_begin() -> None: ... +def profiler_end() -> None: ... +def profiler_reset() -> None: ... +def profiler_report() -> dict[str, list[list]]: ... class ComputeThread: def __init__(self, vm_index: Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]): ... diff --git a/src/interpreter/line_profier.c b/src/interpreter/line_profier.c index a1ea48e9..966aec79 100644 --- a/src/interpreter/line_profier.c +++ b/src/interpreter/line_profier.c @@ -1,4 +1,6 @@ +#include "pocketpy/common/sstream.h" #include "pocketpy/interpreter/line_profiler.h" +#include "pocketpy/objects/sourcedata.h" #include void LineProfiler__ctor(LineProfiler* self) { @@ -60,3 +62,33 @@ void LineProfiler__reset(LineProfiler* self) { LineProfiler__dtor(self); LineProfiler__ctor(self); } + +c11_string* LineProfiler__get_report(LineProfiler* self) { + c11_sbuf sbuf; + c11_sbuf__ctor(&sbuf); + c11_sbuf__write_char(&sbuf, '{'); + for(int i = 0; i < self->records.length; i++) { + c11_smallmap_p2i_KV kv = c11__getitem(c11_smallmap_p2i_KV, &self->records, i); + SourceData_ src = (SourceData_)kv.key; + int line_record_length = src->line_starts.length + 1; + c11_sv src_name = c11_string__sv(src->filename); + c11_sbuf__write_quoted(&sbuf, src_name, '"'); + c11_sbuf__write_cstr(&sbuf, ": ["); + LineRecord* lines = (LineRecord*)kv.value; + for(int j = 1; j < line_record_length; j++) { + // [, ,