mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
add PK_ENABLE_PROFILER
This commit is contained in:
parent
4665fb3405
commit
6cc4d9c5cc
@ -29,6 +29,11 @@ if(PK_ENABLE_OS)
|
||||
add_definitions(-DPK_ENABLE_OS=1)
|
||||
endif()
|
||||
|
||||
option(PK_ENABLE_PROFILER "" OFF)
|
||||
if(PK_ENABLE_PROFILER)
|
||||
add_definitions(-DPK_ENABLE_PROFILER=1)
|
||||
endif()
|
||||
|
||||
option(PK_NO_EXPORT_C_API "" OFF)
|
||||
if(PK_NO_EXPORT_C_API)
|
||||
add_definitions(-DPK_NO_EXPORT_C_API)
|
||||
|
@ -4,7 +4,7 @@ title: Debugging
|
||||
---
|
||||
|
||||
!!!
|
||||
This feature is available in `v1.4.5` or higher.
|
||||
This feature is available in `v1.4.5` or higher. Set `PK_ENABLE_PROFILER` to `1` to enable this feature.
|
||||
!!!
|
||||
|
||||
You can invoke `breakpoint()` in your python code to start a PDB-like session.
|
||||
|
@ -3,7 +3,9 @@ icon: package
|
||||
label: line_profiler
|
||||
---
|
||||
|
||||
Line-by-line profiler for Python.
|
||||
!!!
|
||||
This module is optional. Set `PK_ENABLE_PROFILER` to `1` to enable it.
|
||||
!!!
|
||||
|
||||
## Example
|
||||
|
||||
|
@ -13,6 +13,11 @@
|
||||
#define PK_ENABLE_THREAD 0
|
||||
#endif
|
||||
|
||||
// Enable `line_profiler` module and `breakpoint()` function
|
||||
#ifndef PK_ENABLE_PROFILER // can be overridden by cmake
|
||||
#define PK_ENABLE_PROFILER 0
|
||||
#endif
|
||||
|
||||
// GC min threshold
|
||||
#ifndef PK_GC_MIN_THRESHOLD // can be overridden by cmake
|
||||
#define PK_GC_MIN_THRESHOLD 32768
|
||||
|
@ -139,8 +139,10 @@ public:
|
||||
|
||||
void (*_ceval_on_step)(VM*, Frame*, Bytecode bc) = nullptr;
|
||||
|
||||
#if PK_ENABLE_PROFILER
|
||||
LineProfiler* _profiler = nullptr;
|
||||
NextBreakpoint _next_breakpoint;
|
||||
#endif
|
||||
|
||||
PrintFunc _stdout;
|
||||
PrintFunc _stderr;
|
||||
@ -174,9 +176,11 @@ public:
|
||||
s_data.reset(callstack.top()._sp_base);
|
||||
callstack.pop();
|
||||
|
||||
#if PK_ENABLE_PROFILER
|
||||
if(!_next_breakpoint.empty() && callstack.size()<_next_breakpoint.callstack_size){
|
||||
_next_breakpoint = NextBreakpoint();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PyObject* py_str(PyObject* obj);
|
||||
|
@ -1,6 +1,6 @@
|
||||
python prebuild.py
|
||||
SRC=$(find src/ -name "*.cpp")
|
||||
clang++ -std=c++17 --coverage -O1 -stdlib=libc++ -frtti -Wfatal-errors -o main src2/main.cpp $SRC -Iinclude -DPK_ENABLE_OS=1 -DPK_DEBUG_PRECOMPILED_EXEC=1
|
||||
clang++ -std=c++17 --coverage -O1 -stdlib=libc++ -frtti -Wfatal-errors -o main src2/main.cpp $SRC -Iinclude -DPK_ENABLE_OS=1 -DPK_DEBUG_PRECOMPILED_EXEC=1 -DPK_ENABLE_PROFILER=1
|
||||
|
||||
python scripts/run_tests.py
|
||||
|
||||
|
@ -72,12 +72,17 @@ PyObject* VM::_run_top_frame(){
|
||||
*/
|
||||
{
|
||||
|
||||
|
||||
#if PK_ENABLE_PROFILER
|
||||
#define CEVAL_STEP_CALLBACK() \
|
||||
if(_ceval_on_step) _ceval_on_step(this, frame, byte); \
|
||||
if(_profiler) _profiler->_step(callstack.size(), frame); \
|
||||
if(!_next_breakpoint.empty()) { _next_breakpoint._step(this); }
|
||||
#else
|
||||
#define CEVAL_STEP_CALLBACK() \
|
||||
if(_ceval_on_step) _ceval_on_step(this, frame, byte);
|
||||
#endif
|
||||
|
||||
#define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; }
|
||||
__NEXT_FRAME:
|
||||
// cache
|
||||
const CodeObject* co = frame->co;
|
||||
@ -639,7 +644,10 @@ __NEXT_STEP:;
|
||||
(byte.arg>>8) & 0xFF, // KWARGC
|
||||
true
|
||||
);
|
||||
if(_0 == PY_OP_CALL) DISPATCH_OP_CALL();
|
||||
if(_0 == PY_OP_CALL){
|
||||
frame = top_frame();
|
||||
goto __NEXT_FRAME;
|
||||
}
|
||||
PUSH(_0);
|
||||
} DISPATCH();
|
||||
TARGET(CALL_TP){
|
||||
@ -671,7 +679,10 @@ __NEXT_STEP:;
|
||||
true
|
||||
);
|
||||
}
|
||||
if(_0 == PY_OP_CALL) DISPATCH_OP_CALL();
|
||||
if(_0 == PY_OP_CALL){
|
||||
frame = top_frame();
|
||||
goto __NEXT_FRAME;
|
||||
}
|
||||
PUSH(_0);
|
||||
} DISPATCH();
|
||||
TARGET(RETURN_VALUE){
|
||||
@ -931,13 +942,7 @@ __NEXT_STEP:;
|
||||
} DISPATCH();
|
||||
/*****************************************/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#undef DISPATCH
|
||||
#undef TARGET
|
||||
#undef DISPATCH_OP_CALL
|
||||
#undef CEVAL_STEP_CALLBACK
|
||||
/**********************************************************************/
|
||||
PK_UNREACHABLE()
|
||||
}catch(HandledException){
|
||||
@ -970,6 +975,6 @@ __NEXT_STEP:;
|
||||
|
||||
#undef DISPATCH
|
||||
#undef TARGET
|
||||
#undef DISPATCH_OP_CALL
|
||||
#undef CEVAL_STEP_CALLBACK
|
||||
|
||||
} // namespace pkpy
|
||||
|
@ -250,6 +250,43 @@ void add_module_gc(VM* vm){
|
||||
vm->bind_func<0>(mod, "collect", PK_LAMBDA(VAR(vm->heap.collect())));
|
||||
}
|
||||
|
||||
void add_module_enum(VM* vm){
|
||||
PyObject* mod = vm->new_module("enum");
|
||||
CodeObject_ code = vm->compile(kPythonLibs__enum, "enum.py", EXEC_MODE);
|
||||
vm->_exec(code, mod);
|
||||
PyObject* Enum = mod->attr("Enum");
|
||||
vm->_all_types[PK_OBJ_GET(Type, Enum).index].on_end_subclass = \
|
||||
[](VM* vm, PyTypeInfo* new_ti){
|
||||
new_ti->subclass_enabled = false; // Enum class cannot be subclassed twice
|
||||
NameDict& attr = new_ti->obj->attr();
|
||||
for(auto [k, v]: attr.items()){
|
||||
// wrap every attribute
|
||||
std::string_view k_sv = k.sv();
|
||||
if(k_sv.empty() || k_sv[0] == '_') continue;
|
||||
attr.set(k, vm->call(new_ti->obj, VAR(k_sv), v));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void add_module___builtins(VM* vm){
|
||||
PyObject* mod = vm->new_module("__builtins");
|
||||
|
||||
vm->bind_func<1>(mod, "next", [](VM* vm, ArgsView args){
|
||||
return vm->py_next(args[0]);
|
||||
});
|
||||
|
||||
vm->bind_func<1>(mod, "_enable_instance_dict", [](VM* vm, ArgsView args){
|
||||
PyObject* self = args[0];
|
||||
if(is_tagged(self)) vm->TypeError("object: tagged object cannot enable instance dict");
|
||||
if(self->is_attr_valid()) vm->RuntimeError("object: instance dict is already enabled");
|
||||
self->_enable_instance_dict();
|
||||
return vm->None;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/************************************************/
|
||||
#if PK_ENABLE_PROFILER
|
||||
struct LineProfilerW;
|
||||
struct _LpGuard{
|
||||
PK_ALWAYS_PASS_BY_POINTER(_LpGuard)
|
||||
@ -317,40 +354,10 @@ void add_module_line_profiler(VM *vm){
|
||||
PyObject* mod = vm->new_module("line_profiler");
|
||||
LineProfilerW::register_class(vm, mod);
|
||||
}
|
||||
|
||||
|
||||
void add_module_enum(VM* vm){
|
||||
PyObject* mod = vm->new_module("enum");
|
||||
CodeObject_ code = vm->compile(kPythonLibs__enum, "enum.py", EXEC_MODE);
|
||||
vm->_exec(code, mod);
|
||||
PyObject* Enum = mod->attr("Enum");
|
||||
vm->_all_types[PK_OBJ_GET(Type, Enum).index].on_end_subclass = \
|
||||
[](VM* vm, PyTypeInfo* new_ti){
|
||||
new_ti->subclass_enabled = false; // Enum class cannot be subclassed twice
|
||||
NameDict& attr = new_ti->obj->attr();
|
||||
for(auto [k, v]: attr.items()){
|
||||
// wrap every attribute
|
||||
std::string_view k_sv = k.sv();
|
||||
if(k_sv.empty() || k_sv[0] == '_') continue;
|
||||
attr.set(k, vm->call(new_ti->obj, VAR(k_sv), v));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void add_module___builtins(VM* vm){
|
||||
PyObject* mod = vm->new_module("__builtins");
|
||||
|
||||
vm->bind_func<1>(mod, "next", [](VM* vm, ArgsView args){
|
||||
return vm->py_next(args[0]);
|
||||
});
|
||||
|
||||
vm->bind_func<1>(mod, "_enable_instance_dict", [](VM* vm, ArgsView args){
|
||||
PyObject* self = args[0];
|
||||
if(is_tagged(self)) vm->TypeError("object: tagged object cannot enable instance dict");
|
||||
if(self->is_attr_valid()) vm->RuntimeError("object: instance dict is already enabled");
|
||||
self->_enable_instance_dict();
|
||||
return vm->None;
|
||||
});
|
||||
#else
|
||||
void add_module_line_profiler(VM* vm){
|
||||
(void)vm;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace pkpy
|
@ -73,7 +73,9 @@ void init_builtins(VM* _vm) {
|
||||
|
||||
// builtin functions
|
||||
_vm->bind_func<0>(_vm->builtins, "breakpoint", [](VM* vm, ArgsView args) {
|
||||
#if PK_ENABLE_PROFILER
|
||||
vm->_next_breakpoint = NextBreakpoint(vm->callstack.size(), vm->top_frame()->curr_lineno(), false);
|
||||
#endif
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
|
@ -1437,6 +1437,7 @@ void NextBreakpoint::_step(VM* vm){
|
||||
}
|
||||
|
||||
void VM::_breakpoint(){
|
||||
#if PK_ENABLE_PROFILER
|
||||
_next_breakpoint = NextBreakpoint();
|
||||
|
||||
bool show_where = false;
|
||||
@ -1569,6 +1570,7 @@ void VM::_breakpoint(){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
@ -1,4 +1,8 @@
|
||||
from line_profiler import LineProfiler
|
||||
try:
|
||||
from line_profiler import LineProfiler
|
||||
print('[INFO] line_profiler is used')
|
||||
except ImportError:
|
||||
exit(0)
|
||||
|
||||
def f2(x):
|
||||
a = 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user