Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Modify gc_stats API to be able to select needed ones
Browse files Browse the repository at this point in the history
  • Loading branch information
thewilsonator committed Nov 17, 2018
1 parent 6f27f55 commit 13420ae
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 27 deletions.
63 changes: 60 additions & 3 deletions src/core/memory.d
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ private
}

extern (C) BlkInfo_ gc_query( void* p ) pure nothrow;
extern (C) GC.Stats gc_stats ( ) nothrow @nogc;
extern (C) GC.Stats gc_stats ( ulong fields ) nothrow @nogc;

extern (C) void gc_addRoot( in void* p ) nothrow @nogc;
extern (C) void gc_addRange( in void* p, size_t sz, const TypeInfo ti = null ) nothrow @nogc;
Expand Down Expand Up @@ -170,6 +170,12 @@ struct GC
size_t freeSize;
}

/**
* Auto-generated bitflag enum with values of identical names as `Stats`
* struct. Optionally used to specify exact stats to calculate.
*/
mixin(generateFieldEnum!Stats);

/**
* Enables automatic garbage collection behavior if collections have
* previously been suspended by a call to disable. This function is
Expand Down Expand Up @@ -674,10 +680,16 @@ struct GC
/**
* Returns runtime stats for currently active GC implementation
* See `core.memory.GC.Stats` for list of available metrics.
*
* Params:
* fields = optional bit flag argument which specifies which stats need
* to be calculated. By default equals to "all fields". If some field
* was not requested via bit flag, its value in returned `Stats` struct
* will be undefined.
*/
static Stats stats() nothrow
static Stats stats(ulong fields = ulong.max) nothrow
{
return gc_stats();
return gc_stats(fields);
}

/**
Expand Down Expand Up @@ -1184,4 +1196,49 @@ unittest
assert(GC.addrOf(y.ptr) == null);
}

/**
For a given struct `S` generated bitflag enum with a value for each of
struct fields.
*/
private string generateFieldEnum(alias S)()
{
import core.internal.string;

string code = "enum " ~ __traits(identifier, S) ~ "Fields\n{\n";
ulong shift = 0;
char[3] buf;

foreach (idx, _; S.init.tupleof)
{
auto init = "1UL << " ~ unsignedToTempString(shift, buf);
code ~= __traits(identifier, S.tupleof[idx]) ~ " = " ~ init ~ ",\n";
++shift;
}

code ~= "}";

return code;
}

unittest
{
static struct Dummy
{
int a, b, c;
}

enum code = generateFieldEnum!Dummy();

static assert (code == "enum DummyFields
{
a = 1UL << 0,
b = 1UL << 1,
c = 1UL << 2,
}");

mixin(code);

assert(DummyFields.a == 1);
assert(DummyFields.b == 2);
assert(DummyFields.c == 4);
}
2 changes: 1 addition & 1 deletion src/gc/gcinterface.d
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ interface GC
* Retrieve statistics about garbage collection.
* Useful for debugging and tuning.
*/
core.memory.GC.Stats stats() nothrow;
core.memory.GC.Stats stats(ulong fields) nothrow;

/**
* add p to list of roots
Expand Down
46 changes: 27 additions & 19 deletions src/gc/impl/conservative/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -1191,11 +1191,11 @@ class ConservativeGC : GC
}


core.memory.GC.Stats stats() nothrow
core.memory.GC.Stats stats(ulong fields) nothrow
{
typeof(return) ret;

runLocked!(getStatsNoSync, otherTime, numOthers)(ret);
runLocked!(getStatsNoSync, otherTime, numOthers)(ret, fields);

return ret;
}
Expand All @@ -1204,29 +1204,37 @@ class ConservativeGC : GC
//
//
//
private void getStatsNoSync(out core.memory.GC.Stats stats) nothrow
private void getStatsNoSync(out core.memory.GC.Stats stats, ulong fields) nothrow
{
foreach (pool; gcx.pooltable[0 .. gcx.npools])
alias Flags = core.memory.GC.StatsFields;

if ((fields & Flags.usedSize) || (fields & Flags.freeSize))
{
foreach (bin; pool.pagetable[0 .. pool.npages])
// calculates both if any is requested as it is part of the same
// iteration process

foreach (pool; gcx.pooltable[0 .. gcx.npools])
{
if (bin == B_FREE)
stats.freeSize += PAGESIZE;
else
stats.usedSize += PAGESIZE;
foreach (bin; pool.pagetable[0 .. pool.npages])
{
if (bin == B_FREE)
stats.freeSize += PAGESIZE;
else
stats.usedSize += PAGESIZE;
}
}
}

size_t freeListSize;
foreach (n; 0 .. B_PAGE)
{
immutable sz = binsize[n];
for (List *list = gcx.bucket[n]; list; list = list.next)
freeListSize += sz;
}
size_t freeListSize;
foreach (n; 0 .. B_PAGE)
{
immutable sz = binsize[n];
for (List *list = gcx.bucket[n]; list; list = list.next)
freeListSize += sz;
}

stats.usedSize -= freeListSize;
stats.freeSize += freeListSize;
stats.usedSize -= freeListSize;
stats.freeSize += freeListSize;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/gc/impl/manual/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ class ManualGC : GC
return BlkInfo.init;
}

core.memory.GC.Stats stats() nothrow
core.memory.GC.Stats stats(ulong fields) nothrow
{
return typeof(return).init;
}
Expand Down
2 changes: 1 addition & 1 deletion src/gc/impl/proto/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class ProtoGC : GC
return BlkInfo.init;
}

core.memory.GC.Stats stats() nothrow
core.memory.GC.Stats stats(ulong fields) nothrow
{
return typeof(return).init;
}
Expand Down
4 changes: 2 additions & 2 deletions src/gc/proxy.d
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ extern (C)
return instance.query( p );
}

core.memory.GC.Stats gc_stats() nothrow
core.memory.GC.Stats gc_stats(ulong fields) nothrow
{
return instance.stats();
return instance.stats(fields);
}

void gc_addRoot( void* p ) nothrow @nogc
Expand Down

0 comments on commit 13420ae

Please sign in to comment.