⚡ optimize gc
This commit is contained in:
parent
de524938cf
commit
cb547499ac
4
makefile
4
makefile
|
@ -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
|
||||||
|
|
81
nasal_gc.h
81
nasal_gc.h
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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," ");
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue