mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
fix a bug of line_profiler
This commit is contained in:
parent
0df619b66f
commit
c3b050c77a
@ -60,7 +60,8 @@ for seq in pipeline:
|
||||
text += remove_copied_include(f.read()) + '\n'
|
||||
copied.add(j)
|
||||
|
||||
with open("amalgamated/pocketpy.h", "wt", encoding='utf-8') as f:
|
||||
# use LF line endings instead of CRLF
|
||||
with open("amalgamated/pocketpy.h", "wt", encoding='utf-8', newline='\n') as f:
|
||||
final_text = \
|
||||
r'''/*
|
||||
* Copyright (c) 2023 blueloveTH
|
||||
@ -77,7 +78,7 @@ shutil.copy("src2/main.cpp", "amalgamated/main.cpp")
|
||||
with open("amalgamated/main.cpp", "rt", encoding='utf-8') as f:
|
||||
text = f.read()
|
||||
text = text.replace('#include "pocketpy/pocketpy.h"', '#include "pocketpy.h"')
|
||||
with open("amalgamated/main.cpp", "wt", encoding='utf-8') as f:
|
||||
with open("amalgamated/main.cpp", "wt", encoding='utf-8', newline='\n') as f:
|
||||
f.write(text)
|
||||
|
||||
if sys.platform in ['linux', 'darwin']:
|
||||
@ -89,7 +90,7 @@ print("amalgamated/pocketpy.h")
|
||||
|
||||
def sync(path):
|
||||
shutil.copy("amalgamated/pocketpy.h", os.path.join(path, "pocketpy.h"))
|
||||
with open(os.path.join(path, "pocketpy.cpp"), "wt", encoding='utf-8') as f:
|
||||
with open(os.path.join(path, "pocketpy.cpp"), "wt", encoding='utf-8', newline='\n') as f:
|
||||
f.write("#include \"pocketpy.h\"\n")
|
||||
|
||||
sync("plugins/macos/pocketpy")
|
||||
|
@ -127,4 +127,12 @@ struct Frame {
|
||||
}
|
||||
};
|
||||
|
||||
struct FrameId{
|
||||
std::vector<pkpy::Frame>* data;
|
||||
int index;
|
||||
FrameId(std::vector<pkpy::Frame>* data, int index) : data(data), index(index) {}
|
||||
Frame* operator->() const { return &data->operator[](index); }
|
||||
Frame* get() const { return &data->operator[](index); }
|
||||
};
|
||||
|
||||
}; // namespace pkpy
|
@ -13,19 +13,22 @@ struct LineRecord{
|
||||
bool is_valid() const { return line != -1; }
|
||||
};
|
||||
|
||||
struct LineProfiler{
|
||||
struct FrameRecord{
|
||||
FrameId frame;
|
||||
clock_t prev_time;
|
||||
LineRecord* prev_record;
|
||||
int prev_line;
|
||||
};
|
||||
|
||||
struct LineProfiler{
|
||||
// filename -> records
|
||||
std::map<std::string_view, std::vector<LineRecord>> records;
|
||||
|
||||
stack<FrameRecord> frames;
|
||||
std::set<FuncDecl*> functions;
|
||||
|
||||
void begin();
|
||||
void _step(Frame* frame);
|
||||
void _step_end();
|
||||
void _step(FrameId frame);
|
||||
void _step_end(FrameId frame);
|
||||
void end();
|
||||
Str stats();
|
||||
};
|
||||
|
@ -105,14 +105,6 @@ struct PyTypeInfo{
|
||||
|
||||
};
|
||||
|
||||
struct FrameId{
|
||||
std::vector<pkpy::Frame>* data;
|
||||
int index;
|
||||
FrameId(std::vector<pkpy::Frame>* data, int index) : data(data), index(index) {}
|
||||
Frame* operator->() const { return &data->operator[](index); }
|
||||
Frame* get() const { return &data->operator[](index); }
|
||||
};
|
||||
|
||||
typedef void(*PrintFunc)(const char*, int);
|
||||
|
||||
class VM {
|
||||
|
@ -36,5 +36,6 @@ namespace pkpy{
|
||||
'''
|
||||
return header
|
||||
|
||||
with open("include/pocketpy/_generated.h", "w", encoding='utf-8') as f:
|
||||
# use LF line endings instead of CRLF
|
||||
with open("include/pocketpy/_generated.h", "wt", encoding='utf-8', newline='\n') as f:
|
||||
f.write(generate_python_sources())
|
||||
|
@ -25,7 +25,8 @@ for line in lines:
|
||||
ret + ' ' + body + ' {\n' + mock_string + '\n}\n'
|
||||
)
|
||||
|
||||
with open('src2/pocketpy_c.c', 'w') as f:
|
||||
# use LF line endings instead of CRLF
|
||||
with open('src2/pocketpy_c.c', 'wt', encoding='utf-8', newline='\n') as f:
|
||||
f.write('''
|
||||
#include "pocketpy_c.h"
|
||||
|
||||
|
@ -68,7 +68,7 @@ PyObject* VM::_run_top_frame(){
|
||||
|
||||
#define CEVAL_STEP_CALLBACK() \
|
||||
if(_ceval_on_step) _ceval_on_step(this, frame.get(), byte); \
|
||||
if(_profiler) _profiler->_step(frame.get());
|
||||
if(_profiler) _profiler->_step(frame);
|
||||
|
||||
#define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; }
|
||||
__NEXT_FRAME:
|
||||
|
@ -15,47 +15,75 @@ static std::string to_string_1f(f64 x){
|
||||
}
|
||||
|
||||
void LineProfiler::begin(){
|
||||
prev_time = 0;
|
||||
prev_record = nullptr;
|
||||
prev_line = -1;
|
||||
records.clear();
|
||||
frames.clear();
|
||||
}
|
||||
|
||||
void LineProfiler::_step(Frame *frame){
|
||||
void LineProfiler::_step(FrameId frame){
|
||||
std::string_view filename = frame->co->src->filename.sv();
|
||||
int line = frame->co->lines[frame->_ip];
|
||||
// std::string_view function = frame->co->name.sv();
|
||||
|
||||
if(prev_record == nullptr){
|
||||
prev_time = clock();
|
||||
if(frames.empty()){
|
||||
frames.push({frame, clock(), nullptr, -1});
|
||||
}else{
|
||||
_step_end();
|
||||
_step_end(frame);
|
||||
}
|
||||
|
||||
std::vector<LineRecord>& file_records = records[filename];
|
||||
if(file_records.empty()){
|
||||
// initialize file_records
|
||||
int total_lines = frame->co->src->line_starts.size();
|
||||
file_records.resize(total_lines + 1);
|
||||
for(int i=1; i<=total_lines; i++){
|
||||
file_records[i].line = i;
|
||||
}
|
||||
}
|
||||
prev_record = &file_records.at(line);
|
||||
|
||||
frames.top().prev_record = &file_records.at(line);
|
||||
}
|
||||
|
||||
void LineProfiler::_step_end(){
|
||||
void LineProfiler::_step_end(FrameId frame){
|
||||
clock_t now = clock();
|
||||
clock_t delta = now - prev_time;
|
||||
prev_time = now;
|
||||
if(prev_record->line != prev_line){
|
||||
FrameRecord& top_frame_record = frames.top();
|
||||
LineRecord* prev_record = top_frame_record.prev_record;
|
||||
|
||||
if(prev_record->line != top_frame_record.prev_line){
|
||||
prev_record->hits++;
|
||||
prev_line = prev_record->line;
|
||||
top_frame_record.prev_line = prev_record->line;
|
||||
}
|
||||
|
||||
int id_delta = frame.index - top_frame_record.frame.index;
|
||||
PK_ASSERT(id_delta >= -1 && id_delta <= 1);
|
||||
|
||||
if(id_delta == 1){
|
||||
frames.push({frame, now, nullptr, -1});
|
||||
}else{
|
||||
clock_t delta = now - top_frame_record.prev_time;
|
||||
top_frame_record.prev_time = now;
|
||||
prev_record->time += delta;
|
||||
if(id_delta == -1){
|
||||
frames.pop();
|
||||
prev_record = frames.top().prev_record;
|
||||
prev_record->time += (now - frames.top().prev_time);
|
||||
}
|
||||
}
|
||||
prev_record->time += delta;
|
||||
}
|
||||
|
||||
void LineProfiler::end(){
|
||||
_step_end();
|
||||
clock_t now = clock();
|
||||
FrameRecord& top_frame_record = frames.top();
|
||||
LineRecord* prev_record = top_frame_record.prev_record;
|
||||
|
||||
if(prev_record->line != top_frame_record.prev_line){
|
||||
prev_record->hits++;
|
||||
top_frame_record.prev_line = prev_record->line;
|
||||
}
|
||||
|
||||
clock_t delta = now - top_frame_record.prev_time;
|
||||
top_frame_record.prev_time = now;
|
||||
prev_record->time += delta;
|
||||
|
||||
frames.pop();
|
||||
PK_ASSERT(frames.empty());
|
||||
}
|
||||
|
||||
Str LineProfiler::stats(){
|
||||
|
@ -1,15 +1,24 @@
|
||||
from line_profiler import LineProfiler
|
||||
|
||||
def my_func():
|
||||
def f2(x):
|
||||
a = 0
|
||||
for i in range(1000000):
|
||||
for i in range(x):
|
||||
a += i
|
||||
return a
|
||||
|
||||
def f1(x):
|
||||
res = f2(x)
|
||||
return res
|
||||
|
||||
lp = LineProfiler()
|
||||
|
||||
lp.add_function(my_func)
|
||||
|
||||
lp.runcall(my_func)
|
||||
lp.add_function(f2)
|
||||
|
||||
lp.runcall(f2, 1000000)
|
||||
lp.print_stats()
|
||||
###############################
|
||||
|
||||
lp.add_function(f1)
|
||||
lp.runcall(f1, 1000000)
|
||||
lp.print_stats()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user