add concurrent mark for experiment

This commit is contained in:
ValKmjolnir 2023-07-16 00:37:11 +08:00
parent 0c183b5984
commit eee30b7d8e
10 changed files with 142 additions and 16 deletions

View File

@ -40,6 +40,7 @@ add_executable(nasal ${CMAKE_SOURCE_DIR}/src/main.cpp)
target_link_libraries(nasal nasal-object)
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
target_link_libraries(nasal dl)
target_link_libraries(nasal pthread)
endif()
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")

View File

@ -39,7 +39,7 @@ NASAL_OBJECT=\
# for test
nasal: $(NASAL_OBJECT) | build
$(CXX) $(NASAL_OBJECT) -O3 -o nasal -ldl
$(CXX) $(NASAL_OBJECT) -O3 -o nasal -ldl -lpthread
nasal.exe: $(NASAL_OBJECT) | build
$(CXX) $(NASAL_OBJECT) -O3 -o nasal.exe

View File

@ -1,4 +1,5 @@
#include "nasal_builtin.h"
#include <chrono>
var builtin_print(var* local, gc& ngc) {
for(auto& i : local[1].vec().elems) {
@ -1234,6 +1235,24 @@ var builtin_gcextend(var* local, gc& ngc) {
return nil;
}
var builtin_gcinfo(var* local, gc& ngc) {
auto den = std::chrono::high_resolution_clock::duration::period::den;
var res = ngc.alloc(vm_hash);
double total = 0;
for(u32 i = 0; i<gc_type_size; ++i) {
total += ngc.gcnt[i];
}
// using ms
auto& map = res.hash().elems;
map["total"] = var::num(ngc.worktime*1.0/den*1000);
map["average"] = var::num(ngc.worktime*1.0/den*1000/total);
map["max_gc"] = var::num(ngc.max_time*1.0/den*1000);
map["max_mark"] = var::num(ngc.max_mark_time*1.0/den*1000);
map["max_sweep"] = var::num(ngc.max_sweep_time*1.0/den*1000);
return res;
}
var builtin_logtime(var* local, gc& ngc) {
time_t t = time(nullptr);
tm* tm_t = localtime(&t);
@ -1351,6 +1370,7 @@ nasal_builtin_table builtin[] = {
{"__corun", builtin_corun},
{"__millisec", builtin_millisec},
{"__gcextd", builtin_gcextend},
{"__gcinfo", builtin_gcinfo},
{"__logtime", builtin_logtime},
{"__ghosttype", builtin_ghosttype},
{nullptr, nullptr}

View File

@ -126,6 +126,7 @@ var builtin_costatus(var*, gc&);
var builtin_corun(var*, gc&);
var builtin_millisec(var*, gc&);
var builtin_gcextend(var*, gc&);
var builtin_gcinfo(var*, gc&);
var builtin_logtime(var*, gc&);
var builtin_ghosttype(var*, gc&);

View File

@ -357,6 +357,18 @@ void gc::do_mark_sweep() {
void gc::mark() {
std::vector<var> bfs;
mark_context(bfs);
if (memory.size()>1048576 && bfs.size()>4) {
usize size = bfs.size();
std::thread t0(&gc::concurrent_mark, this, std::ref(bfs), 0, size/4);
std::thread t1(&gc::concurrent_mark, this, std::ref(bfs), size/4, size/2);
std::thread t2(&gc::concurrent_mark, this, std::ref(bfs), size/2, size/4*3);
std::thread t3(&gc::concurrent_mark, this, std::ref(bfs), size/4*3, size);
t0.join();
t1.join();
t2.join();
t3.join();
return;
}
while(!bfs.empty()) {
var value = bfs.back();
@ -369,6 +381,27 @@ void gc::mark() {
}
}
void gc::concurrent_mark(std::vector<var>& vec, usize begin, usize end) {
std::vector<var> bfs;
for(auto i = begin; i<end; ++i) {
var value = vec[i];
if (value.type<=vm_num ||
value.val.gcobj->mark!=gc_status::uncollected) {
continue;
}
mark_var(bfs, value);
}
while(!bfs.empty()) {
var value = bfs.back();
bfs.pop_back();
if (value.type<=vm_num ||
value.val.gcobj->mark!=gc_status::uncollected) {
continue;
}
mark_var(bfs, value);
}
}
void gc::mark_context(std::vector<var>& bfs_queue) {
// scan now running context, this context maybe related to coroutine or main
@ -579,6 +612,8 @@ void gc::info() const {
for(usize i = 0; i<indent; ++i) {
indent_string += "-";
}
auto last_line = indent_string + "+" +
indent_string + "-" + indent_string + "-" + indent_string;
indent_string = indent_string + "+" +
indent_string + "+" + indent_string + "+" + indent_string;
@ -620,7 +655,7 @@ void gc::info() const {
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";
std::clog << last_line << "\n";
}
var gc::alloc(u8 type) {

View File

@ -385,6 +385,7 @@ private:
/* gc functions */
void do_mark_sweep();
void mark();
void concurrent_mark(std::vector<var>&, usize, usize);
void mark_context(std::vector<var>&);
void mark_var(std::vector<var>&, var&);
void mark_vec(std::vector<var>&, nas_vec&);

View File

@ -480,7 +480,8 @@ var runtime = {
# command line arguments
argv: func() {return globals.arg;},
gc: {
extend: func(type) {return __gcextd;}
extend: func(type) {return __gcextd;},
info: func() {return __gcinfo;}
}
};

View File

@ -1,12 +1,79 @@
var test_func = func(test_processes...) {
var test_process_total = maketimestamp();
test_process_total.stamp();
var time_stamp = maketimestamp();
var info = runtime.gc.info();
var gc_total = info.total;
var duration = 0;
foreach(var f; test_processes) {
println("[", os.time(), "] testing ", id(f));
time_stamp.stamp();
f();
duration = time_stamp.elapsedMSec();
info = runtime.gc.info();
println("[", os.time(), "] ", duration, " ms, gc ",
(info.total-gc_total)*100/duration, "%, ",
int(1000/duration), " cps");
gc_total = info.total;
}
println("[", os.time(), "] test time: ",
test_process_total.elapsedMSec(), " ms");
info = runtime.gc.info();
println("##-gc----------------");
println("total : ", info.total, " ms");
println("average : ", info.average, " ms");
println("max gc : ", info.max_gc, " ms");
println("max mark : ", info.max_mark, " ms");
println("max sweep: ", info.max_sweep, " ms");
println("---------------------");
}
var append_vec = func {
var res = [];
for(var i=0; i<1e6; i+=1) {
append(res, []);
append(res, [1]);
}
res = [];
}
var append_hash = func {
var res = [];
for(var i=0; i<1e6; i+=1) {
append(res, {});
append(res, {a:1, b:2});
}
res = [];
}
var append_func = func {
var res = [];
for(var i=0; i<1e6; i+=1) {
append(res, func {});
append(res, func {
println(arg);
});
}
}
var append_vec_in_vec = func {
var res = [];
for(var i=0; i<1e6; i+=1) {
append(res, [[]]);
}
}
var append_vec_in_hash = func {
for(var i=0; i<1e6; i+=1) {
append([], {a:[], b:[]});
}
}
for(var i=0; i<10; i+=1) {
test_func(
append_vec,
append_hash,
append_func,
append_vec_in_vec,
append_vec_in_hash
);
}