diff --git a/Readme.md b/Readme.md index 344b91f..7a338be 100644 --- a/Readme.md +++ b/Readme.md @@ -69,18 +69,15 @@ utils/local_install.sh - multiline editing (see kilocpp editor) - execute system command should capture stderr - add some mem stats to benchmark -- add tests for usql #### Code - add documentation - add more unit test, mainly for usql - rename constants in ml_profiler.h -- replace to_string macro in ml.cpp - add instrumentation (time, nr of evals, num of atoms, debug info, debug environment etc) #### Language - support for "#t" or "t" symbol as a true and "#f" for false -- support for exceptions - string functions - compare - needed for sorting, cmp ignore case - regexp match, regexp tokens @@ -91,8 +88,6 @@ utils/local_install.sh - get-env, set-env; set-env cannot be implemented in stdlib.lsp, because popen is in fact subshell #### Performance -- define is one of most frequent callee, when in scope with very few vars, lookup sequentially -- first, second are often called -> implement in c++ - push_back - repeatedly without reserving size - range - with for(int i...) and reserving result size can be 3times faster on (range 1 10000) - mini_sprintf - unnecesary copying between vector and list diff --git a/ml.cpp b/ml.cpp index 696fa3e..b245321 100644 --- a/ml.cpp +++ b/ml.cpp @@ -2162,6 +2162,9 @@ int main(int argc, char *argv[]) { // performance monitor on if (cmdOptionExists(argv, argv + argc, "-p")) MlPerfMon::instance().turnOn(); + // better stacktrace + if (cmdOptionExists(argv, argv + argc, "-d")) + MlPerfMon::instance().debugOn(); // skip loading std lib if (!cmdOptionExists(argv, argv + argc, "-b")) { load_std_lib(env); @@ -2169,7 +2172,7 @@ int main(int argc, char *argv[]) { // help if (cmdOptionExists(argv, argv + argc, "-h")) { std::cout - << "Usage:\n\t-h print this help\n\t-b skip stdlib loading\n\t-c code - runs code passed on command line\n\t-f source_file - executes code in file\n\t-i runs repl\n\t-run used for shebang\n\t-p prints profile info at the end\n\t-v prints version string\n\n"; + << "Usage:\n\t-h print this help\n\t-b skip stdlib loading\n\t-c code - runs code passed on command line\n\t-f source_file - executes code in file\n\t-i runs repl\n\t-run used for shebang\n\t-p prints profile info at the end\n\t-d better stacktrace when exception\n\t-v prints version string\n\n"; return 0; } // version diff --git a/ml.h b/ml.h index 4983ed3..e169ddf 100644 --- a/ml.h +++ b/ml.h @@ -58,7 +58,6 @@ public: friend std::ostream &operator<<(std::ostream &os, MlEnvironment const &v); private: - // The definitions in the scope. std::map defs; MlEnvironment *parent_scope; @@ -97,40 +96,21 @@ typedef MlValue (*Builtin)(std::vector, MlEnvironment &); class MlPerfMon; class MlValue { + public: - - // Constructs a nil value - MlValue(); - - // Constructs an integer + MlValue(); // Constructs a nil value MlValue(long i); - - // Constructs a floating point value MlValue(double f); - - // Constructs a bool value MlValue(bool b); + MlValue(const std::vector &list); // Constructs a list - // Constructs a list - MlValue(const std::vector &list); - - // Construct a quoted value - static MlValue quote(const MlValue "ed); - - // Construct an atom + static MlValue quote(const MlValue "ed); // Construct a quoted value static MlValue atom(const std::string &s); - - // Construct a string static MlValue string(const std::string &s); - - // Construct a nil static MlValue nil(); - // Construct a lambda function - MlValue(const std::vector ¶ms, MlValue ret, MlEnvironment const &env); - - // Construct a builtin function - MlValue(const std::string &name, Builtin b); + MlValue(const std::vector ¶ms, MlValue ret, MlEnvironment const &env); // Construct a lambda function + MlValue(const std::string &name, Builtin b); // Construct a builtin function std::vector get_used_atoms(); diff --git a/ml_profiler.cpp b/ml_profiler.cpp index fe14572..6c1cb8b 100644 --- a/ml_profiler.cpp +++ b/ml_profiler.cpp @@ -16,21 +16,32 @@ void MlPerfMon::turnOn() { start_time = std::chrono::high_resolution_clock::now(); } +void MlPerfMon::debugOn() { + debugStacktraceOn = true; +} + void MlPerfMon::add_method_call(const MlValue &function, const std::vector &args) { // only main thread is logged, to prevent mixing from others threads so lock not needed if (main_thread_id != std::this_thread::get_id()) return; std::string method = function.type == MlValue::LAMBDA ? "lambda" : function.str; - std::string args_string; - for (size_t i = 0; i < args.size() && args_string.size() < 64; i++) { - args_string.append(" "); - args_string.append(args[i].display()); - } - if (args_string.size() > 64) - args_string = args_string.substr(0, 62) + ".."; // TODO introduce constant here + if (debugStacktraceOn) { + // call stack with more info + std::string args_string; + for (size_t i = 0; i < args.size() && args_string.size() < call_stack_args_str_len; i++) { + args_string.append(" "); + args_string.append(args[i].display()); + } + if (args_string.size() > call_stack_args_str_len) + args_string = args_string.substr(0, call_stack_args_str_len) + ".."; + else + args_string.append(")"); - call_stack.push_back("(" + method + args_string + ")"); + call_stack.push_back("(" + method + args_string); + } else { + call_stack.push_back(method); + } if (perfOn) calls_counter[method]++; @@ -57,7 +68,7 @@ std::string MlPerfMon::callstack() const { return cs.append("\n"); } -size_t MlPerfMon::get_callstack_position() { +size_t MlPerfMon::get_callstack_position() const { return call_stack.size(); } @@ -71,7 +82,7 @@ void MlPerfMon::clear_callstack() { call_stack.empty(); } -void MlPerfMon::print_results() { +void MlPerfMon::print_results() const { if (perfOn) { time_point end_time = high_resolution_clock::now(); diff --git a/ml_profiler.h b/ml_profiler.h index 734d775..78aa5ed 100644 --- a/ml_profiler.h +++ b/ml_profiler.h @@ -12,37 +12,40 @@ static const int method_name_print_len = 15; static const int print_top_methods = 15; static const int call_stack_max_methods = 10; +static const int call_stack_args_str_len = 64; class MlPerfMon { private: - MlPerfMon() : perfOn(false) { + MlPerfMon() : perfOn(false), debugStacktraceOn(false) { main_thread_id = std::this_thread::get_id(); }; public: // https://stackoverflow.com/questions/43523509/simple-singleton-example-in-c - static MlPerfMon& instance(){ + static MlPerfMon& instance() { static MlPerfMon instance; return instance; } void turnOn(); + void debugOn(); void add_method_call(const MlValue &function, const std::vector &args); void end_method_call(); std::string callstack() const; - size_t get_callstack_position(); + size_t get_callstack_position() const; void restore_callstack_position(size_t to_position); void clear_callstack(); - void print_results(); + void print_results() const; private: bool perfOn; + bool debugStacktraceOn; std::unordered_map calls_counter; std::chrono::time_point start_time; std::deque call_stack; diff --git a/stdlib/stdlib.lsp b/stdlib/stdlib.lsp index 0a6bfda..7e06709 100644 --- a/stdlib/stdlib.lsp +++ b/stdlib/stdlib.lsp @@ -50,7 +50,6 @@ (second (system-cmd (+ "echo ${" var "} | tr -d \"\n\"")))) -(defun second (l) (index l 1)) (defun third (l) (index l 2)) (defun fourth (l) (index l 3)) (defun fifth (l) (index l 4))