⚡ 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)
|
target_link_libraries(nasal nasal-object)
|
||||||
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||||
target_link_libraries(nasal dl)
|
target_link_libraries(nasal dl)
|
||||||
|
target_link_libraries(nasal pthread)
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||||
|
|
2
makefile
2
makefile
|
@ -39,7 +39,7 @@ NASAL_OBJECT=\
|
||||||
|
|
||||||
# for test
|
# for test
|
||||||
nasal: $(NASAL_OBJECT) | build
|
nasal: $(NASAL_OBJECT) | build
|
||||||
$(CXX) $(NASAL_OBJECT) -O3 -o nasal -ldl
|
$(CXX) $(NASAL_OBJECT) -O3 -o nasal -ldl -lpthread
|
||||||
|
|
||||||
nasal.exe: $(NASAL_OBJECT) | build
|
nasal.exe: $(NASAL_OBJECT) | build
|
||||||
$(CXX) $(NASAL_OBJECT) -O3 -o nasal.exe
|
$(CXX) $(NASAL_OBJECT) -O3 -o nasal.exe
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "nasal_builtin.h"
|
#include "nasal_builtin.h"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
var builtin_print(var* local, gc& ngc) {
|
var builtin_print(var* local, gc& ngc) {
|
||||||
for(auto& i : local[1].vec().elems) {
|
for(auto& i : local[1].vec().elems) {
|
||||||
|
@ -1234,6 +1235,24 @@ var builtin_gcextend(var* local, gc& ngc) {
|
||||||
return nil;
|
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) {
|
var builtin_logtime(var* local, gc& ngc) {
|
||||||
time_t t = time(nullptr);
|
time_t t = time(nullptr);
|
||||||
tm* tm_t = localtime(&t);
|
tm* tm_t = localtime(&t);
|
||||||
|
@ -1346,11 +1365,12 @@ nasal_builtin_table builtin[] = {
|
||||||
{"__md5", builtin_md5},
|
{"__md5", builtin_md5},
|
||||||
{"__cocreate", builtin_cocreate},
|
{"__cocreate", builtin_cocreate},
|
||||||
{"__coresume", builtin_coresume},
|
{"__coresume", builtin_coresume},
|
||||||
{"__coyield", builtin_coyield },
|
{"__coyield", builtin_coyield},
|
||||||
{"__costatus", builtin_costatus},
|
{"__costatus", builtin_costatus},
|
||||||
{"__corun", builtin_corun},
|
{"__corun", builtin_corun},
|
||||||
{"__millisec", builtin_millisec},
|
{"__millisec", builtin_millisec},
|
||||||
{"__gcextd", builtin_gcextend},
|
{"__gcextd", builtin_gcextend},
|
||||||
|
{"__gcinfo", builtin_gcinfo},
|
||||||
{"__logtime", builtin_logtime},
|
{"__logtime", builtin_logtime},
|
||||||
{"__ghosttype", builtin_ghosttype},
|
{"__ghosttype", builtin_ghosttype},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
|
|
|
@ -126,6 +126,7 @@ var builtin_costatus(var*, gc&);
|
||||||
var builtin_corun(var*, gc&);
|
var builtin_corun(var*, gc&);
|
||||||
var builtin_millisec(var*, gc&);
|
var builtin_millisec(var*, gc&);
|
||||||
var builtin_gcextend(var*, gc&);
|
var builtin_gcextend(var*, gc&);
|
||||||
|
var builtin_gcinfo(var*, gc&);
|
||||||
var builtin_logtime(var*, gc&);
|
var builtin_logtime(var*, gc&);
|
||||||
var builtin_ghosttype(var*, gc&);
|
var builtin_ghosttype(var*, gc&);
|
||||||
|
|
||||||
|
|
|
@ -357,6 +357,18 @@ void gc::do_mark_sweep() {
|
||||||
void gc::mark() {
|
void gc::mark() {
|
||||||
std::vector<var> bfs;
|
std::vector<var> bfs;
|
||||||
mark_context(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()) {
|
while(!bfs.empty()) {
|
||||||
var value = bfs.back();
|
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) {
|
void gc::mark_context(std::vector<var>& bfs_queue) {
|
||||||
|
|
||||||
// scan now running context, this context maybe related to coroutine or main
|
// 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) {
|
for(usize i = 0; i<indent; ++i) {
|
||||||
indent_string += "-";
|
indent_string += "-";
|
||||||
}
|
}
|
||||||
|
auto last_line = indent_string + "+" +
|
||||||
|
indent_string + "-" + indent_string + "-" + indent_string;
|
||||||
indent_string = 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 << " | " << max_mark_time*1.0/den*1000 << " ms\n";
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "max sweep";
|
std::clog << " " << left << setw(indent) << setfill(' ') << "max sweep";
|
||||||
std::clog << " | " << max_sweep_time*1.0/den*1000 << " ms\n";
|
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) {
|
var gc::alloc(u8 type) {
|
||||||
|
|
|
@ -385,6 +385,7 @@ private:
|
||||||
/* gc functions */
|
/* gc functions */
|
||||||
void do_mark_sweep();
|
void do_mark_sweep();
|
||||||
void mark();
|
void mark();
|
||||||
|
void concurrent_mark(std::vector<var>&, usize, usize);
|
||||||
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&);
|
||||||
void mark_vec(std::vector<var>&, nas_vec&);
|
void mark_vec(std::vector<var>&, nas_vec&);
|
||||||
|
|
|
@ -923,7 +923,7 @@ inline void vm::o_ret() {
|
||||||
ctx.localr = ctx.top[-2].addr();
|
ctx.localr = ctx.top[-2].addr();
|
||||||
ctx.upvalr = ctx.top[-3];
|
ctx.upvalr = ctx.top[-3];
|
||||||
|
|
||||||
ctx.top=local-1;
|
ctx.top = local-1;
|
||||||
ctx.funcr = ctx.top[0];
|
ctx.funcr = ctx.top[0];
|
||||||
ctx.top[0] = ret; // rewrite func with returned value
|
ctx.top[0] = ret; // rewrite func with returned value
|
||||||
|
|
||||||
|
|
|
@ -480,7 +480,8 @@ var runtime = {
|
||||||
# command line arguments
|
# command line arguments
|
||||||
argv: func() {return globals.arg;},
|
argv: func() {return globals.arg;},
|
||||||
gc: {
|
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) {
|
var test_func = func(test_processes...) {
|
||||||
append(res, []);
|
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) {
|
var append_vec = func {
|
||||||
append(res, {});
|
var res = [];
|
||||||
|
for(var i=0; i<1e6; i+=1) {
|
||||||
|
append(res, [1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res = [];
|
|
||||||
for(var i=0;i<1e6;i+=1) {
|
var append_hash = func {
|
||||||
append(res, 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