20,741
edits
m (→Nasal GC Tracking: archive code snippets) |
|||
Line 154: | Line 154: | ||
= Nasal GC Tracking = | = Nasal GC Tracking = | ||
ThorstenB once posted a patch that tracks GC invocations over time (printf) which should be easy to also expose to the property tree and log/plot accordingly. | ThorstenB once posted a patch that tracks GC invocations over time (printf) which should be easy to also expose to the property tree and log/plot accordingly. | ||
Also, it shows "GC pressure" (=symbols/references) per namespace. | Also, it shows "GC pressure" (=symbols/references) per namespace. | ||
Line 169: | Line 168: | ||
with &FGNasalSys::trackGC being registed then. | with &FGNasalSys::trackGC being registed then. | ||
looking at the code, there's something called initGlobals at: http://sourceforge.net/p/flightgear/simgear/ci/next/tree/simgear/nasal/code.c#l161 | looking at the code, there's something called initGlobals at: http://sourceforge.net/p/flightgear/simgear/ci/next/tree/simgear/nasal/code.c#l161 | ||
Line 205: | Line 202: | ||
And then the C++ code can do stuff like fgSetInt(), SG_LOG() etc easily | And then the C++ code can do stuff like fgSetInt(), SG_LOG() etc easily | ||
SimGear: http://codepad.org/ | SimGear: http://codepad.org/ZSGZbMiV/raw.txt | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp">diff --git a/simgear/nasal/code.c b/simgear/nasal/code.c | ||
diff --git a/ | index 2bf4645..61a7ae8 100644 | ||
index | --- a/simgear/nasal/code.c | ||
--- a/ | +++ b/simgear/nasal/code.c | ||
+++ b/ | @@ -22,6 +22,19 @@ void printStackDEBUG(naContext ctx); | ||
@@ - | |||
struct Globals* globals = 0; | |||
+ | +extern unsigned int gRefCount,gObjCount; | ||
+void | + | ||
+ | +void registerGCTracker(TrackGCcb cb) { | ||
+// check if globals is a valid pointer | |||
+if (!globals) { | |||
+fprintf(stderr, "Globals must be set up first!)"); | |||
+return; | |||
+} | +} | ||
+ | + | ||
// | +printf("Registering GC tracking callback!"); | ||
+globals->gc_cb=cb; | |||
+} | |||
+ | |||
static naRef bindFunction(naContext ctx, struct Frame* f, naRef code); | |||
#define ERR(c, msg) naRuntimeError((c),(msg)) | |||
@@ -168,6 +181,8 @@ static void initGlobals() | |||
globals->sem = naNewSem(); | |||
globals->lock = naNewLock(); | |||
+ gObjCount = gRefCount = 0; | |||
+ | |||
globals->allocCount = 256; // reasonable starting value | |||
for(i=0; i<NUM_NASAL_TYPES; i++) | |||
naGC_init(&(globals->pools[i]), i); | |||
diff --git a/simgear/nasal/code.h b/simgear/nasal/code.h | |||
index e7cb3f3..5b0befc 100644 | |||
--- a/simgear/nasal/code.h | |||
+++ b/simgear/nasal/code.h | |||
@@ -41,6 +41,7 @@ struct Globals { | |||
// Garbage collecting allocators: | |||
struct naPool pools[NUM_NASAL_TYPES]; | |||
int allocCount; | |||
+ TrackGCcb gc_cb; | |||
// Dead blocks waiting to be freed when it is safe | |||
void** deadBlocks; | |||
diff --git a/simgear/nasal/gc.c b/simgear/nasal/gc.c | |||
index 5ac9c43..6819d19 100644 | |||
--- a/simgear/nasal/gc.c | |||
+++ b/simgear/nasal/gc.c | |||
@@ -4,6 +4,9 @@ | |||
#define MIN_BLOCK_SIZE 32 | |||
+int gRefCount=0; | |||
+int gObjCount=0; | |||
+ | |||
static void reap(struct naPool* p); | |||
static void mark(naRef r); | |||
@@ -38,6 +41,8 @@ static void garbageCollect() | |||
int i; | |||
struct Context* c; | |||
globals->allocCount = 0; | |||
+ // https://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg31762.html | |||
+ gObjCount = gRefCount=0; | |||
c = globals->allContexts; | |||
while(c) { | |||
for(i=0; i<NUM_NASAL_TYPES; i++) | |||
@@ -53,6 +58,14 @@ static void garbageCollect() | |||
c = c->nextAll; | |||
} | |||
+ // check if there is a GC callback registered, if so call it | |||
+ | |||
+ TrackGCcb cb = globals->gc_cb; | |||
+ if(cb) { | |||
+ // callback is registered, so call it | |||
+ (*cb) (gRefCount, gObjCount); | |||
+ } | |||
+ | |||
mark(globals->save); | |||
mark(globals->save_hash); | |||
mark(globals->symbols); | |||
@@ -242,6 +255,7 @@ static void markvec(naRef r) | |||
static void mark(naRef r) | |||
{ | { | ||
int i; | |||
+ gRefCount ++; | |||
if(IS_NUM(r) || IS_NIL(r)) | |||
return; | |||
@@ -249,6 +263,8 @@ static void mark(naRef r) | |||
if(PTR(r).obj->mark == 1) | |||
return; | |||
+ | + gObjCount++; | ||
+ | |||
+ | + | ||
// | PTR(r).obj->mark = 1; | ||
switch(PTR(r).obj->type) { | |||
case T_VEC: markvec(r); break; | |||
@@ - | diff --git a/simgear/nasal/nasal.h b/simgear/nasal/nasal.h | ||
index 8b6b2c9..48ed460 100644 | |||
--- a/simgear/nasal/nasal.h | |||
+++ b/simgear/nasal/nasal.h | |||
@@ -44,6 +44,10 @@ void* naGetUserData(naContext c) GCC_PURE; | |||
// run GC now (may block) | |||
void naGC(); | |||
+struct Globals; | |||
+typedef void (*TrackGCcb) (unsigned int refs, unsigned int objects); | |||
+void registerGCTracker(TrackGCcb cb); | |||
+ | |||
// "Save" this object in the context, preventing it (and objects | |||
// referenced by it) from being garbage collected. | |||
</syntaxhighlight> | </syntaxhighlight> | ||