mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-28 10:47:49 +01:00
better logger
This commit is contained in:
@@ -33,7 +33,7 @@ BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 0
|
||||
ColumnLimit: 140
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 8
|
||||
IndentCaseLabels: true
|
||||
|
||||
1
.idea/cmake.xml
generated
1
.idea/cmake.xml
generated
@@ -4,6 +4,7 @@
|
||||
<configurations>
|
||||
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DSANITIZE=YES" />
|
||||
<configuration PROFILE_NAME="RelWithDebInfo" ENABLED="true" CONFIG_NAME="RelWithDebInfo" />
|
||||
<configuration PROFILE_NAME="Release" ENABLED="true" CONFIG_NAME="Release" />
|
||||
</configurations>
|
||||
</component>
|
||||
</project>
|
||||
@@ -2,6 +2,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_subdirectory(vm)
|
||||
add_subdirectory(logger)
|
||||
|
||||
add_executable(psil main.cpp)
|
||||
|
||||
|
||||
6
src/logger/CMakeLists.txt
Normal file
6
src/logger/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_library(logger src/Logger.cpp)
|
||||
|
||||
target_include_directories(logger PUBLIC include)
|
||||
49
src/logger/include/Logger.h
Normal file
49
src/logger/include/Logger.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Created by stepus53 on 3.1.24.
|
||||
//
|
||||
|
||||
#ifndef PSIL_LOGGER_H
|
||||
#define PSIL_LOGGER_H
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
enum LogLevel { DISABLED = 0, ERROR = 1, INFO = 2, DEBUG = 3, TRACE = 4 };
|
||||
static void log(const std::string &tag, const std::string &what, int level);
|
||||
static void log(const std::string &tag, const std::function<void(std::ostream &)> &fn, int level);
|
||||
|
||||
// 0 - disabled
|
||||
// 1 - error
|
||||
// 2 - info
|
||||
// 3 - debug
|
||||
// 4 - trace
|
||||
static void set_level(const std::string &tag, int level);
|
||||
static void set_default_level(int level);
|
||||
|
||||
static void set_out(std::ostream &out);
|
||||
static void set_out_err(std::ostream &out_err);
|
||||
|
||||
private:
|
||||
static Logger &get();
|
||||
|
||||
std::unordered_map<std::string, int> _levels;
|
||||
static inline std::unordered_map<int, std::string> _level_names{
|
||||
{ERROR, "ERROR"},
|
||||
{INFO, "INFO"},
|
||||
{DEBUG, "DEBUG"},
|
||||
{TRACE, "TRACE"},
|
||||
};
|
||||
int _default_level = 1;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> _start_time = std::chrono::high_resolution_clock::now();
|
||||
std::reference_wrapper<std::ostream> _out = std::cout;
|
||||
std::reference_wrapper<std::ostream> _out_err = std::cerr;
|
||||
};
|
||||
|
||||
|
||||
#endif//PSIL_LOGGER_H
|
||||
46
src/logger/src/Logger.cpp
Normal file
46
src/logger/src/Logger.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Created by stepus53 on 3.1.24.
|
||||
//
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
Logger &Logger::get() {
|
||||
static Logger logger;
|
||||
return logger;
|
||||
}
|
||||
|
||||
void Logger::log(const std::string &tag, const std::string &what, int level) {
|
||||
int en_level = get()._default_level;
|
||||
if (get()._levels.find(tag) != get()._levels.end()) en_level = get()._levels.at(tag);
|
||||
|
||||
if (en_level < level) return;
|
||||
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
std::stringstream out;
|
||||
out << std::setprecision(4) << std::fixed << "["
|
||||
<< static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(now - get()._start_time).count()) / 1000.0 << "s]"
|
||||
<< "[" << tag << "][" << get()._level_names.at(level) << "] " << what << '\n';
|
||||
|
||||
if (level == 1) get()._out_err.get() << out.str();
|
||||
else
|
||||
get()._out.get() << out.str();
|
||||
}
|
||||
|
||||
void Logger::log(const std::string &tag, const std::function<void(std::ostream &)> &fn, int level) {
|
||||
int en_level = get()._default_level;
|
||||
if (get()._levels.find(tag) != get()._levels.end()) en_level = get()._levels.at(tag);
|
||||
|
||||
if (en_level < level) return;
|
||||
|
||||
std::stringstream out;
|
||||
fn(out);
|
||||
log(tag, out.str(), level);
|
||||
}
|
||||
|
||||
void Logger::set_level(const std::string &tag, int level) { get()._levels[tag] = level; }
|
||||
void Logger::set_out(std::ostream &out) { get()._out = out; }
|
||||
void Logger::set_out_err(std::ostream &out_err) { get()._out_err = out_err; }
|
||||
void Logger::set_default_level(int level) { get()._default_level = level; }
|
||||
@@ -4,4 +4,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
add_library(vm src/VM.cpp src/Cell.cpp
|
||||
src/Parser.cpp src/MemoryContext.cpp src/Handle.cpp src/Compiler.cpp)
|
||||
|
||||
target_link_libraries(vm PUBLIC logger)
|
||||
|
||||
target_include_directories(vm PUBLIC include)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "Cell.h"
|
||||
#include "Handle.h"
|
||||
#include "Logger.h"
|
||||
|
||||
class Handle;
|
||||
|
||||
@@ -39,11 +40,8 @@ public:
|
||||
void request_gc_and_wait() {
|
||||
std::unique_lock l(_gc_done_m);
|
||||
_gc_done = false;
|
||||
{
|
||||
request_gc();
|
||||
}
|
||||
if (!_gc_done)
|
||||
_gc_done_cv.wait(l, [&] { return _gc_done.load(); });
|
||||
{ request_gc(); }
|
||||
if (!_gc_done) _gc_done_cv.wait(l, [&] { return _gc_done.load(); });
|
||||
}
|
||||
|
||||
void request_gc() {
|
||||
@@ -52,21 +50,16 @@ public:
|
||||
_gc_request_cv.notify_all();
|
||||
}
|
||||
|
||||
size_t cell_count() {
|
||||
return _cells_num;
|
||||
}
|
||||
size_t cell_count() { return _cells_num; }
|
||||
|
||||
template<typename R>
|
||||
R run_dirty(const std::function<R(std::function<void(Cell *)>)> &f) {
|
||||
std::lock_guard l(_gc_dirty_notif_queue_lock);
|
||||
return f([&](Cell *c) {
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "marked dirty: " << c << " \n";
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
|
||||
_gc_dirty_notif_queue.emplace(c); });
|
||||
if (c == nullptr) return;
|
||||
Logger::log("MemoryContext", [&](std::ostream &out) { out << "marked dirty: " << c; }, Logger::DEBUG);
|
||||
_gc_dirty_notif_queue.emplace(c);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -81,7 +74,7 @@ private:
|
||||
|
||||
if ((_cells_num + tcellnum) >= (_cell_limit)) {
|
||||
// We might need to run GC twice as it has to process the messages;
|
||||
std::cerr << "Running forced GC" << std::endl;
|
||||
Logger::log("MemoryContext", "Running forced gc", Logger::ERROR);
|
||||
for (int i = 0; i < 3 && (_cells_num + tcellnum) >= (_cell_limit); i++) {
|
||||
request_gc_and_wait();
|
||||
{
|
||||
@@ -90,6 +83,8 @@ private:
|
||||
}
|
||||
}
|
||||
if ((_cells_num + tcellnum) >= (_cell_limit)) {
|
||||
Logger::log("MemoryContext", "Out of cells", Logger::ERROR);
|
||||
|
||||
throw std::runtime_error("Out of cells");
|
||||
}
|
||||
}
|
||||
@@ -100,9 +95,7 @@ private:
|
||||
std::lock_guard tmplg(_new_roots_lock);
|
||||
Handle ret(cell);
|
||||
_temp_cells.emplace_back(cell);
|
||||
if ((_cells_num + _temp_cells.size() + 1) >= (size_t) (_cell_limit / 2)) {
|
||||
request_gc();
|
||||
}
|
||||
if ((_cells_num + _temp_cells.size() + 1) >= (size_t) (_cell_limit / 2)) { request_gc(); }
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,7 @@
|
||||
#include <sstream>
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
MemoryContext::MemoryContext() {
|
||||
_gc_thread = std::thread(std::bind(&MemoryContext::gc_thread_entry, this));
|
||||
}
|
||||
MemoryContext::MemoryContext() { _gc_thread = std::thread(std::bind(&MemoryContext::gc_thread_entry, this)); }
|
||||
|
||||
MemoryContext::~MemoryContext() {
|
||||
// Three times because the first one might not start it as it's been running already
|
||||
@@ -35,22 +32,20 @@ void MemoryContext::add_root(Cell *c) {
|
||||
{
|
||||
std::lock_guard l(_new_roots_lock);
|
||||
_new_roots[c]++;
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "new root: " << c << " T: " << static_cast<int>(c->_type) << " NUM: " << _new_roots[c] << "\n";
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
Logger::log(
|
||||
"MemoryContext",
|
||||
[&](std::ostream &out) { out << "new root: " << c << " T: " << static_cast<int>(c->_type) << " NUM: " << _new_roots[c]; },
|
||||
Logger::TRACE);
|
||||
}
|
||||
}
|
||||
void MemoryContext::remove_root(Cell *c) {
|
||||
{
|
||||
std::lock_guard l(_new_roots_lock);
|
||||
_new_roots[c]--;
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "del root: " << c << " T: " << static_cast<int>(c->_type) << " NUM: " << _new_roots[c] << "\n";
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
Logger::log(
|
||||
"MemoryContext",
|
||||
[&](std::ostream &out) { out << "del root: " << c << " T: " << static_cast<int>(c->_type) << " NUM: " << _new_roots[c]; },
|
||||
Logger::TRACE);
|
||||
if (_new_roots[c] == 0) _new_roots.erase(c);
|
||||
}
|
||||
}
|
||||
@@ -63,11 +58,7 @@ void MemoryContext::gc_thread_entry() {
|
||||
}
|
||||
if (_gc_thread_stop) return;
|
||||
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "gc start " << '\n';
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
Logger::log("MemoryContext", [&](std::ostream &out) { out << "gc start "; }, Logger::DEBUG);
|
||||
auto gcstart = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::queue<Cell *> toVisit;
|
||||
@@ -80,21 +71,14 @@ void MemoryContext::gc_thread_entry() {
|
||||
if (c == nullptr) continue;
|
||||
if (c->_live) continue;
|
||||
c->_live = true;
|
||||
//
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "processing c " << c << " " << static_cast<int>(c->_type) << "\n";
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
Logger::log(
|
||||
"MemoryContext", [&](std::ostream &out) { out << "visiting c " << c << " " << static_cast<int>(c->_type); },
|
||||
Logger::TRACE);
|
||||
|
||||
if (c->_type == CellType::CONS) {
|
||||
ConsCell &cc = dynamic_cast<ConsCell &>(*c);
|
||||
// {std::stringstream out; out << "processing car " << cc._car << "\n"; std::cerr<<out.str();}
|
||||
toVisit.emplace(cc._car);
|
||||
// {std::stringstream out; out << "real car " << toVisit.back() << "\n"; std::cerr<<out.str();}
|
||||
// {std::stringstream out; out << "processing cdr " << cc._cdr << "\n"; std::cerr<<out.str();}
|
||||
toVisit.emplace(cc._cdr);
|
||||
// {std::stringstream out; out << "real cdr " << toVisit.back() << "\n"; std::cerr<<out.str();}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -114,51 +98,38 @@ void MemoryContext::gc_thread_entry() {
|
||||
|
||||
|
||||
for (auto const &r: new_roots) {
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "processing new " << r.first << " diff " << r.second << "\n";
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
Logger::log(
|
||||
"MemoryContext", [&](std::ostream &out) { out << "processing new " << r.first << " diff " << r.second; },
|
||||
Logger::TRACE);
|
||||
if (r.second == 0) continue;
|
||||
_roots[r.first] += r.second;
|
||||
if (_roots[r.first] <= 0)
|
||||
_roots.erase(r.first);
|
||||
if (_roots[r.first] <= 0) _roots.erase(r.first);
|
||||
}
|
||||
|
||||
auto stop = std::chrono::high_resolution_clock::now();
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "New roots time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
|
||||
std::cout << out.str();
|
||||
}
|
||||
|
||||
Logger::log("MemoryContext",
|
||||
"New roots processing time: " +
|
||||
std::to_string(std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count()),
|
||||
Logger::INFO);
|
||||
}
|
||||
|
||||
{
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
std::for_each(_cells.begin(), _cells.end(), [&](Cell *c) {
|
||||
c->_live = false;
|
||||
});
|
||||
std::for_each(_cells.begin(), _cells.end(), [&](Cell *c) { c->_live = false; });
|
||||
|
||||
for (const auto &r: _roots) {
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "processing r " << r.first << " diff " << r.second << "\n";
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
Logger::log(
|
||||
"MemoryContext", [&](std::ostream &out) { out << "processing r " << r.first << " diff " << r.second; },
|
||||
Logger::DEBUG);
|
||||
toVisit.emplace(r.first);
|
||||
}
|
||||
visitAll();
|
||||
auto stop = std::chrono::high_resolution_clock::now();
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "Scanned " << _roots.size() << " roots" << std::endl;
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "Roots scan time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
|
||||
std::cout << out.str();
|
||||
}
|
||||
Logger::log("MemoryContext", [&](std::ostream &out) { out << "Scanned " << _roots.size() << " roots"; }, Logger::DEBUG);
|
||||
Logger::log("MemoryContext",
|
||||
"Roots scan time: " + std::to_string(std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count()),
|
||||
Logger::INFO);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -170,11 +141,7 @@ void MemoryContext::gc_thread_entry() {
|
||||
}
|
||||
while (!dirtied.empty()) {
|
||||
for (const auto &r: dirtied) {
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "processing dirty " << r << "\n";
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
Logger::log("MemoryContext", [&](std::ostream &out) { out << "processing dirty " << r; }, Logger::DEBUG);
|
||||
toVisit.emplace(r);
|
||||
}
|
||||
visitAll();
|
||||
@@ -187,11 +154,9 @@ void MemoryContext::gc_thread_entry() {
|
||||
}
|
||||
|
||||
auto stop = std::chrono::high_resolution_clock::now();
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "Dirty mark time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
|
||||
std::cout << out.str();
|
||||
}
|
||||
Logger::log("MemoryContext",
|
||||
"Dirty scan time: " + std::to_string(std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count()),
|
||||
Logger::INFO);
|
||||
}
|
||||
{
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
@@ -201,13 +166,7 @@ void MemoryContext::gc_thread_entry() {
|
||||
_cells.remove_if([&](Cell *l) {
|
||||
if (!l->_live) {
|
||||
freed += 1;
|
||||
|
||||
// {
|
||||
// std::stringstream out;
|
||||
// out << "deleting: " << l << "\n";
|
||||
// std::cerr << out.str();
|
||||
// }
|
||||
|
||||
Logger::log("MemoryContext", [&](std::ostream &out) { out << "deleting: " << l; }, Logger::DEBUG);
|
||||
delete l;
|
||||
return true;
|
||||
}
|
||||
@@ -215,25 +174,17 @@ void MemoryContext::gc_thread_entry() {
|
||||
});
|
||||
|
||||
auto stop = std::chrono::high_resolution_clock::now();
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "Sweep time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
|
||||
std::cout << out.str();
|
||||
}
|
||||
Logger::log("MemoryContext",
|
||||
"Sweep time: " + std::to_string(std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count()),
|
||||
Logger::INFO);
|
||||
_cells_num = _cells.size();
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "GC Freed " << freed << " cells left: " << _cells_num << " \n";
|
||||
std::cout << out.str();
|
||||
}
|
||||
Logger::log("MemoryContext", "GC Freed: " + std::to_string(freed) + " cells left: " + std::to_string(_cells_num), Logger::INFO);
|
||||
}
|
||||
|
||||
auto gcstop = std::chrono::high_resolution_clock::now();
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "GC total time: " << std::chrono::duration_cast<std::chrono::microseconds>(gcstop - gcstart).count() << "\n";
|
||||
std::cout << out.str();
|
||||
}
|
||||
Logger::log("MemoryContext",
|
||||
"GC total time: " + std::to_string(std::chrono::duration_cast<std::chrono::microseconds>(gcstop - gcstart).count()),
|
||||
Logger::INFO);
|
||||
|
||||
|
||||
{
|
||||
|
||||
@@ -36,15 +36,11 @@ void VM::step() {
|
||||
|
||||
Handle curFrame = _e;
|
||||
|
||||
for (int i = 1; i < frame; i++) {
|
||||
curFrame = curFrame.cdr();
|
||||
}
|
||||
for (int i = 1; i < frame; i++) { curFrame = curFrame.cdr(); }
|
||||
|
||||
Handle curArg = curFrame.car();
|
||||
|
||||
for (int i = 1; i < arg; i++) {
|
||||
curArg = curArg.cdr();
|
||||
}
|
||||
for (int i = 1; i < arg; i++) { curArg = curArg.cdr(); }
|
||||
|
||||
_s.push(curArg.car());
|
||||
} else if (poppedH == SEL) {
|
||||
@@ -130,10 +126,14 @@ void VM::step() {
|
||||
} else if (poppedH == EVAL) {
|
||||
Handle code = _s.pop();
|
||||
Handle newc = Compiler::compile(code, nullptr);
|
||||
std::cerr << "compiled:\n";
|
||||
std::cerr << "(" << code << ")\n";
|
||||
std::cerr << "to:\n";
|
||||
std::cerr << "(" << newc << ")\n";
|
||||
Logger::log(
|
||||
"Compiler",
|
||||
[&](std::ostream &out) {
|
||||
out << "Compiled (" << code << ")\n";
|
||||
out << "to\n";
|
||||
out << "(" << newc << ")";
|
||||
},
|
||||
Logger::DEBUG);
|
||||
newc.splice(_c);
|
||||
_c = newc;
|
||||
} else if (poppedH == PRINT) {
|
||||
|
||||
Reference in New Issue
Block a user