The function gc_stats() in gc.d from the Tango runtime is not exposed to the user. This patch exposes this function as GC.stats() in tango.core.Memory. The GCStats struct is made public, too.
Additionally, the GCStats struct is extended by 3 additional members: gc_count tells the user how many GC cycles happened so far, mark_time how long the GC spent in the mark phase, and sweep_time how long it spent in the sweep phase. The changes in gxc.d are to fill those new members.
(Both things are kind of unrelated, but I didn't split the patch/tickets because they are so trivial.)
Patch against Tango svn follows:
Index: lib/common/tango/core/Memory.d
===================================================================
--- lib/common/tango/core/Memory.d (Revision 4762)
+++ lib/common/tango/core/Memory.d (Arbeitskopie)
@@ -47,6 +47,20 @@
extern (C) void gc_removeRoot( void* p );
extern (C) void gc_removeRange( void* p );
+
+ struct GCStats
+ {
+ size_t poolsize; // total size of pool
+ size_t usedsize; // bytes allocated
+ size_t freeblocks; // number of blocks marked FREE
+ size_t freelistsize; // total of memory on free lists
+ size_t pageblocks; // number of blocks marked PAGE
+ size_t gc_count; // number of GC runs
+ ulong mark_time; // microseconds spend in mark-phase
+ ulong sweep_time; // microseconds spend in sweep-phase
+ }
+
+ extern (C) GCStats gc_stats();
}
@@ -502,4 +516,11 @@
newcap = newext > newcap ? newext : newcap; // just to handle overflows
return newcap;
}
+
+ alias .GCStats GCStats;
+
+ static GCStats stats() {
+ return gc_stats();
+ }
}
+
Index: lib/gc/basic/rt/basicgc/gcx.d
===================================================================
--- lib/gc/basic/rt/basicgc/gcx.d (Revision 4762)
+++ lib/gc/basic/rt/basicgc/gcx.d (Arbeitskopie)
@@ -55,6 +55,7 @@
debug(THREADINVARIANT) private import tango.stdc.posix.pthread;
debug(PRINTF) private import tango.stdc.posix.pthread : pthread_self, pthread_t;
debug private import tango.stdc.stdio : printf;
+private import tango.time.StopWatch? : StopWatch?;
version (GNU)
{
@@ -1337,6 +1338,10 @@
stats.poolsize = psize;
stats.usedsize = bsize - flsize;
stats.freelistsize = flsize;
+
+ stats.gc_count = gcx.stats_gc_count;
+ stats.mark_time = gcx.stats_mark_time;
+ stats.sweep_time = gcx.stats_sweep_time;
}
}
@@ -1434,7 +1439,12 @@
List *bucket[B_MAX]; // free list for each size
+ // see rt.basicgc.gcstats.GCStats
+ size_t stats_gc_count;
+ ulong stats_mark_time;
+ ulong stats_sweep_time;
+
void initialize()
{ int dummy;
@@ -2262,6 +2272,11 @@
debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n");
+ stats_gc_count++;
+
+ StopWatch? timer;
+ timer.start();
+
thread_suspendAll();
p_cache = null;
@@ -2394,6 +2409,9 @@
thread_resumeAll();
+ stats_mark_time += timer.microsec;
+ timer.start();
+
// Free up everything not marked
debug(COLLECT_PRINTF) printf("\tfree'ing\n");
size_t freedpages = 0;
@@ -2551,6 +2569,8 @@
}
}
+ stats_sweep_time += timer.microsec;
+
debug(COLLECT_PRINTF) printf("recovered pages = %d\n", recoveredpages);
debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, npools);
Index: lib/gc/basic/rt/basicgc/gcstats.d
===================================================================
--- lib/gc/basic/rt/basicgc/gcstats.d (Revision 4762)
+++ lib/gc/basic/rt/basicgc/gcstats.d (Arbeitskopie)
@@ -35,4 +35,7 @@
size_t freeblocks; // number of blocks marked FREE
size_t freelistsize; // total of memory on free lists
size_t pageblocks; // number of blocks marked PAGE
+ size_t gc_count; // number of GC runs
+ ulong mark_time; // microseconds spent in mark-phase
+ ulong sweep_time; // microseconds spent in sweep-phase
}