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

Commit f87aed9

Browse files
Modify gc_stats API to be able to select needed ones
Allows to introduce more fields to `Stats` struct in future without compromising performance by calculating extra unnecessary fields. This will prevent `core.memory.GC` API from getting bloated as new stats become desired.
1 parent 54ab96e commit f87aed9

File tree

6 files changed

+87
-26
lines changed

6 files changed

+87
-26
lines changed

src/core/memory.d

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ private
138138
}
139139

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

143143
extern (C) void gc_addRoot( in void* p ) nothrow @nogc;
144144
extern (C) void gc_addRange( in void* p, size_t sz, const TypeInfo ti = null ) nothrow @nogc;
@@ -170,6 +170,12 @@ struct GC
170170
size_t freeSize;
171171
}
172172

173+
/**
174+
* Auto-generated bitflag enum with values of identical names as `Stats`
175+
* struct. Optionally used to specify exact stats to calculate.
176+
*/
177+
mixin(generateFieldEnum!Stats);
178+
173179
/**
174180
* Enables automatic garbage collection behavior if collections have
175181
* previously been suspended by a call to disable. This function is
@@ -677,7 +683,7 @@ struct GC
677683
*/
678684
static Stats stats() nothrow
679685
{
680-
return gc_stats();
686+
return gc_stats(ulong.max);
681687
}
682688

683689
/**
@@ -1167,3 +1173,50 @@ unittest
11671173
int* pint; __delete(pint);
11681174
S* ps; __delete(ps);
11691175
}
1176+
1177+
/**
1178+
For a given struct `S` generated bitflag enum with a value for each of
1179+
struct fields.
1180+
*/
1181+
private string generateFieldEnum(alias S)()
1182+
{
1183+
import core.internal.string;
1184+
1185+
string code = "enum " ~ __traits(identifier, S) ~ "Fields\n{\n";
1186+
ulong shift = 0;
1187+
char[3] buf;
1188+
1189+
foreach (idx, _; S.init.tupleof)
1190+
{
1191+
auto init = "1UL << " ~ unsignedToTempString(shift, buf);
1192+
code ~= __traits(identifier, S.tupleof[idx]) ~ " = " ~ init ~ ",\n";
1193+
++shift;
1194+
}
1195+
1196+
code ~= "}";
1197+
1198+
return code;
1199+
}
1200+
1201+
unittest
1202+
{
1203+
static struct Dummy
1204+
{
1205+
int a, b, c;
1206+
}
1207+
1208+
enum code = generateFieldEnum!Dummy();
1209+
1210+
static assert (code == "enum DummyFields
1211+
{
1212+
a = 1UL << 0,
1213+
b = 1UL << 1,
1214+
c = 1UL << 2,
1215+
}");
1216+
1217+
mixin(code);
1218+
1219+
assert(DummyFields.a == 1);
1220+
assert(DummyFields.b == 2);
1221+
assert(DummyFields.c == 4);
1222+
}

src/gc/gcinterface.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ interface GC
146146
* Retrieve statistics about garbage collection.
147147
* Useful for debugging and tuning.
148148
*/
149-
core.memory.GC.Stats stats() nothrow;
149+
core.memory.GC.Stats stats(ulong fields) nothrow;
150150

151151
/**
152152
* add p to list of roots

src/gc/impl/conservative/gc.d

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,11 +1191,11 @@ class ConservativeGC : GC
11911191
}
11921192

11931193

1194-
core.memory.GC.Stats stats() nothrow
1194+
core.memory.GC.Stats stats(ulong fields) nothrow
11951195
{
11961196
typeof(return) ret;
11971197

1198-
runLocked!(getStatsNoSync, otherTime, numOthers)(ret);
1198+
runLocked!(getStatsNoSync, otherTime, numOthers)(ret, fields);
11991199

12001200
return ret;
12011201
}
@@ -1204,29 +1204,37 @@ class ConservativeGC : GC
12041204
//
12051205
//
12061206
//
1207-
private void getStatsNoSync(out core.memory.GC.Stats stats) nothrow
1207+
private void getStatsNoSync(out core.memory.GC.Stats stats, ulong fields) nothrow
12081208
{
1209-
foreach (pool; gcx.pooltable[0 .. gcx.npools])
1209+
alias Flags = core.memory.GC.StatsFields;
1210+
1211+
if ((fields & Flags.usedSize) || (fields & Flags.freeSize))
12101212
{
1211-
foreach (bin; pool.pagetable[0 .. pool.npages])
1213+
// calculates both if any is requested as it is part of the same
1214+
// iteration process
1215+
1216+
foreach (pool; gcx.pooltable[0 .. gcx.npools])
12121217
{
1213-
if (bin == B_FREE)
1214-
stats.freeSize += PAGESIZE;
1215-
else
1216-
stats.usedSize += PAGESIZE;
1218+
foreach (bin; pool.pagetable[0 .. pool.npages])
1219+
{
1220+
if (bin == B_FREE)
1221+
stats.freeSize += PAGESIZE;
1222+
else
1223+
stats.usedSize += PAGESIZE;
1224+
}
12171225
}
1218-
}
12191226

1220-
size_t freeListSize;
1221-
foreach (n; 0 .. B_PAGE)
1222-
{
1223-
immutable sz = binsize[n];
1224-
for (List *list = gcx.bucket[n]; list; list = list.next)
1225-
freeListSize += sz;
1226-
}
1227+
size_t freeListSize;
1228+
foreach (n; 0 .. B_PAGE)
1229+
{
1230+
immutable sz = binsize[n];
1231+
for (List *list = gcx.bucket[n]; list; list = list.next)
1232+
freeListSize += sz;
1233+
}
12271234

1228-
stats.usedSize -= freeListSize;
1229-
stats.freeSize += freeListSize;
1235+
stats.usedSize -= freeListSize;
1236+
stats.freeSize += freeListSize;
1237+
}
12301238
}
12311239
}
12321240

src/gc/impl/manual/gc.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ class ManualGC : GC
190190
return BlkInfo.init;
191191
}
192192

193-
core.memory.GC.Stats stats() nothrow
193+
core.memory.GC.Stats stats(ulong fields) nothrow
194194
{
195195
return typeof(return).init;
196196
}

src/gc/impl/proto/gc.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class ProtoGC : GC
155155
return BlkInfo.init;
156156
}
157157

158-
core.memory.GC.Stats stats() nothrow
158+
core.memory.GC.Stats stats(ulong fields) nothrow
159159
{
160160
return typeof(return).init;
161161
}

src/gc/proxy.d

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,9 @@ extern (C)
184184
return instance.query( p );
185185
}
186186

187-
core.memory.GC.Stats gc_stats() nothrow
187+
core.memory.GC.Stats gc_stats(ulong fields) nothrow
188188
{
189-
return instance.stats();
189+
return instance.stats(fields);
190190
}
191191

192192
void gc_addRoot( void* p ) nothrow @nogc

0 commit comments

Comments
 (0)