optimize gc

This commit is contained in:
ValKmjolnir 2023-07-10 20:34:21 +08:00
parent bce8148f60
commit eab84d5c0d
4 changed files with 86 additions and 40 deletions

View File

@ -762,7 +762,7 @@ If get this, Congratulations!
This interpreter uses more strict syntax to make sure it is easier for you to program and debug. This interpreter uses more strict syntax to make sure it is easier for you to program and debug.
And flightgear's nasal interpreter also has the same rule. And flightgear's nasal interpreter also has the same rule.
So do not use varibale without using `var` to declare it. So do not use variable without using `var` to declare it.
In Andy's interpreter: In Andy's interpreter:

View File

@ -145,7 +145,7 @@ void execute(
// get running time // get running time
if (cmd&VM_TIME) { if (cmd&VM_TIME) {
f64 tm = (clk::now()-start).count()*1.0/den; f64 tm = (clk::now()-start).count()*1.0/den;
std::clog << "process exited after " << tm << "s.\n\n"; std::clog << " process exited after " << tm << "s.\n\n";
} }
} }

View File

@ -337,6 +337,23 @@ nas_map& var::map() {
return *val.gcobj->ptr.map; return *val.gcobj->ptr.map;
} }
void gc::do_mark_sweep() {
using clk = std::chrono::high_resolution_clock;
auto begin = clk::now();
mark();
auto mark_end = clk::now();
sweep();
auto sweep_end = clk::now();
auto total_time = (sweep_end-begin).count();
auto mark_time = (mark_end-begin).count();
auto sweep_time = (sweep_end-mark_end).count();
worktime += total_time;
max_time = max_time<total_time? total_time:max_time;
max_mark_time = max_mark_time<mark_time? mark_time:max_mark_time;
max_sweep_time = max_sweep_time<sweep_time? sweep_time:max_sweep_time;
}
void gc::mark() { void gc::mark() {
std::vector<var> bfs; std::vector<var> bfs;
mark_context(bfs); mark_context(bfs);
@ -389,13 +406,17 @@ void gc::mark_var(std::vector<var>& bfs_queue, var& value) {
void gc::mark_vec(std::vector<var>& bfs_queue, nas_vec& vec) { void gc::mark_vec(std::vector<var>& bfs_queue, nas_vec& vec) {
for(auto& i : vec.elems) { for(auto& i : vec.elems) {
bfs_queue.push_back(i); if (i.type>vm_num) {
bfs_queue.push_back(i);
}
} }
} }
void gc::mark_hash(std::vector<var>& bfs_queue, nas_hash& hash) { void gc::mark_hash(std::vector<var>& bfs_queue, nas_hash& hash) {
for(auto& i : hash.elems) { for(auto& i : hash.elems) {
bfs_queue.push_back(i.second); if (i.second.type>vm_num) {
bfs_queue.push_back(i.second);
}
} }
} }
@ -502,24 +523,39 @@ void gc::clear() {
env_argv.clear(); env_argv.clear();
} }
void gc::info() { void gc::info() const {
using std::left; using std::left;
using std::setw; using std::setw;
using std::setfill; using std::setfill;
const char* used_table_name[] = {
"object type", "gc count", "alloc count", "memory size",
"detail", "time spend", "gc time", "avg time", "max gc",
"max mark", "max sweep", nullptr
};
const char* name[] = { const char* name[] = {
"string ", "string",
"vector ", "vector",
"hashmap ", "hashmap",
"function ", "function",
"upvalue ", "upvalue",
"object ", "object",
"coroutine", "coroutine",
"mapper " "mapper",
nullptr
}; };
usize indent = 0; usize indent = 0, len = 0;
for(u8 i = 0; i<gc_type_size; ++i) { for(usize i = 0; used_table_name[i]; ++i) {
usize len = 0; len = std::string(used_table_name[i]).length();
indent = indent<len? len:indent;
}
for(usize i = 0; name[i]; ++i) {
len = std::string(name[i]).length();
indent = indent<len? len:indent;
}
for(u32 i = 0; i<gc_type_size; ++i) {
len = std::to_string(gcnt[i]).length(); len = std::to_string(gcnt[i]).length();
indent = indent<len? len:indent; indent = indent<len? len:indent;
len = std::to_string(acnt[i]).length(); len = std::to_string(acnt[i]).length();
@ -527,51 +563,60 @@ void gc::info() {
len = std::to_string(size[i]).length(); len = std::to_string(size[i]).length();
indent = indent<len? len:indent; indent = indent<len? len:indent;
} }
auto indent_string = std::string("--");
for(usize i = 0; i<indent; ++i) {
indent_string += "-";
}
indent_string = indent_string + "+" +
indent_string + "+" + indent_string + "+" + indent_string;
std::clog << "\n" << indent_string << "\n";
std::clog << " " << left << setw(indent) << setfill(' ') << "object type";
std::clog << " | " << left << setw(indent) << setfill(' ') << "gc count";
std::clog << " | " << left << setw(indent) << setfill(' ') << "alloc count";
std::clog << " | " << left << setw(indent) << setfill(' ') << "memory size";
std::clog << "\n" << indent_string << "\n";
double total = 0; double total = 0;
std::clog << "\ngc info (gc count|alloc count|memory size)\n";
for(u8 i = 0; i<gc_type_size; ++i) { for(u8 i = 0; i<gc_type_size; ++i) {
if (!gcnt[i] && !acnt[i] && !size[i]) { if (!gcnt[i] && !acnt[i] && !size[i]) {
continue; continue;
} }
total += gcnt[i]; total += gcnt[i];
std::clog << " " << name[i]; std::clog << " " << left << setw(indent) << setfill(' ') << name[i];
std::clog << " | " << left << setw(indent) << setfill(' ') << gcnt[i]; std::clog << " | " << left << setw(indent) << setfill(' ') << gcnt[i];
std::clog << " | " << left << setw(indent) << setfill(' ') << acnt[i]; std::clog << " | " << left << setw(indent) << setfill(' ') << acnt[i];
std::clog << " | " << left << setw(indent) << setfill(' ') << size[i]; std::clog << " | " << left << setw(indent) << setfill(' ') << size[i];
std::clog << "\n"; std::clog << "\n";
} }
std::clog << indent_string << "\n";
auto den = std::chrono::high_resolution_clock::duration::period::den; auto den = std::chrono::high_resolution_clock::duration::period::den;
std::clog << " gc time | " << worktime*1.0/den*1000 << " ms\n"; std::clog << " " << left << setw(indent) << setfill(' ') << "detail";
if (total) { std::clog << " | " << left << setw(indent) << setfill(' ') << "time spend";
std::clog << " avg time | " << worktime*1.0/den*1000/total << " ms\n"; std::clog << " | " << left << setw(indent) << setfill('x') << "x";
std::clog << " max gc | " << max_time*1.0/den*1000 << " ms\n"; std::clog << " | " << left << setw(indent) << setfill('x') << "x";
std::clog << " max mark | " << max_mark_time*1.0/den*1000 << " ms\n"; std::clog << "\n" << indent_string << "\n";
std::clog << " max sweep | " << max_sweep_time*1.0/den*1000 << " ms\n";
} std::clog << " " << left << setw(indent) << setfill(' ') << "gc time";
std::clog<<"\n"; std::clog << " | " << worktime*1.0/den*1000 << " ms\n";
std::clog << " " << left << setw(indent) << setfill(' ') << "avg time";
std::clog << " | " << worktime*1.0/den*1000/total << " ms\n";
std::clog << " " << left << setw(indent) << setfill(' ') << "max gc";
std::clog << " | " << max_time*1.0/den*1000 << " ms\n";
std::clog << " " << left << setw(indent) << setfill(' ') << "max mark";
std::clog << " | " << max_mark_time*1.0/den*1000 << " ms\n";
std::clog << " " << left << setw(indent) << setfill(' ') << "max sweep";
std::clog << " | " << max_sweep_time*1.0/den*1000 << " ms\n";
std::clog << indent_string << "\n";
} }
var gc::alloc(u8 type) { var gc::alloc(u8 type) {
using clk = std::chrono::high_resolution_clock;
const u8 index = type-vm_str; const u8 index = type-vm_str;
++acnt[index]; ++acnt[index];
if (unused[index].empty()) { if (unused[index].empty()) {
++gcnt[index]; ++gcnt[index];
auto begin = clk::now(); do_mark_sweep();
mark();
auto mark_end = clk::now();
sweep();
auto sweep_end = clk::now();
auto total_time = (sweep_end-begin).count();
auto mark_time = (mark_end-begin).count();
auto sweep_time = (sweep_end-mark_end).count();
worktime += total_time;
max_time = max_time<total_time? total_time:max_time;
max_mark_time = max_mark_time<mark_time? mark_time:max_mark_time;
max_sweep_time = max_sweep_time<sweep_time? sweep_time:max_sweep_time;
} }
if (unused[index].empty()) { if (unused[index].empty()) {
extend(type); extend(type);

View File

@ -383,6 +383,7 @@ struct gc {
private: private:
/* gc functions */ /* gc functions */
void do_mark_sweep();
void mark(); void mark();
void mark_context(std::vector<var>&); void mark_context(std::vector<var>&);
void mark_var(std::vector<var>&, var&); void mark_var(std::vector<var>&, var&);
@ -398,7 +399,7 @@ public:
void extend(u8); void extend(u8);
void init(const std::vector<std::string>&, const std::vector<std::string>&); void init(const std::vector<std::string>&, const std::vector<std::string>&);
void clear(); void clear();
void info(); void info() const;
var alloc(const u8); var alloc(const u8);
void ctxchg(nas_co&); void ctxchg(nas_co&);
void ctxreserve(); void ctxreserve();