| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- #include "pocketpy/profiler.h"
- namespace pkpy{
- static std::string left_pad(std::string s, int width){
- int n = width - s.size();
- if(n <= 0) return s;
- return std::string(n, ' ') + s;
- }
- static std::string to_string_1f(f64 x){
- char buf[32];
- snprintf(buf, 32, "%.1f", x);
- return buf;
- }
- std::string_view LineRecord::line_content() const {
- auto [_0, _1] = src->_get_line(line);
- return std::string_view(_0, _1-_0);
- }
- void LineProfiler::begin(){
- prev_time = 0;
- prev_record = nullptr;
- prev_line = -1;
- records.clear();
- }
- void LineProfiler::_step(Frame *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();
- }else{
- _step_end();
- }
- std::vector<LineRecord>& file_records = records[filename];
- if(file_records.empty()) file_records.resize(frame->co->src->line_starts.size() + 10);
- prev_record = &file_records[line];
- if(!prev_record->is_valid()){
- prev_record->line = line;
- prev_record->src = frame->co->src.get();
- }
- }
- void LineProfiler::_step_end(){
- clock_t now = clock();
- clock_t delta = now - prev_time;
- prev_time = now;
- if(prev_record->line != prev_line){
- prev_record->hits++;
- prev_line = prev_record->line;
- }
- prev_record->time += delta;
- }
- void LineProfiler::end(){
- _step_end();
- }
- Str LineProfiler::stats(){
- SStream ss;
- for(auto& [filename, file_records] : records){
- clock_t total_time = 0;
- for(auto& record: file_records){
- if(record.is_valid()) total_time += record.time;
- }
- ss << "Total time: " << (f64)total_time / CLOCKS_PER_SEC << "s\n";
- ss << "File: " << filename << "\n";
- // ss << "Function: " << "<?>" << "at line " << -1 << "\n";
- ss << "Line # Hits Time Per Hit % Time Line Contents\n";
- ss << "==============================================================\n";
- for(int line = 1; line < file_records.size(); line++){
- LineRecord& record = file_records[line];
- if(!record.is_valid()) continue;
- ss << left_pad(std::to_string(line), 6);
- ss << left_pad(std::to_string(record.hits), 10);
- ss << left_pad(std::to_string(record.time), 13);
- ss << left_pad(std::to_string(record.time / record.hits), 9);
- ss << left_pad(to_string_1f(record.time * (f64)100 / total_time), 9);
- ss << " " << record.line_content() << "\n";
- }
- ss << "\n";
- }
- return ss.str();
- }
- } // namespace pkpy
|