From eee30b7d8e3287133390c350c17db83c220e0d57 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sun, 16 Jul 2023 00:37:11 +0800 Subject: [PATCH] :zap: add concurrent mark for experiment --- CMakeLists.txt | 1 + makefile | 4 +- src/main.cpp | 2 +- src/nasal_builtin.cpp | 22 ++++++++++- src/nasal_builtin.h | 1 + src/nasal_gc.cpp | 37 ++++++++++++++++++- src/nasal_gc.h | 1 + src/nasal_vm.h | 2 +- std/lib.nas | 3 +- test/gc_test.nas | 85 ++++++++++++++++++++++++++++++++++++++----- 10 files changed, 142 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 38a182f..acdace3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/makefile b/makefile index 1b571d5..80b0210 100644 --- a/makefile +++ b/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 @@ -57,7 +57,7 @@ build/nasal_err.o: src/nasal.h src/nasal_err.h src/nasal_err.cpp | build $(CXX) -std=$(STD) -c -O3 src/nasal_err.cpp -fno-exceptions -fPIC -o build/nasal_err.o -I . build/nasal_gc.o: src/nasal.h src/nasal_gc.h src/nasal_gc.cpp | build - $(CXX) -std=$(STD) -c -O3 src/nasal_gc.cpp -fno-exceptions -fPIC -o build/nasal_gc.o -I . + $(CXX) -std=$(STD) -c -O3 src/nasal_gc.cpp -fno-exceptions -fPIC -o build/nasal_gc.o -I . build/nasal_import.o: \ src/nasal.h\ diff --git a/src/main.cpp b/src/main.cpp index d20d64c..7d9b8fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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"; } } diff --git a/src/nasal_builtin.cpp b/src/nasal_builtin.cpp index a097810..fdc0d0b 100644 --- a/src/nasal_builtin.cpp +++ b/src/nasal_builtin.cpp @@ -1,4 +1,5 @@ #include "nasal_builtin.h" +#include 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 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& vec, usize begin, usize end) { + std::vector bfs; + for(auto i = begin; imark!=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& 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&, usize, usize); void mark_context(std::vector&); void mark_var(std::vector&, var&); void mark_vec(std::vector&, nas_vec&); diff --git a/src/nasal_vm.h b/src/nasal_vm.h index a5f3855..c9ab6d5 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -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 diff --git a/std/lib.nas b/std/lib.nas index e8680c3..ae1e969 100644 --- a/std/lib.nas +++ b/std/lib.nas @@ -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;} } }; diff --git a/test/gc_test.nas b/test/gc_test.nas index 147cc7c..2aa9d04 100644 --- a/test/gc_test.nas +++ b/test/gc_test.nas @@ -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 + ); } \ No newline at end of file