optimize gc

This commit is contained in:
ValKmjolnir 2022-12-07 01:17:40 +08:00
parent de524938cf
commit cb547499ac
4 changed files with 52 additions and 58 deletions

View File

@ -58,8 +58,8 @@ test:nasal
@ ./nasal -d test/life.nas @ ./nasal -d test/life.nas
@ ./nasal -t test/loop.nas @ ./nasal -t test/loop.nas
@ ./nasal -t -d test/mandel.nas @ ./nasal -t -d test/mandel.nas
@ ./nasal -t -d test/mandelbrot.nas @ ./nasal -t test/mandelbrot.nas
@ ./nasal -t -d test/md5.nas @ ./nasal -t test/md5.nas
@ ./nasal -t -d test/md5compare.nas @ ./nasal -t -d test/md5compare.nas
-@ ./nasal -d test/module_test.nas -@ ./nasal -d test/module_test.nas
@ ./nasal -e test/nasal_test.nas @ ./nasal -e test/nasal_test.nas

View File

@ -16,7 +16,6 @@
#include <iomanip> #include <iomanip>
#include <vector> #include <vector>
#include <queue>
#include <unordered_map> #include <unordered_map>
#include <chrono> #include <chrono>
@ -219,24 +218,15 @@ struct nas_co {
u32 pc; u32 pc;
var* top; var* top;
var* canary; var* canary=stack+STACK_DEPTH-1;
var* localr; var* localr;
var* memr; var* memr;
var funcr; var funcr;
var upvalr; var upvalr;
u32 status; u32 status;
nas_co(): nas_co() {
pc(0),top(stack), clear();
canary(stack+STACK_DEPTH-1),
localr(nullptr),
memr(nullptr),
funcr({vm_nil,(f64)0}),
upvalr({vm_nil,(f64)0}),
status(nas_co::suspended) {
for(u32 i=0;i<STACK_DEPTH;++i) {
stack[i]={vm_nil,(f64)0};
}
} }
void clear() { void clear() {
for(u32 i=0;i<STACK_DEPTH;++i) { for(u32 i=0;i<STACK_DEPTH;++i) {
@ -248,6 +238,7 @@ struct nas_co {
top=stack; top=stack;
status=nas_co::suspended; status=nas_co::suspended;
funcr={vm_nil,(f64)0}; funcr={vm_nil,(f64)0};
upvalr={vm_nil,(f64)0};
} }
}; };
@ -488,7 +479,7 @@ struct gc {
std::vector<var> strs; // reserved address for const vm_str std::vector<var> strs; // reserved address for const vm_str
std::vector<var> env_argv; // command line arguments std::vector<var> env_argv; // command line arguments
std::vector<nas_val*> memory; // gc memory std::vector<nas_val*> memory; // gc memory
std::queue<nas_val*> unused[gc_tsize]; // gc free list std::vector<nas_val*> unused[gc_tsize]; // gc free list
/* values for analysis */ /* values for analysis */
u64 size[gc_tsize]; u64 size[gc_tsize];
@ -517,28 +508,28 @@ struct gc {
/* gc functions */ /* gc functions */
void gc::mark() { void gc::mark() {
std::queue<var> bfs; std::vector<var> bfs;
// scan coroutine process stack when coroutine ptr is not null // scan coroutine process stack when coroutine ptr is not null
// scan main process stack when coroutine ptr is null // scan main process stack when coroutine ptr is null
// this scan process must execute because when running coroutine, // this scan process must execute because when running coroutine,
// the nas_co related to it will not update it's context(like `top`) until the coroutine suspends or exits. // the nas_co related to it will not update it's context(like `top`) until the coroutine suspends or exits.
for(var* i=stack;i<=top;++i) { for(var* i=stack;i<=top;++i) {
bfs.push(*i); bfs.push_back(*i);
} }
bfs.push(funcr); bfs.push_back(funcr);
bfs.push(upvalr); bfs.push_back(upvalr);
bfs.push(temp); bfs.push_back(temp);
if (cort) { // scan main process stack if (cort) { // scan main process stack
for(var* i=mctx.stack;i<=mctx.top;++i) { for(var* i=mctx.stack;i<=mctx.top;++i) {
bfs.push(*i); bfs.push_back(*i);
} }
bfs.push(mctx.funcr); bfs.push_back(mctx.funcr);
bfs.push(mctx.upvalr); bfs.push_back(mctx.upvalr);
} }
while(!bfs.empty()) { while(!bfs.empty()) {
var tmp=bfs.front(); var tmp=bfs.back();
bfs.pop(); bfs.pop_back();
if (tmp.type<=vm_num || tmp.val.gcobj->mark) { if (tmp.type<=vm_num || tmp.val.gcobj->mark) {
continue; continue;
} }
@ -546,32 +537,32 @@ void gc::mark() {
switch(tmp.type) { switch(tmp.type) {
case vm_vec: case vm_vec:
for(auto& i:tmp.vec().elems) { for(auto& i:tmp.vec().elems) {
bfs.push(i); bfs.push_back(i);
} }
break; break;
case vm_hash: case vm_hash:
for(auto& i:tmp.hash().elems) { for(auto& i:tmp.hash().elems) {
bfs.push(i.second); bfs.push_back(i.second);
} }
break; break;
case vm_func: case vm_func:
for(auto& i:tmp.func().local) { for(auto& i:tmp.func().local) {
bfs.push(i); bfs.push_back(i);
} }
for(auto& i:tmp.func().upval) { for(auto& i:tmp.func().upval) {
bfs.push(i); bfs.push_back(i);
} }
break; break;
case vm_upval: case vm_upval:
for(auto& i:tmp.upval().elems) { for(auto& i:tmp.upval().elems) {
bfs.push(i); bfs.push_back(i);
} }
break; break;
case vm_co: case vm_co:
bfs.push(tmp.co().funcr); bfs.push_back(tmp.co().funcr);
bfs.push(tmp.co().upvalr); bfs.push_back(tmp.co().upvalr);
for(var* i=tmp.co().stack;i<=tmp.co().top;++i) { for(var* i=tmp.co().stack;i<=tmp.co().top;++i) {
bfs.push(*i); bfs.push_back(*i);
} }
break; break;
} }
@ -582,7 +573,7 @@ void gc::sweep() {
for(auto i:memory) { for(auto i:memory) {
if (i->mark==GC_UNCOLLECTED) { if (i->mark==GC_UNCOLLECTED) {
i->clear(); i->clear();
unused[i->type-vm_str].push(i); unused[i->type-vm_str].push_back(i);
i->mark=GC_COLLECTED; i->mark=GC_COLLECTED;
} else if (i->mark==GC_FOUND) { } else if (i->mark==GC_FOUND) {
i->mark=GC_UNCOLLECTED; i->mark=GC_UNCOLLECTED;
@ -596,7 +587,7 @@ void gc::extend(u8 type) {
for(u32 i=0;i<incr[index];++i) { for(u32 i=0;i<incr[index];++i) {
nas_val* tmp=new nas_val(type); nas_val* tmp=new nas_val(type);
memory.push_back(tmp); memory.push_back(tmp);
unused[index].push(tmp); unused[index].push_back(tmp);
} }
} }
@ -612,7 +603,7 @@ void gc::init(const std::vector<string>& s,const std::vector<string>& argv) {
for(u32 j=0;j<ini[i];++j) { for(u32 j=0;j<ini[i];++j) {
nas_val* tmp=new nas_val(i+vm_str); nas_val* tmp=new nas_val(i+vm_str);
memory.push_back(tmp); memory.push_back(tmp);
unused[i].push(tmp); unused[i].push_back(tmp);
} }
} }
cort=nullptr; cort=nullptr;
@ -638,9 +629,7 @@ void gc::clear() {
} }
memory.clear(); memory.clear();
for(u8 i=0;i<gc_tsize;++i) { for(u8 i=0;i<gc_tsize;++i) {
while(!unused[i].empty()) { unused[i].clear();
unused[i].pop();
}
} }
for(auto& i:strs) { for(auto& i:strs) {
delete i.val.gcobj; delete i.val.gcobj;
@ -651,7 +640,7 @@ void gc::clear() {
void gc::info() { void gc::info() {
const char* name[]={"str ","vec ","hash ","func ","upval","obj ","co "}; const char* name[]={"str ","vec ","hash ","func ","upval","obj ","co "};
std::cout<<"\ngarbage collector info (gc count|alloc count|memory size)\n"; std::clog<<"\ngarbage collector info (gc count|alloc count|memory size)\n";
u32 maxlen=0; u32 maxlen=0;
for(u8 i=0;i<gc_tsize;++i) { for(u8 i=0;i<gc_tsize;++i) {
u32 len=std::to_string(gcnt[i]).length(); u32 len=std::to_string(gcnt[i]).length();
@ -665,15 +654,15 @@ void gc::info() {
for(u8 i=0;i<gc_tsize;++i) { for(u8 i=0;i<gc_tsize;++i) {
if (gcnt[i] || acnt[i] || ini[i] || size[i]) { if (gcnt[i] || acnt[i] || ini[i] || size[i]) {
total+=gcnt[i]; total+=gcnt[i];
std::cout<<" "<<name[i]<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<gcnt[i]; std::clog<<" "<<name[i]<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<gcnt[i];
std::cout<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<acnt[i]; std::clog<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<acnt[i];
std::cout<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<ini[i]+size[i]*incr[i]<<" (+"<<size[i]<<")\n"; std::clog<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<ini[i]+size[i]*incr[i]<<" (+"<<size[i]<<")\n";
} }
} }
double t=worktime*1.0/1000000000; // seconds double t=worktime*1.0/1000000000; // seconds
std::cout<<" time | "<<(t<0.1? t*1000:t)<<(t<0.1? " ms\n":" s\n"); std::clog<<" time | "<<(t<0.1? t*1000:t)<<(t<0.1? " ms\n":" s\n");
if (total) { if (total) {
std::cout<<" avg | "<<t/total*1000<<" ms\n"; std::clog<<" avg | "<<t/total*1000<<" ms\n";
} }
} }
@ -690,9 +679,9 @@ var gc::alloc(u8 type) {
if (unused[index].empty()) { if (unused[index].empty()) {
extend(type); extend(type);
} }
var ret={type,unused[index].front()}; var ret={type,unused[index].back()};
ret.val.gcobj->mark=GC_UNCOLLECTED; ret.val.gcobj->mark=GC_UNCOLLECTED;
unused[index].pop(); unused[index].pop_back();
return ret; return ret;
} }

View File

@ -73,10 +73,11 @@ println("coroutine state:\e[91m ",coroutine.status(co),"\e[0m");
println("ok"); println("ok");
# pressure test # pressure test
for(var t=0;t<5;t+=1){ for(var t=0;t<10;t+=1){
var productor=func(){ var productor=func(){
for(var i=0;;i+=1) while(1){
coroutine.yield(i); coroutine.yield(i);
}
} }
var total=1000; # ms var total=1000; # ms
var co=coroutine.create(productor); var co=coroutine.create(productor);
@ -86,14 +87,16 @@ for(var t=0;t<5;t+=1){
var bar=process_bar.high_resolution_bar(40); var bar=process_bar.high_resolution_bar(40);
var consumer=func(){ var consumer=func(){
counter+=1; counter+=1;
for(var i=0;i<5;i+=1) for(var i=0;i<t+1;i+=1)
coroutine.resume(co); coroutine.resume(co);
var rate=(tm.elapsedMSec()+1)/total; if(counter-int(counter/1000)*1000==0){
print(" ",bar.bar(rate)," ",int(rate*100),"% | ",counter," tasks \r"); var rate=(tm.elapsedMSec()+1)/total;
print(" ",bar.bar(rate)," ",int(rate*100),"% | ",str(counter)," tasks in ",t+1," \r");
}
} }
tm.stamp(); tm.stamp();
while(tm.elapsedMSec()<total) while(tm.elapsedMSec()<total)
consumer(); consumer();
println(); println(" ",bar.bar(1)," 100% | ",str(counter)," tasks in ",t+1," ");
} }

View File

@ -1,14 +1,16 @@
import.stl.sort; import.stl.sort;
import.stl.process_bar; import.stl.process_bar;
for(var i=0;i<3910;i+=1){ for(var i=0;i<1954;i+=1){
runtime.gc.extend("str"); runtime.gc.extend("str");
}
for(var i=0;i<3907;i+=1){
runtime.gc.extend("vec"); runtime.gc.extend("vec");
} }
var test=func(n){ var test=func(n){
var ts=maketimestamp(); var ts=maketimestamp();
var bar=process_bar.high_resolution_bar(50); var bar=process_bar.high_resolution_bar(40);
var color=[]; var color=[];
var message=[]; var message=[];
@ -21,10 +23,10 @@ var test=func(n){
message[i]=[i+n*10,"message "~i]; message[i]=[i+n*10,"message "~i];
if((i-last_step)/n>1/100){ if((i-last_step)/n>1/100){
last_step=i; last_step=i;
print(bar.bar((i+1)/n)~" "~str(int((i+1)/n*100))~"% \r"); print(" ",bar.bar((i+1)/n)~" "~str(int((i+1)/n*100))~"% \r");
} }
} }
print(bar.bar((i+1)/n)~" 100% | ",ts.elapsedMSec()/1000," s | "); print(" ",bar.bar((i+1)/n)~" 100% | ",ts.elapsedMSec()/1000," s | ");
var mess=func(vec){ var mess=func(vec){
var s=size(vec); var s=size(vec);