⚡ add concurrent mark for experiment
This commit is contained in:
parent
0c183b5984
commit
eee30b7d8e
|
@ -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")
|
||||
|
|
2
makefile
2
makefile
|
@ -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
|
||||
|
|
|
@ -145,7 +145,7 @@ void execute(
|
|||
// get running time
|
||||
if (cmd&VM_TIME) {
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -1346,11 +1365,12 @@ nasal_builtin_table builtin[] = {
|
|||
{"__md5", builtin_md5},
|
||||
{"__cocreate", builtin_cocreate},
|
||||
{"__coresume", builtin_coresume},
|
||||
{"__coyield", builtin_coyield },
|
||||
{"__coyield", builtin_coyield},
|
||||
{"__costatus", builtin_costatus},
|
||||
{"__corun", builtin_corun},
|
||||
{"__millisec", builtin_millisec},
|
||||
{"__gcextd", builtin_gcextend},
|
||||
{"__gcinfo", builtin_gcinfo},
|
||||
{"__logtime", builtin_logtime},
|
||||
{"__ghosttype", builtin_ghosttype},
|
||||
{nullptr, nullptr}
|
||||
|
|
|
@ -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&);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -923,7 +923,7 @@ inline void vm::o_ret() {
|
|||
ctx.localr = ctx.top[-2].addr();
|
||||
ctx.upvalr = ctx.top[-3];
|
||||
|
||||
ctx.top=local-1;
|
||||
ctx.top = local-1;
|
||||
ctx.funcr = ctx.top[0];
|
||||
ctx.top[0] = ret; // rewrite func with returned value
|
||||
|
||||
|
|
|
@ -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;}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,12 +1,79 @@
|
|||
var res = [];
|
||||
for(var i=0;i<1e6;i+=1) {
|
||||
append(res, []);
|
||||
|
||||
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("---------------------");
|
||||
}
|
||||
res = [];
|
||||
for(var i=0;i<1e6;i+=1) {
|
||||
append(res, {});
|
||||
|
||||
var append_vec = func {
|
||||
var res = [];
|
||||
for(var i=0; i<1e6; i+=1) {
|
||||
append(res, [1]);
|
||||
}
|
||||
}
|
||||
res = [];
|
||||
for(var i=0;i<1e6;i+=1) {
|
||||
append(res, func {});
|
||||
|
||||
var append_hash = func {
|
||||
var res = [];
|
||||
for(var i=0; i<1e6; i+=1) {
|
||||
append(res, {a:1, b:2});
|
||||
}
|
||||
}
|
||||
|
||||
var append_func = func {
|
||||
var res = [];
|
||||
for(var i=0; i<1e6; i+=1) {
|
||||
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
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue