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'
|
text += remove_copied_include(f.read()) + '\n'
|
||||||
copied.add(j)
|
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 = \
|
final_text = \
|
||||||
r'''/*
|
r'''/*
|
||||||
* Copyright (c) 2023 blueloveTH
|
* 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:
|
with open("amalgamated/main.cpp", "rt", encoding='utf-8') as f:
|
||||||
text = f.read()
|
text = f.read()
|
||||||
text = text.replace('#include "pocketpy/pocketpy.h"', '#include "pocketpy.h"')
|
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)
|
f.write(text)
|
||||||
|
|
||||||
if sys.platform in ['linux', 'darwin']:
|
if sys.platform in ['linux', 'darwin']:
|
||||||
@ -89,7 +90,7 @@ print("amalgamated/pocketpy.h")
|
|||||||
|
|
||||||
def sync(path):
|
def sync(path):
|
||||||
shutil.copy("amalgamated/pocketpy.h", os.path.join(path, "pocketpy.h"))
|
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")
|
f.write("#include \"pocketpy.h\"\n")
|
||||||
|
|
||||||
sync("plugins/macos/pocketpy")
|
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
|
}; // namespace pkpy
|
@ -13,19 +13,22 @@ struct LineRecord{
|
|||||||
bool is_valid() const { return line != -1; }
|
bool is_valid() const { return line != -1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LineProfiler{
|
struct FrameRecord{
|
||||||
|
FrameId frame;
|
||||||
clock_t prev_time;
|
clock_t prev_time;
|
||||||
LineRecord* prev_record;
|
LineRecord* prev_record;
|
||||||
int prev_line;
|
int prev_line;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LineProfiler{
|
||||||
// filename -> records
|
// filename -> records
|
||||||
std::map<std::string_view, std::vector<LineRecord>> records;
|
std::map<std::string_view, std::vector<LineRecord>> records;
|
||||||
|
stack<FrameRecord> frames;
|
||||||
std::set<FuncDecl*> functions;
|
std::set<FuncDecl*> functions;
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void _step(Frame* frame);
|
void _step(FrameId frame);
|
||||||
void _step_end();
|
void _step_end(FrameId frame);
|
||||||
void end();
|
void end();
|
||||||
Str stats();
|
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);
|
typedef void(*PrintFunc)(const char*, int);
|
||||||
|
|
||||||
class VM {
|
class VM {
|
||||||
|
@ -36,5 +36,6 @@ namespace pkpy{
|
|||||||
'''
|
'''
|
||||||
return header
|
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())
|
f.write(generate_python_sources())
|
||||||
|
@ -25,7 +25,8 @@ for line in lines:
|
|||||||
ret + ' ' + body + ' {\n' + mock_string + '\n}\n'
|
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('''
|
f.write('''
|
||||||
#include "pocketpy_c.h"
|
#include "pocketpy_c.h"
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ PyObject* VM::_run_top_frame(){
|
|||||||
|
|
||||||
#define CEVAL_STEP_CALLBACK() \
|
#define CEVAL_STEP_CALLBACK() \
|
||||||
if(_ceval_on_step) _ceval_on_step(this, frame.get(), byte); \
|
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; }
|
#define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; }
|
||||||
__NEXT_FRAME:
|
__NEXT_FRAME:
|
||||||
|
@ -15,47 +15,75 @@ static std::string to_string_1f(f64 x){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LineProfiler::begin(){
|
void LineProfiler::begin(){
|
||||||
prev_time = 0;
|
frames.clear();
|
||||||
prev_record = nullptr;
|
|
||||||
prev_line = -1;
|
|
||||||
records.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineProfiler::_step(Frame *frame){
|
void LineProfiler::_step(FrameId frame){
|
||||||
std::string_view filename = frame->co->src->filename.sv();
|
std::string_view filename = frame->co->src->filename.sv();
|
||||||
int line = frame->co->lines[frame->_ip];
|
int line = frame->co->lines[frame->_ip];
|
||||||
// std::string_view function = frame->co->name.sv();
|
|
||||||
|
|
||||||
if(prev_record == nullptr){
|
if(frames.empty()){
|
||||||
prev_time = clock();
|
frames.push({frame, clock(), nullptr, -1});
|
||||||
}else{
|
}else{
|
||||||
_step_end();
|
_step_end(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LineRecord>& file_records = records[filename];
|
std::vector<LineRecord>& file_records = records[filename];
|
||||||
if(file_records.empty()){
|
if(file_records.empty()){
|
||||||
|
// initialize file_records
|
||||||
int total_lines = frame->co->src->line_starts.size();
|
int total_lines = frame->co->src->line_starts.size();
|
||||||
file_records.resize(total_lines + 1);
|
file_records.resize(total_lines + 1);
|
||||||
for(int i=1; i<=total_lines; i++){
|
for(int i=1; i<=total_lines; i++){
|
||||||
file_records[i].line = 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 now = clock();
|
||||||
clock_t delta = now - prev_time;
|
FrameRecord& top_frame_record = frames.top();
|
||||||
prev_time = now;
|
LineRecord* prev_record = top_frame_record.prev_record;
|
||||||
if(prev_record->line != prev_line){
|
|
||||||
|
if(prev_record->line != top_frame_record.prev_line){
|
||||||
prev_record->hits++;
|
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(){
|
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(){
|
Str LineProfiler::stats(){
|
||||||
|
@ -1,15 +1,24 @@
|
|||||||
from line_profiler import LineProfiler
|
from line_profiler import LineProfiler
|
||||||
|
|
||||||
def my_func():
|
def f2(x):
|
||||||
a = 0
|
a = 0
|
||||||
for i in range(1000000):
|
for i in range(x):
|
||||||
a += i
|
a += i
|
||||||
return a
|
return a
|
||||||
|
|
||||||
|
def f1(x):
|
||||||
|
res = f2(x)
|
||||||
|
return res
|
||||||
|
|
||||||
lp = LineProfiler()
|
lp = LineProfiler()
|
||||||
|
|
||||||
lp.add_function(my_func)
|
lp.add_function(f2)
|
||||||
|
|
||||||
lp.runcall(my_func)
|
|
||||||
|
|
||||||
|
lp.runcall(f2, 1000000)
|
||||||
lp.print_stats()
|
lp.print_stats()
|
||||||
|
###############################
|
||||||
|
|
||||||
|
lp.add_function(f1)
|
||||||
|
lp.runcall(f1, 1000000)
|
||||||
|
lp.print_stats()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user