callstack added
This commit is contained in:
parent
5afa7dd69f
commit
9ab0a2c98d
39
Readme.md
39
Readme.md
|
|
@ -7,19 +7,28 @@
|
||||||
|
|
||||||
|
|
||||||
### TODO
|
### TODO
|
||||||
- replace to_string macro in ml.cpp
|
|
||||||
- add debug support, at least call stack
|
- add debug support, at least call stack
|
||||||
- documentation
|
|
||||||
- add url of source/inspiration to clib/*.cpp
|
|
||||||
- add stdtest - to test every functionality
|
- add stdtest - to test every functionality
|
||||||
- add instrumentation (time, nr of evals, num of atoms, debug info, debug environment etc)
|
- add parenthesis coloring into linenoise
|
||||||
- multiline editing (kilo editor)
|
- multiline editing (kilo editor)
|
||||||
- execute system command should capture stderr
|
- execute system command should capture stderr
|
||||||
- add some mem stats to benchmark
|
- add some mem stats to benchmark
|
||||||
|
- create pastebin like web using ml
|
||||||
|
#### Code
|
||||||
|
- documentation
|
||||||
|
- rename constants in ml_profiler.h
|
||||||
|
- replace to_string macro in ml.cpp
|
||||||
|
- add url of source/inspiration to clib/*.cpp
|
||||||
|
- add instrumentation (time, nr of evals, num of atoms, debug info, debug environment etc)
|
||||||
|
#### Language
|
||||||
- support for (), nil, t, in lsp code replace 0 by nil in logicals
|
- support for (), nil, t, in lsp code replace 0 by nil in logicals
|
||||||
- file functions
|
- file functions
|
||||||
- name it here
|
- open file
|
||||||
|
- read line
|
||||||
|
- write line
|
||||||
|
- close file
|
||||||
- string functions
|
- string functions
|
||||||
|
- itok - integer to char, chartoint (better names) - mini printf can be useed for it (%d)
|
||||||
- compare - needed for sorting, cmp ignore case
|
- compare - needed for sorting, cmp ignore case
|
||||||
- regexp functions
|
- regexp functions
|
||||||
- date support
|
- date support
|
||||||
|
|
@ -31,7 +40,6 @@
|
||||||
- mapcar (funcall, apply)
|
- mapcar (funcall, apply)
|
||||||
- syntax highlighting do VS Code
|
- syntax highlighting do VS Code
|
||||||
- add hash datatype
|
- add hash datatype
|
||||||
- create pastebin like web using ml
|
|
||||||
|
|
||||||
#### Performance
|
#### Performance
|
||||||
- define is one of most frequent callee, when in scope with very few vars, lookup sequentially
|
- define is one of most frequent callee, when in scope with very few vars, lookup sequentially
|
||||||
|
|
@ -40,24 +48,25 @@
|
||||||
- mini_sprintf - unnecesary copying between vector and list
|
- mini_sprintf - unnecesary copying between vector and list
|
||||||
- (do, scope ..) repeatedly assign to acc
|
- (do, scope ..) repeatedly assign to acc
|
||||||
|
|
||||||
|
#### Compile
|
||||||
|
```
|
||||||
|
mkdir -p build
|
||||||
|
gcc -std=c99 -c -O2 -o linenoise.o clib/linenoise.c
|
||||||
|
c++ -c -O2 -I/usr/local/opt/openssl/include -Iclib --std=c++17 ml.cpp ml_io.cpp ml_date.cpp ml_string.cpp ml_util.cpp ml_profiler.cpp clib/json11.cpp clib/csvparser.cpp clib/sslclient.cpp clib/printf.cpp
|
||||||
|
// on linux c++ -o build/ml -O2 -L/usr/local/lib -L/usr/local/opt/openssl/lib -lm -lstdc++ -lcrypto -lssl *.o
|
||||||
|
c++ -o build/ml -O2 -L/usr/local/lib -L/usr/local/opt/openssl/lib -lm -lstdc++ -lcrypto -lssl -Wl,-stack_size -Wl,0x1000000 *.o
|
||||||
|
```
|
||||||
|
// or cmake
|
||||||
|
|
||||||
#### Install
|
#### Install
|
||||||
```
|
```
|
||||||
cp build/ml /usr/local/bin/ml
|
cp build/ml /usr/local/bin/ml
|
||||||
cp stdlib/*.lsp /usr/local/var/mlisp/
|
cp stdlib/*.lsp /usr/local/var/mlisp/
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Compile
|
|
||||||
```
|
|
||||||
gcc -std=c99 -c -O2 -o linenoise.o clib/linenoise.c
|
|
||||||
c++ -c -O2 -I/usr/local/opt/openssl/include -Iclib --std=c++17 ml.cpp ml_io.cpp ml_date.cpp ml_string.cpp ml_util.cpp ml_profiler.cpp clib/json11.cpp clib/csvparser.cpp clib/sslclient.cpp clib/printf.cpp
|
|
||||||
c++ -o ml -O2 -L/usr/local/lib -L/usr/local/opt/openssl/lib -lm -lstdc++ -lcrypto -lssl -Wl,-stack_size -Wl,0x1000000 *.o
|
|
||||||
```
|
|
||||||
or
|
|
||||||
cmake
|
|
||||||
|
|
||||||
### Example of use
|
### Example of use
|
||||||
```
|
```
|
||||||
time ./build/ml -c '(include "../example.lisp") (print (fact 1000))'
|
|
||||||
./build/ml -f debug.lisp
|
./build/ml -f debug.lisp
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,4 +46,12 @@
|
||||||
|
|
||||||
(print (and (print "xx") (= 1 0) (print "yy")))
|
(print (and (print "xx") (= 1 0) (print "yy")))
|
||||||
|
|
||||||
|
(defun aa () (do
|
||||||
|
(print "prvni")
|
||||||
|
(+ 1 xx)
|
||||||
|
(print "druhy")
|
||||||
|
))
|
||||||
|
|
||||||
|
(aa)
|
||||||
|
|
||||||
; (sleep 1.5)
|
; (sleep 1.5)
|
||||||
23
ml.cpp
23
ml.cpp
|
|
@ -51,10 +51,10 @@
|
||||||
|
|
||||||
|
|
||||||
// Convert an object to a string using a string stream conveniently
|
// Convert an object to a string using a string stream conveniently
|
||||||
#if __APPLE_
|
#if __linux
|
||||||
#define to_string(x) static_cast<std::ostringstream>((std::ostringstream() << std::dec << x )).str()
|
|
||||||
#elif __linux
|
|
||||||
#define to_string(x) static_cast<std::ostringstream&>((std::ostringstream() << std::dec << x )).str()
|
#define to_string(x) static_cast<std::ostringstream&>((std::ostringstream() << std::dec << x )).str()
|
||||||
|
#else
|
||||||
|
#define to_string(x) static_cast<std::ostringstream>((std::ostringstream() << std::dec << x )).str()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Is this character a valid lisp symbol character
|
// Is this character a valid lisp symbol character
|
||||||
|
|
@ -624,7 +624,8 @@ MlError::~MlError() {
|
||||||
|
|
||||||
std::string MlError::description() {
|
std::string MlError::description() {
|
||||||
// return "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + msg + "\"";
|
// return "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + msg + "\"";
|
||||||
return "error: the expression `" + cause->debug() + "` with message \"" + msg + "\"";
|
return MlPerfMon::instance().callstack() +
|
||||||
|
"error: the expression `" + cause->debug() + "` with message \"" + msg + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
void MlEnvironment::combine(MlEnvironment const &other) {
|
void MlEnvironment::combine(MlEnvironment const &other) {
|
||||||
|
|
@ -693,6 +694,7 @@ MlValue MlValue::apply(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
MlValue MlValue::eval(MlEnvironment &env) {
|
MlValue MlValue::eval(MlEnvironment &env) {
|
||||||
std::vector<MlValue> args;
|
std::vector<MlValue> args;
|
||||||
MlValue function;
|
MlValue function;
|
||||||
|
MlValue res;
|
||||||
MlEnvironment e;
|
MlEnvironment e;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case QUOTE:
|
case QUOTE:
|
||||||
|
|
@ -715,11 +717,10 @@ MlValue MlValue::eval(MlEnvironment &env) {
|
||||||
args[i] = args[i].eval(env);
|
args[i] = args[i].eval(env);
|
||||||
|
|
||||||
MlPerfMon::instance().add_method_call(function.type == LAMBDA ? "lambda" : function.str);
|
MlPerfMon::instance().add_method_call(function.type == LAMBDA ? "lambda" : function.str);
|
||||||
|
res = function.apply( args, env );
|
||||||
|
MlPerfMon::instance().end_method_call();
|
||||||
|
|
||||||
return function.apply(
|
return res;
|
||||||
args,
|
|
||||||
env
|
|
||||||
);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -1015,7 +1016,7 @@ namespace builtin {
|
||||||
eval_args(args, env);
|
eval_args(args, env);
|
||||||
|
|
||||||
std::exit(args.size() < 1 ? 0 : args[0].cast_to_int().as_int());
|
std::exit(args.size() < 1 ? 0 : args[0].cast_to_int().as_int());
|
||||||
return MlValue();
|
return MlValue(); // will not be called :-)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print several values and return the last one
|
// Print several values and return the last one
|
||||||
|
|
@ -1557,7 +1558,7 @@ namespace builtin {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2)
|
||||||
throw MlError(MlValue("string-split", string_split), env, args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
throw MlError(MlValue("string-split", string_split), env, args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||||
|
|
||||||
// TODO more efficient
|
// TODO do it more efficient
|
||||||
std::vector<std::string> elements = regexp_strsplit(args[0].as_string(), args[1].as_string());
|
std::vector<std::string> elements = regexp_strsplit(args[0].as_string(), args[1].as_string());
|
||||||
std::vector<MlValue> result{};
|
std::vector<MlValue> result{};
|
||||||
|
|
||||||
|
|
@ -1970,7 +1971,7 @@ int main(int argc, char *argv[]) {
|
||||||
} catch (MlError &e) {
|
} catch (MlError &e) {
|
||||||
std::cerr << e.description() << std::endl;
|
std::cerr << e.description() << std::endl;
|
||||||
} catch (std::runtime_error &e) {
|
} catch (std::runtime_error &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << MlPerfMon::instance().callstack() << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@
|
||||||
#include "ml_profiler.h"
|
#include "ml_profiler.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
// for linux gcc
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
@ -15,6 +16,8 @@ void MlPerfMon::turnOn() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MlPerfMon::add_method_call(const std::string &method) {
|
void MlPerfMon::add_method_call(const std::string &method) {
|
||||||
|
call_stack.push_back(method);
|
||||||
|
|
||||||
if (perfOn) {
|
if (perfOn) {
|
||||||
auto search = calls_counter.find(method);
|
auto search = calls_counter.find(method);
|
||||||
if (search != calls_counter.end()) {
|
if (search != calls_counter.end()) {
|
||||||
|
|
@ -25,6 +28,25 @@ void MlPerfMon::add_method_call(const std::string &method) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MlPerfMon::end_method_call() {
|
||||||
|
if (!call_stack.empty()){
|
||||||
|
call_stack.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MlPerfMon::callstack() const {
|
||||||
|
std::string cs {"call stack:\n"};
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (auto it = call_stack.rbegin(); it != call_stack.rend() && cnt < call_stack_max_methods; ++it, ++cnt)
|
||||||
|
cs.append( std::string(*it) + "\n"); // << std::endl;
|
||||||
|
|
||||||
|
if (call_stack.size() > call_stack_max_methods)
|
||||||
|
cs.append("next " + std::to_string(call_stack.size() - call_stack_max_methods) + " entries skipped..\n");
|
||||||
|
|
||||||
|
return cs.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
void MlPerfMon::print_results() {
|
void MlPerfMon::print_results() {
|
||||||
if (perfOn) {
|
if (perfOn) {
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> end_time = std::chrono::high_resolution_clock::now();
|
std::chrono::time_point<std::chrono::high_resolution_clock> end_time = std::chrono::high_resolution_clock::now();
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@
|
||||||
#include "ml.h"
|
#include "ml.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <deque>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
static const int method_name_print_len = 15;
|
static const int method_name_print_len = 15;
|
||||||
static const int print_top_methods = 15;
|
static const int print_top_methods = 15;
|
||||||
|
static const int call_stack_max_methods = 10;
|
||||||
|
|
||||||
class MlPerfMon {
|
class MlPerfMon {
|
||||||
|
|
||||||
|
|
@ -24,10 +26,13 @@ public:
|
||||||
void turnOn();
|
void turnOn();
|
||||||
|
|
||||||
void add_method_call(const std::string &method);
|
void add_method_call(const std::string &method);
|
||||||
|
void end_method_call();
|
||||||
|
std::string callstack() const;
|
||||||
void print_results();
|
void print_results();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool perfOn;
|
bool perfOn;
|
||||||
std::unordered_map<std::string, long> calls_counter;
|
std::unordered_map<std::string, long> calls_counter;
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> start_time;
|
std::chrono::time_point<std::chrono::high_resolution_clock> start_time;
|
||||||
|
std::deque<std::string> call_stack;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue