diff --git a/src/nasal_gc.cpp b/src/nasal_gc.cpp index b565c7e..12ed05f 100644 --- a/src/nasal_gc.cpp +++ b/src/nasal_gc.cpp @@ -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& 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 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(i->type)-static_cast(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(type)-static_cast(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& constant_strings, diff --git a/src/nasal_gc.h b/src/nasal_gc.h index 76631aa..4e3691d 100644 --- a/src/nasal_gc.h +++ b/src/nasal_gc.h @@ -20,6 +20,14 @@ namespace nasal { +struct free_list { + std::vector 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 strs = {}; // reserved address for const vm_str std::vector env_argv = {}; // command line arguments std::vector memory; // gc memory - std::vector 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&, nas_co&); void mark_map(std::vector&, 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); diff --git a/test/gc_test.nas b/test/gc_test.nas index c8f526d..6f72d76 100644 --- a/test/gc_test.nas +++ b/test/gc_test.nas @@ -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", append_vec_in_vec], - ["vec", append_hash_in_vec], - ["hash", append_vec_in_hash], + ["vec ", append_vec], + ["hash ", append_hash], + ["func ", append_func], + ["vec ", append_vec_in_vec], + ["vec ", append_hash_in_vec], + ["hash ", append_vec_in_hash], ["hash", append_hash_in_hash] ); } \ No newline at end of file