⚡ add concurrent sweep
This commit is contained in:
parent
eeb126ab65
commit
705df8dc1d
|
@ -25,7 +25,7 @@ void gc::mark() {
|
|||
mark_context_root(bfs);
|
||||
|
||||
// concurrent mark, experimental
|
||||
if (memory.size()>UINT16_MAX && bfs.size()>32) {
|
||||
if (memory.size() > gc::concurrent_threshold() && bfs.size() > 16) {
|
||||
flag_concurrent_mark_triggered = true;
|
||||
usize size = bfs.size();
|
||||
std::thread t0(&gc::concurrent_mark, this, std::ref(bfs), 0, size/4);
|
||||
|
@ -179,6 +179,29 @@ void gc::mark_map(std::vector<var>& bfs_queue, nas_map& mp) {
|
|||
}
|
||||
|
||||
void gc::sweep() {
|
||||
if (memory.size() > gc::concurrent_threshold()) {
|
||||
flag_concurrent_mark_triggered = true;
|
||||
usize size = memory.size();
|
||||
std::vector<free_list> collect = {{}, {}, {}, {}};
|
||||
std::thread t0(&gc::concurrent_sweep, this, std::ref(collect[0]), 0, size/4);
|
||||
std::thread t1(&gc::concurrent_sweep, this, std::ref(collect[1]), size/4, size/2);
|
||||
std::thread t2(&gc::concurrent_sweep, this, std::ref(collect[2]), size/2, size/4*3);
|
||||
std::thread t3(&gc::concurrent_sweep, this, std::ref(collect[3]), size/4*3, size);
|
||||
t0.join();
|
||||
t1.join();
|
||||
t2.join();
|
||||
t3.join();
|
||||
|
||||
for (auto& i : collect) {
|
||||
for (int j = 0; j < gc_type_size; ++j) {
|
||||
for (auto ptr : i[j]) {
|
||||
unused[j].push_back(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto i : memory) {
|
||||
if (i->mark==nas_val::gc_status::uncollected) {
|
||||
i->clear();
|
||||
|
@ -190,6 +213,19 @@ void gc::sweep() {
|
|||
}
|
||||
}
|
||||
|
||||
void gc::concurrent_sweep(free_list& collect, usize begin, usize end) {
|
||||
for (usize iter = begin; iter < end; ++ iter) {
|
||||
auto i = memory[iter];
|
||||
if (i->mark==nas_val::gc_status::uncollected) {
|
||||
i->clear();
|
||||
collect[static_cast<u8>(i->type)-static_cast<u8>(vm_type::vm_str)].push_back(i);
|
||||
i->mark = nas_val::gc_status::collected;
|
||||
} else if (i->mark==nas_val::gc_status::found) {
|
||||
i->mark = nas_val::gc_status::uncollected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gc::extend(const vm_type type) {
|
||||
const u8 index = static_cast<u8>(type)-static_cast<u8>(vm_type::vm_str);
|
||||
size[index] += incr[index];
|
||||
|
@ -223,7 +259,7 @@ void gc::extend(const vm_type type) {
|
|||
}
|
||||
|
||||
// if incr[index] = 1, this will always be 1
|
||||
incr[index] = incr[index] + incr[index]/2;
|
||||
incr[index] = incr[index] + incr[index];
|
||||
}
|
||||
|
||||
void gc::init(const std::vector<std::string>& constant_strings,
|
||||
|
|
|
@ -20,6 +20,14 @@
|
|||
|
||||
namespace nasal {
|
||||
|
||||
struct free_list {
|
||||
std::vector<nas_val*> elem[gc_type_size];
|
||||
|
||||
auto& operator[](i64 index) {
|
||||
return elem[index];
|
||||
}
|
||||
};
|
||||
|
||||
struct gc {
|
||||
/* main context temporary storage */
|
||||
context main_context;
|
||||
|
@ -39,18 +47,18 @@ struct gc {
|
|||
std::vector<var> strs = {}; // reserved address for const vm_str
|
||||
std::vector<var> env_argv = {}; // command line arguments
|
||||
std::vector<nas_val*> memory; // gc memory
|
||||
std::vector<nas_val*> unused[gc_type_size]; // gc free list
|
||||
free_list unused; // gc free list
|
||||
|
||||
/* heap increase size */
|
||||
u64 incr[gc_type_size] = {
|
||||
128, // vm_str
|
||||
128, // vm_vec
|
||||
64, // vm_hash
|
||||
256, // vm_str
|
||||
512, // vm_vec
|
||||
512, // vm_hash
|
||||
256, // vm_func
|
||||
256, // vm_upval
|
||||
16, // vm_obj
|
||||
16, // vm_co
|
||||
2, // vm_map
|
||||
4, // vm_obj
|
||||
4, // vm_co
|
||||
1, // vm_map
|
||||
};
|
||||
// total memory usage, not very accurate
|
||||
u64 total_memory_usage = 0;
|
||||
|
@ -86,6 +94,11 @@ private:
|
|||
void mark_co(std::vector<var>&, nas_co&);
|
||||
void mark_map(std::vector<var>&, nas_map&);
|
||||
void sweep();
|
||||
void concurrent_sweep(free_list&, usize, usize);
|
||||
|
||||
static const auto concurrent_threshold() {
|
||||
return UINT16_MAX * 16;
|
||||
}
|
||||
|
||||
public:
|
||||
void extend(const vm_type);
|
||||
|
|
|
@ -17,9 +17,9 @@ var test_func = func(test_processes...) {
|
|||
f();
|
||||
duration = time_stamp.elapsedMSec();
|
||||
info = runtime.gc.info();
|
||||
println(duration, " ms, gc ",
|
||||
(info.total-gc_total)*100/duration, "%, ",
|
||||
1000/duration, " count/sec"
|
||||
println(duration, " ms,\tgc ",
|
||||
(info.total-gc_total)*100/duration, "%,\t",
|
||||
1000/duration, " loop/sec"
|
||||
);
|
||||
gc_total = info.total;
|
||||
}
|
||||
|
@ -28,13 +28,13 @@ var test_func = func(test_processes...) {
|
|||
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("---------------------");
|
||||
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 MAX_ITER_NUM = 2e5;
|
||||
|
@ -92,12 +92,12 @@ var append_hash_in_hash = func {
|
|||
|
||||
for (var i = 0; i < 10; i += 1) {
|
||||
test_func(
|
||||
["vec", append_vec],
|
||||
["hash", append_hash],
|
||||
["func", append_func],
|
||||
["vec<vec>", append_vec_in_vec],
|
||||
["vec<hash>", append_hash_in_vec],
|
||||
["hash<str, vec>", append_vec_in_hash],
|
||||
["vec ", append_vec],
|
||||
["hash ", append_hash],
|
||||
["func ", append_func],
|
||||
["vec<vec> ", append_vec_in_vec],
|
||||
["vec<hash> ", append_hash_in_vec],
|
||||
["hash<str, vec> ", append_vec_in_hash],
|
||||
["hash<str, hash>", append_hash_in_hash]
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue