better logger

This commit is contained in:
2024-01-03 15:33:40 +01:00
parent 8d68d7d795
commit 35a0a74a00
10 changed files with 170 additions and 121 deletions

View File

@@ -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
View File

@@ -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>

View File

@@ -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)

View 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)

View 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
View 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; }

View File

@@ -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)

View File

@@ -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;
}
}

View File

@@ -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);
{

View File

@@ -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) {